· 10 years ago · Sep 11, 2016, 12:10 PM
1package me.catcoder.cbrel.data;
2
3import java.sql.Connection;
4import java.sql.PreparedStatement;
5import java.sql.ResultSet;
6import java.sql.SQLException;
7import java.util.LinkedList;
8import java.util.List;
9
10
11public class Database{
12 private DatabaseCore core;
13
14 /**
15 * Creates a new database and validates its connection.
16 *
17 * If the connection is invalid, this will throw a ConnectionException.
18 * @param core The core for the database, either MySQL or SQLite.
19 * @throws ConnectionException If the connection was invalid
20 */
21 public Database(DatabaseCore core) throws ConnectionException{
22 try{
23 try{
24 if(!core.getConnection().isValid(10)){
25 throw new ConnectionException("Database doesn not appear to be valid!");
26 }
27 }
28 catch(AbstractMethodError e){
29 //You don't need to validate this core.
30 }
31 }
32 catch(SQLException e){
33 throw new ConnectionException(e.getMessage());
34 }
35
36 this.core = core;
37 }
38
39 /**
40 * Returns the database core object, that this database runs on.
41 * @return the database core object, that this database runs on.
42 */
43 public DatabaseCore getCore(){
44 return core;
45 }
46
47 /**
48 * Fetches the connection to this database for querying. Try to avoid doing this in the main thread.
49 * @return Fetches the connection to this database for querying.
50 */
51 public Connection getConnection(){
52 return core.getConnection();
53 }
54
55 /**
56 * Executes the given statement either immediately, or soon.
57 * @param query The query
58 * @param objs The string values for each ? in the given query.
59 */
60 public void execute(String query, Object...objs){
61 BufferStatement bs = new BufferStatement(query, objs);
62 core.queue(bs);
63 }
64
65 /**
66 * Returns true if the table exists
67 * @param table The table to check for
68 * @return True if the table is found
69 */
70 public boolean hasTable(String table) throws SQLException{
71 ResultSet rs = getConnection().getMetaData().getTables(null, null, "%", null);
72 while(rs.next()){
73 if(table.equalsIgnoreCase(rs.getString("TABLE_NAME"))){
74 rs.close();
75 return true;
76 }
77 }
78 rs.close();
79 return false;
80 }
81
82 /**
83 * Closes the database
84 */
85 public void close(){
86 this.core.close();
87 }
88
89 /**
90 * Returns true if the given table has the given column
91 * @param table The table
92 * @param column The column
93 * @return True if the given table has the given column
94 * @throws SQLException If the database isn't connected
95 */
96 public boolean hasColumn(String table, String column) throws SQLException{
97 if(!hasTable(table)) return false;
98
99 String query = "SELECT * FROM " + table + " LIMIT 0,1";
100 try{
101 PreparedStatement ps = this.getConnection().prepareStatement(query);
102 ResultSet rs = ps.executeQuery();
103
104 while(rs.next()){
105 rs.getString(column); //Throws an exception if it can't find that column
106 return true;
107 }
108 }
109 catch(SQLException e){
110 return false;
111 }
112 return false; //Uh, wtf.
113 }
114
115 /**
116 * Represents a connection error, generally when the server
117 * can't connect to MySQL or something.
118 */
119 public static class ConnectionException extends Exception{
120 private static final long serialVersionUID = 8348749992936357317L;
121
122 public ConnectionException(String msg){
123 super(msg);
124 }
125 }
126
127 /**
128 * Copies the contents of this database into the given database.
129 * Does not delete the contents of this database, or change any
130 * settings. This may take a long time, and will print out
131 * progress reports to System.out
132 *
133 * This method does not create the tables in the new database.
134 * You need to do that yourself.
135 *
136 * @param db The database to copy data to
137 * @throws SQLException if an error occurs.
138 */
139 public void copyTo(Database db) throws SQLException{
140 ResultSet rs = getConnection().getMetaData().getTables(null, null, "%", null);
141 List<String> tables = new LinkedList<String>();
142 while(rs.next()){
143 tables.add(rs.getString("TABLE_NAME"));
144 }
145 rs.close();
146
147 core.flush();
148
149 //For each table
150 for(String table : tables){
151 if(table.toLowerCase().startsWith("sqlite_autoindex_")) continue;
152 System.out.println("Copying " + table);
153 //Wipe the old records
154 db.getConnection().prepareStatement("DELETE FROM " + table).execute();
155
156 //Fetch all the data from the existing database
157 rs = getConnection().prepareStatement("SELECT * FROM " + table).executeQuery();
158
159 int n = 0;
160
161 //Build the query
162 String query = "INSERT INTO " + table + " VALUES (";
163 //Append another placeholder for the value
164 query += "?";
165 for(int i = 2; i <= rs.getMetaData().getColumnCount(); i++){
166 //Add the rest of the placeholders and values. This is so we have (?, ?, ?) and not (?, ?, ?, ).
167 query += ", ?";
168 }
169 //End the query
170 query += ")";
171
172 PreparedStatement ps = db.getConnection().prepareStatement(query);
173 while(rs.next()){
174 n++;
175
176 for(int i = 1; i <= rs.getMetaData().getColumnCount(); i++){
177 ps.setObject(i, rs.getObject(i));
178 }
179
180 ps.addBatch();
181
182 if(n % 100 == 0){
183 ps.executeBatch();
184 System.out.println(n + " запиÑей Ñкопировано...");
185 }
186 }
187 ps.executeBatch();
188 //Close the resultset of that table
189 rs.close();
190 }
191 //Success!
192 db.getConnection().close();
193
194
195 this.getConnection().close();
196 }
197}