source: gs2-extensions/tipple-bridge/trunk/src/src/main/java/sqlCli.java@ 34901

Last change on this file since 34901 was 34901, checked in by su41, 3 years ago

Added a new sql query to test. It works fine but it's not 100% complete query. Also removed the option of projectId since we'll just pull everything from all projects, and let Greenstone handle sorting that out

File size: 9.7 KB
Line 
1import com.mysql.cj.exceptions.MysqlErrorNumbers;
2import picocli.CommandLine;
3import picocli.CommandLine.Command;
4import picocli.CommandLine.Option;
5import picocli.CommandLine.Parameters;
6
7import java.sql.*;
8import java.util.HashMap;
9import com.google.gson.Gson;
10import java.io.FileWriter;
11import java.util.concurrent.Callable;
12
13/*
14TODO:
15
16 */
17
18//-u su41Tipple -p --port 3306 --dbname koicarp_test
19//@/home/su41/configFileTest
20
21/*
22The mixinStandardHelpOptions = true adds in --help and --version options
23 */
24@Command (name="sqlCli", description = "Arguments for database connection", mixinStandardHelpOptions = true)
25public class sqlCli implements Callable<Integer> {
26
27 //our cli arguments
28 @Option(names = {"-u", "--user"}, description = "The user name",
29 required = true)
30 String userName;
31
32 //interactive allows the user to omit the argument value and instead enter it as a prompt
33 /*
34 NOTE: if you are running an interactive option on an IDE, most likely the IDE will be using
35 the javaw.exe library which tries to mimic the terminal.
36 The point is that interactive option would usually make whatever you enter hidden (it doesn't
37 echo back) but on the IDE it will echo back.
38 */
39 @Option(names = {"-p", "--password"}, description = "User's password", interactive = true,
40 required = true)
41 String password;
42
43 @Option(names = {"--port"}, description="Port number", defaultValue="3306")
44 int port;
45
46 @Option(names = {"--dbname"}, description="Name of the database", defaultValue="koicarp_test")
47 String dbName;
48
49 @Option(names = {"--host"}, description = "Type of host e.g. localhost ",
50 required = true, defaultValue = "localhost")
51 String host;
52
53 /*
54 this parameter can be read in at any point on the options line.
55 but that's only because it's the only parameter at the moment.
56 If we add more parameters, will have to start indexing
57 https://picocli.info/quick-guide.html#_options_and_parameters
58 */
59 @Parameters(description = "Name of the output JSON file. E.g. yourFileName.json")
60 String jsonOutputFile;
61
62 public Integer call(){
63 //if it doesn't end with ...
64 if(!jsonOutputFile.endsWith(".json")){
65 System.out.println("Invalid file format.");
66 System.out.println("The file to save the output to must be a .json file.");
67 //exit code other than 0 means it's not fine.
68 return 1;
69 }
70 //else we're good to go.
71 // databaseConnect(userName, password, port, dbName, projectID, jsonOutputFile, host);
72 int status = databaseConnect(userName, password, port, dbName, jsonOutputFile, host);
73 return status;
74 }
75
76 public static void main(String... args) {
77 int exitCode = new CommandLine(new sqlCli()).execute(args);
78 System.exit(exitCode);
79 }
80
81
82 private static int databaseConnect(String user, String pass, int port, String dbName,
83 String fileName, String host){
84 Connection conn;
85 Statement stmt;
86 //return status for code to send back to commandLine.execute
87 int returnStatus = 0;
88 // String dbUrl = "jdbc:mysql://localhost:" + port +"/"+ dbName;
89
90 //TODO: are we changing / putting the type of database into a variable too?
91 String dbUrl = "jdbc:mysql://" + host + ":" + port +"/"+ dbName;
92
93 //originally in the try ()
94 // FileWriter file = new FileWriter("tippleData.json")
95 System.out.println("Saving output to:");
96 System.out.println(" " + fileName);
97
98 try (FileWriter file = new FileWriter(fileName)){
99 //register the jdbc driver
100 Class.forName("com.mysql.cj.jdbc.Driver");
101 //opening the connection
102 System.out.println("Connecting to database:");
103 System.out.println(" " + dbUrl);
104
105 conn = DriverManager.getConnection(dbUrl, user, pass);
106
107 //create and execute query
108 stmt = conn.createStatement();
109 //remember to put in the projectId parameter instead of hardcoding it
110
111 /*
112 if we get up to the point where we allow boundary setting, i.e user specifies
113 between x and y number of records
114 could use an if statement to check
115 if the paramter exists or not, if it does then run a statement with those x and y
116 if not, then run a different statement without them
117 */
118
119 // String sql = "SELECT name, id, typeId, created from td_ContentItem where projectId="+projectID;
120
121 String sql = "SELECT cItem.name, cItem.created, mFile.path\n" +
122 "FROM td_ManagedFile AS mFile, td_ContentItem AS cItem, td_ContentItem_MediaItem AS cMediaItem, td_MediaItem AS mItem\n" +
123 "WHERE\n" +
124 "cItem.id = cMediaItem.contentItemId \n" +
125 "and cMediaItem.mediaItemId = mItem.id\n" +
126 "And mItem.fileId = mFile.id\n" +
127 "ORDER BY mFile.projectId;\n";
128 ResultSet myResult = stmt.executeQuery(sql);
129 ResultSetMetaData resultMetaData = myResult.getMetaData();
130
131 int dbColumn = resultMetaData.getColumnCount();
132 System.out.println(" Number of columns in table retrieved: " + dbColumn);
133
134 //create gson object and have the file write the opening bracket for valid json
135 Gson myGSon = new Gson();
136 file.write("[");
137
138 while(myResult.next()){
139 //string/object as key/value pair
140 HashMap<String, Object> dbRow = new HashMap<String, Object>(dbColumn);
141
142 for(int i = 1; i <= dbColumn; i++){
143 /*
144 doing checking this way could mean we have to have a case
145 for every data type,
146 if a data type changes in the database that's probably fine, but
147 if a new data type is sent in, we'll have update the statements
148 */
149 /*
150 Without this kind of check though, the output would throw a pretty nasty
151 warning about illegal reflective access. Though it would still print the
152 date out fine. The warning:
153
154 WARNING: An illegal reflective access operation has occurred
155 WARNING: Illegal reflective access by com.google.gson.internal.bind.ReflectiveTypeAdapterFactory (file:/home/su41/.gradle/caches/modules-2/files-2.1/com.google.code.gson/gson/2.7/751f548c85fa49f330cecbb1875893f971b33c4e/gson-2.7.jar) to field java.time.LocalDateTime.date
156 WARNING: Please consider reporting this to the maintainers of com.google.gson.internal.bind.ReflectiveTypeAdapterFactory
157 WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
158 WARNING: All illegal access operations will be denied in a future release
159 */
160 if(resultMetaData.getColumnTypeName(i).equals("DATETIME")){
161 dbRow.put(resultMetaData.getColumnName(i), myResult.getDate(i));
162 }
163 else{
164 dbRow.put(resultMetaData.getColumnName(i), myResult.getObject(i));
165 }
166 }
167 String dbRowAsJson = myGSon.toJson(dbRow);
168
169 //printing statements for checking output
170 // System.out.println("As normal: " + dbRow);
171 // System.out.println("====");
172 //System.out.println("As JSON: " + anObject);
173
174 //saving to json file
175
176 file.write(dbRowAsJson);
177
178 //Adding commas between each row that we write to our file, as we need it to be valid json
179 if(!myResult.isLast()){
180 file.write(",");
181 }
182 }
183 //write the closing bracket, and flush the writer
184 file.write("]");
185 file.flush();
186 file.close();
187 //System.out.println(myList);
188 System.out.println("Closing connection...");
189 myResult.close();
190 stmt.close();
191 conn.close();
192 System.out.println("Connection closed");
193 }
194 catch(SQLException sqlError){
195 // looking at the sql error code is good for debugging.
196 // can ref: https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-error-sqlstates.html
197 // to see what they're for
198
199 // System.out.println("MySQL error code: " + sqlError.getErrorCode());
200
201
202 //prints out the error message from sql, then check to see which error code
203 // came back and what the code matches.
204 // if it's access denied, usually something to do with username, password or db name
205 System.out.println(sqlError.getMessage());
206
207 if(sqlError.getErrorCode() == MysqlErrorNumbers.ER_ACCESS_DENIED_ERROR){
208 System.out.println("Error with database credentials. Double check your: ");
209 System.out.println(" -'Username'");
210 System.out.println(" -'Password' ");
211 }
212
213 if(sqlError.getErrorCode() == MysqlErrorNumbers.ER_DBACCESS_DENIED_ERROR){
214 System.out.println("Error with database credentials. Double check your: ");
215 System.out.println(" -'Database name' ");
216 }
217 returnStatus = 1;
218
219 }
220 catch(Exception e){
221 //catch for class.name
222 e.printStackTrace();
223 //print out wrong username or password instead of the stack trace?
224 System.out.println("encountered error");
225 returnStatus = 2;
226 }
227 return returnStatus;
228 }
229}
Note: See TracBrowser for help on using the repository browser.