OSDN Git Service

d048680b257ac4d8255066a4e18e1a5d2abf0b75
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / sql / DatabaseConnection.java
1 /*
2  * This file is part of NixNote/NeighborNote 
3  * Copyright 2009 Randy Baumgarte
4  * Copyright 2013 Yuki Takahashi
5  * 
6  * This file may be licensed under the terms of of the
7  * GNU General Public License Version 2 (the ``GPL'').
8  *
9  * Software distributed under the License is distributed
10  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
11  * express or implied. See the GPL for the specific language
12  * governing rights and limitations.
13  *
14  * You should have received a copy of the GPL along with this
15  * program. If not, go to http://www.gnu.org/licenses/gpl.html
16  * or write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19 */
20 package cx.fbn.nevernote.sql;
21
22 import java.io.File;
23 import java.sql.Connection;
24 import java.sql.DriverManager;
25 import java.sql.SQLException;
26
27 import cx.fbn.nevernote.Global;
28 import cx.fbn.nevernote.sql.driver.NSqlQuery;
29 import cx.fbn.nevernote.utilities.ApplicationLogger;
30
31
32 public class DatabaseConnection {
33         // Table helpers
34         private WordsTable                                      wordsTable;
35         private TagTable                                        tagTable;
36         private NotebookTable                           notebookTable;
37         private NoteTable                                       noteTable;
38         private DeletedTable                            deletedTable;
39         private SavedSearchTable                        searchTable;
40         private WatchFolderTable                        watchFolderTable;
41         private InvalidXMLTable                         invalidXMLTable;
42         private LinkedNotebookTable                     linkedNotebookTable;
43         private SharedNotebookTable                     sharedNotebookTable;
44         private InkImagesTable                          inkImagesTable;
45         private SyncTable                                       syncTable;
46         private SystemIconTable                         systemIconTable;
47         private HistoryTable historyTable;
48         private ExcludedTable excludedTable;
49         private StaredTable staredTable;
50         
51         private final ApplicationLogger         logger;
52         private Connection                                      conn;
53         private Connection                                      indexConn;
54         private Connection                                      resourceConn;
55         private Connection behaviorConn;
56         
57         int throttle;
58         int id;
59
60         public DatabaseConnection(ApplicationLogger l, String url, String iurl, String rurl, String burl, String userid, String password, String cypherPassword, int throttle) {
61                 logger = l;
62                 this.throttle = throttle;
63                 dbSetup(url, iurl, rurl, burl, userid, password, cypherPassword);
64         }
65         
66         private void setupTables() {
67                 tagTable = new TagTable(logger, this);
68                 notebookTable = new NotebookTable(logger, this);
69                 noteTable = new NoteTable(logger, this);
70                 deletedTable = new DeletedTable(logger, this);
71                 searchTable = new SavedSearchTable(logger, this);       
72                 watchFolderTable = new WatchFolderTable(logger, this);
73                 invalidXMLTable = new InvalidXMLTable(logger, this);
74                 wordsTable = new WordsTable(logger, this);
75                 syncTable = new SyncTable(logger, this);
76                 linkedNotebookTable = new LinkedNotebookTable(logger, this);
77                 sharedNotebookTable = new SharedNotebookTable(logger, this);
78                 systemIconTable = new SystemIconTable(logger, this);
79                 inkImagesTable = new InkImagesTable(logger, this);
80                 historyTable = new HistoryTable(logger, this);
81                 excludedTable = new ExcludedTable(logger, this);
82                 staredTable = new StaredTable(logger, this);
83                 
84         }
85         
86         
87         // Compact the database
88         public void compactDatabase() {
89                 
90         }
91         
92         // Initialize the database connection
93         public void dbSetup(String url,String indexUrl, String resourceUrl, String behaviorUrl, String userid, String userPassword, String cypherPassword) {
94                 logger.log(logger.HIGH, "Entering DatabaseConnection.dbSetup " +id);
95
96                 
97                 try {
98                         Class.forName("org.h2.Driver");
99                 } catch (ClassNotFoundException e1) {
100                         e1.printStackTrace();
101                         System.exit(16);
102                 }
103                 
104 //              QJdbc.initialize();
105                 
106                 setupTables();
107                 
108                 File f = Global.getFileManager().getDbDirFile(Global.databaseName + ".h2.db");
109                 boolean dbExists = f.exists(); 
110                 f = Global.getFileManager().getDbDirFile(Global.indexDatabaseName + ".h2.db");
111                 boolean indexDbExists = f.exists(); 
112                 f = Global.getFileManager().getDbDirFile(Global.resourceDatabaseName + ".h2.db");
113                 boolean resourceDbExists = f.exists();
114                 f = Global.getFileManager().getDbDirFile(Global.behaviorDatabaseName + ".h2.db");
115                 boolean behaviorDbExists = f.exists();
116                 
117                 logger.log(logger.HIGH, "Entering RDatabaseConnection.dbSetup");
118                 
119                 String passwordString = null;
120                 try {
121                         
122                         if (cypherPassword==null || cypherPassword.trim().equals(""))
123                                 passwordString = userPassword;
124                         else
125                                 passwordString = cypherPassword+" "+userPassword;
126 //                      conn = DriverManager.getConnection(url,userid,passwordString);
127 //                      conn = DriverManager.getConnection(url,userid,passwordString);
128 //                      conn = DriverManager.getConnection(url+";CACHE_SIZE=4096",userid,passwordString);
129                         if (throttle == 0) {
130                                 conn = DriverManager.getConnection(url+";CACHE_SIZE="+Global.databaseCache,userid,passwordString);
131                         } else {
132                                 conn = DriverManager.getConnection(url+";THROTTLE=" +new Integer(throttle).toString()+";CACHE_SIZE="+Global.databaseCache,userid,passwordString);
133                         }
134                         indexConn = DriverManager.getConnection(indexUrl,userid,passwordString);
135                         resourceConn = DriverManager.getConnection(resourceUrl,userid,passwordString);
136                         behaviorConn = DriverManager.getConnection(behaviorUrl, userid, passwordString);
137                         
138 //                      conn = DriverManager.getConnection(url+";AUTO_SERVER=TRUE",userid,passwordString);
139                 } catch (SQLException e) {
140                         e.printStackTrace();
141                         return;
142                 }
143                 
144                 // If it doesn't exist and we are the main thread, then we need to create stuff.
145                 if (!dbExists)  {
146                         createTables();
147                         Global.setAutomaticLogin(false);
148                 }               
149                 if (!resourceDbExists) {
150                         createResourceTables();
151                         if (dbTableExists("NoteResources")) {
152                                 // Begin migration of database
153                                 NSqlQuery query = new NSqlQuery(resourceConn);
154                                 String linkcmd = "create linked table oldnoteresources "+
155                                                 "('org.h2.Driver', '"+url+"', '"+userid+"', '"+passwordString+"', 'NoteResources')";
156                                 query.exec(linkcmd);
157                                 query.exec("insert into noteresources (select * from oldnoteresources)");
158                                 query.exec("Drop table oldnoteresources;");
159                                 query.exec("Update noteresources set indexneeded='true'");
160                                 
161                         }
162                 }
163                 if (!indexDbExists)  {
164                         createIndexTables();
165                         executeSql("Update note set indexneeded='true'");
166                 }
167                 
168                 // 操作履歴テーブルと除外ノートテーブルとスター付きノートテーブルを作る
169                 if (!behaviorDbExists) {
170                         createHistoryTables();
171                         createExcludedTables();
172                         createStaredTables();
173                 }
174                 
175                 // If we encrypted/decrypted it the last time, we need to reconnect the tables.
176 //              if (Global.relinkTables) {
177 //                      NSqlQuery query = new NSqlQuery(conn);
178 //                      query.exec("Drop table NoteResources;");
179 //                      String linkcmd = "create linked table NoteResources "
180 //                              +"('org.h2.Driver', '"+url+"', '"+userid+"', '"+passwordString+ "', 'NoteResources')";
181 //                      System.out.println(linkcmd);
182 //                      query.exec(linkcmd);
183 //                      System.err.println(query.lastError());
184 //                      Global.relinkTables = false;
185 //              }
186                 
187                 
188                 logger.log(logger.HIGH, "Leaving DatabaseConnection.dbSetup" +id);
189         }
190         
191         
192         public void dbShutdown() {
193                 logger.log(logger.HIGH, "Entering RDatabaseConnection.dbShutdown");
194                 try {
195                         conn.close();
196                 } catch (SQLException e) {
197                         e.printStackTrace();
198                 }
199                 logger.log(logger.HIGH, "Leaving RDatabaseConnection.dbShutdown");
200         }
201         
202         public void upgradeDb(String version) {
203                 if (version.equals("0.85")) {
204                         executeSql("alter table note add column titleColor integer");
205                         executeSql("alter table note add column thumbnail blob");
206                         executeSql("alter table note add column thumbnailneeded boolean");
207                         executeSql("Update note set thumbnailneeded = true;");
208                         executeSql("create index NOTE_NOTEBOOK_INDEX on note (notebookguid, guid);");
209                         executeSql("create index NOTETAGS_TAG_INDEX on notetags (tagguid, noteguid);");
210                         version = "0.86";
211                         Global.setDatabaseVersion(version);
212                 } 
213                 if (version.equals("0.86")) {
214         
215                         executeSql("alter table notebook add column publishingUri VarChar");
216                         executeSql("alter table notebook add column publishingOrder Integer");
217                         executeSql("alter table notebook add column publishingAscending Boolean");
218                         executeSql("alter table notebook add column publishingPublicDescription varchar");
219                         executeSql("alter table notebook add column stack varchar");
220                         executeSql("alter table notebook add column icon blob");
221                         executeSql("alter table notebook add column readOnly boolean");
222                         executeSql("alter table notebook add column linked boolean");
223                         
224                         executeSql("alter table tag add column realname varchar");
225                         executeSql("alter table tag add column linked boolean");
226                         executeSql("alter table tag add column icon blob");
227                         executeSql("alter table tag add column notebookguid varchar");
228                         executeSql("alter table SavedSearch add column icon blob");
229
230                         executeSql("create index NOTE_THUMBNAIL_INDEX on note (thumbnailneeded, guid);");
231                         executeSql("create index NOTE_EXPUNGED_INDEX on note (isExpunged, guid);");
232                         executeSql("create index NOTE_DUEDATE_INDEX on note (attributeSubjectDate, guid);");
233                         executeSql("create index TAG_NOTEBOOK_INDEX on tag (notebookGuid);");
234                         
235                         executeSql("update note set thumbnailneeded=true, thumbnail=null;");
236                         executeSql("update notebook set publishingUri='', " +
237                                         "publishingAscending=false, stack='', readonly=false, publishingOrder=1, " +
238                                         "publishingPublicDescription='', linked=false");
239                         executeSql("update tag set linked=false, realname='', notebookguid=''");
240                         
241                         sharedNotebookTable.createTable();
242                         linkedNotebookTable.createTable();
243                         systemIconTable.createTable();
244                         inkImagesTable.createTable();
245                         
246                         version = "0.95";
247                         executeSql("Insert into Sync (key, value) values ('FullNotebookSync', 'true')");
248                         executeSql("Insert into Sync (key, value) values ('FullLinkedNotebookSync', 'true')");
249                         executeSql("Insert into Sync (key, value) values ('FullSharedNotebookSync', 'true')");
250                         executeSql("Insert into Sync (key, value) values ('FullInkNoteImageSync', 'true')");
251                         Global.setDatabaseVersion(version);
252                 } 
253                 if (version.equals("0.95")) {
254                         if (dbTableExists("words"))
255                                 executeSql("Drop table words;");
256                         if (dbTableExists("NoteResources"))
257                                 executeSql("Drop table NoteResources;");
258                 }
259                 if (!dbTableColumnExists("NOTE", "ORIGINAL_GUID")) {
260                         executeSql("alter table note add column ORIGINAL_GUID VarChar");
261                         executeSql("create index NOTE_ORIGINAL_GUID_INDEX on note (original_guid, guid);");
262                 }
263                 if (!dbTableColumnExists("NOTEBOOK", "NARROW_SORT_ORDER")) {
264                         executeSql("alter table notebook add column NARROW_SORT_ORDER integer");
265                         executeSql("update notebook set NARROW_SORT_ORDER = -1");
266
267                         executeSql("alter table notebook add column WIDE_SORT_ORDER integer");
268                         executeSql("update notebook set WIDE_SORT_ORDER = -1");
269                         
270                         executeSql("alter table notebook add column WIDE_SORT_COLUMN integer");
271                         executeSql("update notebook set WIDE_SORT_COLUMN = -1");
272                         
273                         executeSql("alter table notebook add column NARROW_SORT_COLUMN integer");
274                         executeSql("update notebook set NARROW_SORT_COLUMN = -1");
275                 }
276                 if (!dbTableColumnExists("NOTE", "PINNED")) {
277                         executeSql("alter table note add column pinned integer");
278                         executeSql("update note set pinned = 0");
279                 }
280                 if (!dbTableColumnExists("NOTE", "ATTRIBUTECONTENTCLASS")) {
281                         executeSql("alter table note add column attributeContentClass VarChar");
282                         executeSql("update note set attributeContentClass = ''");
283                 }
284                 
285                 // Apache Luceneを使った日本語検索のためのプレーンテキストノートコンテンツカラムを準備
286                 if (!dbTableColumnExists("NOTE", "CONTENTTEXT")) {
287                         executeSql("alter table note add column contentText VarChar");
288                         executeSql("update note set contentText = ''");
289                         NSqlQuery query = new NSqlQuery(conn);
290                         query.exec("Select guid, content from Note where contentText = ''");
291                         while (query.next()) {
292                                 String guid = query.valueString(0);
293                                 String content = query.valueString(1);
294                                 String contentText = Global.extractPlainText(content);
295                                 NSqlQuery query2 = new NSqlQuery(conn);
296                                 query2.prepare("update note set contentText=:contentText where guid=:guid");
297                                 query2.bindValue(":contentText", contentText);
298                                 query2.bindValue(":guid", guid);
299                                 query2.exec();
300                         }
301                         
302                         // Apache Luceneを使った全文検索のための準備
303                         query.exec("CREATE ALIAS IF NOT EXISTS FTL_INIT FOR \"org.h2.fulltext.FullTextLuceneEx.init\"");
304                         query.exec("CALL FTL_INIT()");
305                         
306                         Global.rebuildFullTextNoteTarget(this);
307                 }
308                 
309                 // Evernoteサムネイルカラムを追加
310                 if (!dbTableColumnExists("NOTE", "ENTHUMBNAIL")) {
311                         executeSql("alter table note add column enThumbNail Blob");
312                 }
313                 
314                 // Apache Luceneを使った日本語検索のためのプレーンテキストノートリソースカラムを準備
315                 NSqlQuery rQuery = new NSqlQuery(resourceConn);
316                 rQuery.exec("select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='NOTERESOURCES' and COLUMN_NAME='RESOURCETEXT'");
317                 if (!rQuery.next()) {
318                         rQuery.exec("alter table noteResources add column resourceText VarChar");
319                         rQuery.exec("update noteResources set resourceText = ''");
320                         
321                         // Apache Luceneを使った全文検索のための準備
322                         rQuery.exec("CREATE ALIAS IF NOT EXISTS FTL_INIT FOR \"org.h2.fulltext.FullTextLuceneEx.init\"");
323                         rQuery.exec("CALL FTL_INIT()");
324                         
325                         Global.rebuildFullTextResourceTarget(this);
326                 }
327         }
328         
329         public void executeSql(String sql) {
330                 NSqlQuery query = new NSqlQuery(conn);
331                 query.exec(sql);        
332         }
333         
334         public void checkDatabaseVersion() {
335                 if (!Global.getDatabaseVersion().equals("0.86")) {
336                         upgradeDb(Global.getDatabaseVersion());
337                 }
338                 if (!Global.getDatabaseVersion().equals("0.95")) {
339                         upgradeDb(Global.getDatabaseVersion());
340                 }
341                 if (!Global.getDatabaseVersion().equals("0.97")) {
342                         upgradeDb(Global.getDatabaseVersion());
343                 }
344         }
345         
346
347         public void backupDatabase(int highSequence, long date) {
348                 
349         }
350         
351         
352         public void createTables() {
353                 Global.setDatabaseVersion("0.85");
354                 Global.setAutomaticLogin(false);
355                 Global.saveCurrentNoteGuid("");
356                 Global.saveUploadAmount(0);
357                 
358                 getTagTable().createTable();
359                 notebookTable.createTable(true);
360                 noteTable.createTable();
361                 deletedTable.createTable();             
362                 searchTable.createTable();
363                 watchFolderTable.createTable();
364                 invalidXMLTable.createTable();
365                 syncTable.createTable();
366         }
367         
368         public void createIndexTables() {
369                 wordsTable.createTable();
370         }
371         
372         public void createResourceTables() {
373                 noteTable.noteResourceTable.createTable();
374         }
375         
376         public void createHistoryTables() {
377                 historyTable.createTable();
378         }
379         
380         public void createExcludedTables() {
381                 excludedTable.createTable();
382         }
383         
384         public void createStaredTables() {
385                 staredTable.createTable();
386         }
387         
388         public Connection getConnection() {
389                 return conn;
390         }
391         public Connection getIndexConnection() {
392                 return  indexConn;
393         }
394         public Connection getResourceConnection() {
395                 return resourceConn;
396         }
397         
398         public Connection getBehaviorConnection() {
399                 return behaviorConn;
400         }
401         
402         //***************************************************************
403         //* Table get methods
404         //***************************************************************
405         public DeletedTable getDeletedTable() {
406                 return deletedTable;
407         }
408         public TagTable getTagTable() {
409                 return tagTable;
410         }
411         public NoteTable getNoteTable() {
412                 return noteTable;
413         }
414         public NotebookTable getNotebookTable() {
415                 return notebookTable;
416         }
417         public SavedSearchTable getSavedSearchTable() {
418                 return searchTable;
419         }
420         public WatchFolderTable getWatchFolderTable() {
421                 return watchFolderTable;
422         }
423         public WordsTable getWordsTable() {
424                 return wordsTable;
425         }
426         public InvalidXMLTable getInvalidXMLTable() {
427                 return invalidXMLTable;
428         }
429         public SyncTable getSyncTable() {
430                 return syncTable;
431         }
432         public LinkedNotebookTable getLinkedNotebookTable() {
433                 return linkedNotebookTable;
434         }
435         public SharedNotebookTable getSharedNotebookTable() {
436                 return sharedNotebookTable;
437         }
438         public SystemIconTable getSystemIconTable() {
439                 return systemIconTable;
440         }
441         public InkImagesTable getInkImagesTable() {
442                 return inkImagesTable;
443         }
444         
445         public HistoryTable getHistoryTable() {
446                 return historyTable;
447         }
448         
449         public ExcludedTable getExcludedTable() {
450                 return excludedTable;
451         }
452         
453         public StaredTable getStaredTable() {
454                 return staredTable;
455         }
456
457         //****************************************************************
458         //* Begin/End transactions
459         //****************************************************************
460         public void beginTransaction() {
461                 commitTransaction();
462         NSqlQuery query = new NSqlQuery(getConnection());                                                       
463                 if (!query.exec("Begin Transaction"))
464                         logger.log(logger.EXTREME, "Begin transaction has failed: " +query.lastError());
465
466         }
467         public void commitTransaction() {
468         NSqlQuery query = new NSqlQuery(getConnection());
469                                                         
470                 if (!query.exec("Commit"))
471                         logger.log(logger.EXTREME, "Transaction commit has failed: " +query.lastError());
472         }
473
474         //****************************************************************
475         //* Check if a table exists
476         //****************************************************************
477         public boolean dbTableExists(String name) {
478         NSqlQuery query = new NSqlQuery(getConnection());
479         query.prepare("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_NAME=:name");
480         query.bindValue(":name", name.toUpperCase());
481         query.exec();
482         if (query.next())
483                 return true;
484         else
485                 return false;
486         }
487         
488         //****************************************************************
489         //* Check if a row in a table exists
490         //****************************************************************
491         public boolean dbTableColumnExists(String tableName, String columnName) {
492         NSqlQuery query = new NSqlQuery(getConnection());
493         query.prepare("select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=:name and COLUMN_NAME=:column");
494         query.bindValue(":name", tableName.toUpperCase());
495         query.bindValue(":column", columnName);
496         query.exec();
497         if (query.next())
498                 return true;
499         else
500                 return false;
501         }
502 }