OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / sqlite-jdbc / src / main / java / SQLite / JDBC2z / JDBCConnection.java
1 package SQLite.JDBC2z;
2
3 import java.sql.*;
4 import java.util.*;
5
6 public class JDBCConnection
7     implements java.sql.Connection, SQLite.BusyHandler {
8
9     /**
10      * Open database.
11      */
12     protected DatabaseX db;
13
14     /**
15      * Database URL.
16      */
17     protected String url;
18
19     /**
20      * Character encoding.
21      */
22     protected String enc;
23
24     /**
25      * SQLite 3 VFS to use.
26      */
27     protected String vfs;
28
29     /**
30      * Autocommit flag, true means autocommit.
31      */
32     protected boolean autocommit = true;
33
34     /**
35      * In-transaction flag.
36      * Can be true only when autocommit false.
37      */
38     protected boolean intrans = false;
39
40     /**
41      * Timeout for Database.exec()
42      */
43     protected int timeout = 1000000;
44
45     /**
46      * Use double/julian date representation.
47      */
48     protected boolean useJulian = false;
49
50     /**
51      * File name of database.
52      */
53     private String dbfile = null;
54
55     /**
56      * Reference to meta data or null.
57      */
58     private JDBCDatabaseMetaData meta = null;
59
60     /**
61      * Base time value for timeout handling.
62      */
63     private long t0;
64
65     /**
66      * Database in readonly mode.
67      */
68     private boolean readonly = false;
69
70     /**
71      * Transaction isolation mode.
72      */
73     private int trmode = TRANSACTION_SERIALIZABLE;
74
75     private boolean busy0(DatabaseX db, int count) {
76         if (count <= 1) {
77             t0 = System.currentTimeMillis();
78         }
79         if (db != null) {
80             long t1 = System.currentTimeMillis();
81             if (t1 - t0 > timeout) {
82                 return false;
83             }
84             db.wait(100);
85             return true;
86         }
87         return false;
88     }
89
90     public boolean busy(String table, int count) {
91         return busy0(db, count);
92     }
93
94     protected boolean busy3(DatabaseX db, int count) {
95         if (count <= 1) {
96             t0 = System.currentTimeMillis();
97         }
98         if (db != null) {
99             long t1 = System.currentTimeMillis();
100             if (t1 - t0 > timeout) {
101                 return false;
102             }
103             return true;
104         }
105         return false;
106     }
107
108     private DatabaseX open(boolean readonly) throws SQLException {
109         DatabaseX dbx = null;
110         try {
111             dbx = new DatabaseX();
112             dbx.open(dbfile, readonly ? SQLite.Constants.SQLITE_OPEN_READONLY :
113                      (SQLite.Constants.SQLITE_OPEN_READWRITE |
114                       SQLite.Constants.SQLITE_OPEN_CREATE), vfs);
115             dbx.set_encoding(enc);
116         } catch (SQLite.Exception e) {
117             throw new SQLException(e.toString());
118         }
119         int loop = 0;
120         while (true) {
121             try {
122                 dbx.exec("PRAGMA short_column_names = off;", null);
123                 dbx.exec("PRAGMA full_column_names = on;", null);
124                 dbx.exec("PRAGMA empty_result_callbacks = on;", null);
125                 if (SQLite.Database.version().compareTo("2.6.0") >= 0) {
126                     dbx.exec("PRAGMA show_datatypes = on;", null);
127                 }
128             } catch (SQLite.Exception e) {
129                 if (dbx.last_error() != SQLite.Constants.SQLITE_BUSY ||
130                     !busy0(dbx, ++loop)) {
131                     try {
132                         dbx.close();
133                     } catch (SQLite.Exception ee) {
134                     }
135                     throw new SQLException(e.toString());
136                 }
137                 continue;
138             }
139             break;
140         }
141         return dbx;
142     }
143
144     public JDBCConnection(String url, String enc, String pwd, String drep,
145                           String vfs)
146         throws SQLException {
147         if (url.startsWith("sqlite:/")) {
148             dbfile = url.substring(8);
149         } else if (url.startsWith("jdbc:sqlite:/")) {
150             dbfile = url.substring(13);
151         } else {
152             throw new SQLException("unsupported url");
153         }
154         this.url = url;
155         this.enc = enc;
156         this.vfs = vfs;
157         try {
158             db = open(readonly);
159             try {
160                 if (pwd != null && pwd.length() > 0) {
161                     db.key(pwd);
162                 }
163             } catch (SQLite.Exception se) {
164                 throw new SQLException("error while setting key");
165             }
166             db.busy_handler(this);
167         } catch (SQLException e) {
168             if (db != null) {
169                 try {
170                     db.close();
171                 } catch (SQLite.Exception ee) {
172                 }
173             }
174             throw e;
175         }
176         useJulian = drep != null &&
177             (drep.startsWith("j") || drep.startsWith("J"));
178     }
179
180     /* non-standard */
181     public SQLite.Database getSQLiteDatabase() {
182         return (SQLite.Database) db;
183     }
184   
185     public Statement createStatement() {
186         JDBCStatement s = new JDBCStatement(this);
187         return s;
188     }
189
190     public Statement createStatement(int resultSetType,
191                                      int resultSetConcurrency)
192         throws SQLException {
193         if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
194             resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
195             resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
196             throw new SQLFeatureNotSupportedException("unsupported result set type");
197         }
198         if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
199             resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
200             throw new SQLFeatureNotSupportedException("unsupported result set concurrency");
201         }
202         JDBCStatement s = new JDBCStatement(this);
203         return s;
204     }
205         
206     public DatabaseMetaData getMetaData() throws SQLException {
207         if (meta == null) {
208             meta = new JDBCDatabaseMetaData(this);
209         }
210         return meta;
211     }
212
213     public void close() throws SQLException {
214         try {
215             rollback();
216         } catch (SQLException e) {
217             /* ignored */
218         }
219         intrans = false;
220         if (db != null) {
221             try {
222                 db.close();
223                 db = null;
224             } catch (SQLite.Exception e) {
225                 throw new SQLException(e.toString());
226             }
227         }
228     }
229
230     public boolean isClosed() throws SQLException {
231         return db == null;
232     }
233
234     public boolean isReadOnly() throws SQLException {
235         return readonly;
236     }
237
238     public void clearWarnings() throws SQLException {
239     }
240
241     public void commit() throws SQLException {
242         if (db == null) {
243             throw new SQLException("stale connection");
244         }
245         if (!intrans) {
246             return;
247         }
248         try {
249             db.exec("COMMIT", null);
250             intrans = false;
251         } catch (SQLite.Exception e) {
252             throw new SQLException(e.toString());
253         }
254     }
255
256     public boolean getAutoCommit() throws SQLException {
257         return autocommit;
258     }
259
260     public String getCatalog() throws SQLException {
261         return null;
262     }
263
264     public int getTransactionIsolation() throws SQLException {
265         return trmode;
266     }
267
268     public SQLWarning getWarnings() throws SQLException {
269         return null;
270     }
271
272     public String nativeSQL(String sql) throws SQLException {
273         throw new SQLException("not supported");
274     }
275
276     public CallableStatement prepareCall(String sql) throws SQLException {
277         throw new SQLException("not supported");
278     }
279
280     public CallableStatement prepareCall(String sql, int x, int y)
281         throws SQLException {
282         throw new SQLFeatureNotSupportedException();
283     }
284
285     public PreparedStatement prepareStatement(String sql) throws SQLException {
286         JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
287         return s;
288     }
289
290     public PreparedStatement prepareStatement(String sql, int resultSetType,
291                                               int resultSetConcurrency)
292         throws SQLException {
293         if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
294             resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
295             resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
296             throw new SQLFeatureNotSupportedException("unsupported result set type");
297         }
298         if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
299             resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
300             throw new SQLFeatureNotSupportedException("unsupported result set concurrency");
301         }
302         JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
303         return s;
304     }
305
306     public void rollback() throws SQLException {
307         if (db == null) {
308             throw new SQLException("stale connection");
309         }
310         if (!intrans) {
311             return;
312         }
313         try {
314             db.exec("ROLLBACK", null);
315             intrans = false;
316         } catch (SQLite.Exception e) {
317             throw new SQLException(e.toString());
318         }
319     }
320
321     public void setAutoCommit(boolean ac) throws SQLException {
322         if (ac && intrans && db != null) {
323             try {
324                 db.exec("ROLLBACK", null);
325             } catch (SQLite.Exception e) {
326                 throw new SQLException(e.toString());
327             } finally {
328                 intrans = false;
329             }
330         }
331         autocommit = ac;
332     }
333
334     public void setCatalog(String catalog) throws SQLException {
335     }
336
337     public void setReadOnly(boolean ro) throws SQLException {
338         if (intrans) {
339             throw new SQLException("incomplete transaction");
340         }
341         if (ro != readonly) {
342             DatabaseX dbx = null;
343             try {
344                 dbx = open(ro);
345                 db.close();
346                 db = dbx;
347                 dbx = null;
348                 readonly = ro;
349             } catch (SQLException e) {
350                 throw e;
351             } catch (SQLite.Exception ee) {
352                 if (dbx != null) {
353                     try {
354                         dbx.close();
355                     } catch (SQLite.Exception eee) {
356                     }
357                 }
358                 throw new SQLException(ee.toString());
359             }
360         }
361     }
362
363     public void setTransactionIsolation(int level) throws SQLException {
364         if (db.is3() && SQLite.JDBCDriver.sharedCache) {
365             String flag = null;
366             if (level == TRANSACTION_READ_UNCOMMITTED &&
367                 trmode != TRANSACTION_READ_UNCOMMITTED) {
368                 flag = "on";
369             } else if (level == TRANSACTION_SERIALIZABLE &&
370                        trmode != TRANSACTION_SERIALIZABLE) {
371                 flag = "off";
372             }
373             if (flag != null) {
374                 try {
375                     db.exec("PRAGMA read_uncommitted = " + flag + ";", null);
376                     trmode = level;
377                 } catch (java.lang.Exception e) {
378                 }
379             }
380         }
381         if (level != trmode) {
382             throw new SQLException("not supported");
383         }
384     }
385
386     public java.util.Map<String, Class<?>> getTypeMap() throws SQLException {
387         throw new SQLFeatureNotSupportedException();
388     }
389
390     public void setTypeMap(java.util.Map map) throws SQLException {
391         throw new SQLFeatureNotSupportedException();
392     }
393   
394     public int getHoldability() throws SQLException {
395         return ResultSet.HOLD_CURSORS_OVER_COMMIT;
396     }
397
398     public void setHoldability(int holdability) throws SQLException {
399         if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT) {
400             return;
401         }
402         throw new SQLFeatureNotSupportedException("unsupported holdability");
403     }
404
405     public Savepoint setSavepoint() throws SQLException {
406         throw new SQLFeatureNotSupportedException();
407     }
408
409     public Savepoint setSavepoint(String name) throws SQLException {
410         throw new SQLFeatureNotSupportedException();
411     }
412
413     public void rollback(Savepoint x) throws SQLException {
414         throw new SQLFeatureNotSupportedException();
415     }
416
417     public void releaseSavepoint(Savepoint x) throws SQLException {
418         throw new SQLFeatureNotSupportedException();
419     }
420
421     public Statement createStatement(int resultSetType,
422                                      int resultSetConcurrency,
423                                      int resultSetHoldability)
424         throws SQLException {
425         if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
426             throw new SQLFeatureNotSupportedException("unsupported holdability");
427         }
428         return createStatement(resultSetType, resultSetConcurrency);
429     }
430
431     public PreparedStatement prepareStatement(String sql, int resultSetType,
432                                               int resultSetConcurrency,
433                                               int resultSetHoldability)
434         throws SQLException {
435         if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
436             throw new SQLFeatureNotSupportedException("unsupported holdability");
437         }
438         return prepareStatement(sql, resultSetType, resultSetConcurrency);
439     }
440
441     public CallableStatement prepareCall(String sql, int x, int y, int z)
442         throws SQLException {
443         throw new SQLFeatureNotSupportedException();
444     }
445
446     public PreparedStatement prepareStatement(String sql, int autokeys)
447         throws SQLException {
448         if (autokeys != Statement.NO_GENERATED_KEYS) {
449             throw new SQLFeatureNotSupportedException("generated keys not supported");
450         }
451         return prepareStatement(sql);
452     }
453
454     public PreparedStatement prepareStatement(String sql, int colIndexes[])
455         throws SQLException {
456         throw new SQLFeatureNotSupportedException();
457     }
458
459     public PreparedStatement prepareStatement(String sql, String columns[])
460         throws SQLException {
461         throw new SQLFeatureNotSupportedException();
462     }
463
464     public Clob createClob() throws SQLException {
465         throw new SQLFeatureNotSupportedException();
466     }
467
468     public Blob createBlob() throws SQLException {
469         throw new SQLFeatureNotSupportedException();
470     }
471
472     public NClob createNClob() throws SQLException {
473         throw new SQLFeatureNotSupportedException();
474     }
475
476     public SQLXML createSQLXML() throws SQLException {
477         throw new SQLFeatureNotSupportedException();
478     }
479
480     public boolean isValid(int timeout) throws SQLException {
481         return true;
482     }
483
484     public void setClientInfo(String name, String value)
485         throws SQLClientInfoException {
486         throw new SQLClientInfoException();
487     }
488
489     public void setClientInfo(Properties prop) throws SQLClientInfoException {
490         throw new SQLClientInfoException();
491     }
492
493     public String getClientInfo(String name) throws SQLException {
494         throw new SQLException("unsupported");
495     }
496
497     public Properties getClientInfo() throws SQLException {
498         return new Properties();
499     }
500
501     public Array createArrayOf(String type, Object[] elems)
502         throws SQLException {
503         throw new SQLFeatureNotSupportedException();
504     }
505
506     public Struct createStruct(String type, Object[] attrs)
507         throws SQLException {
508         throw new SQLFeatureNotSupportedException();
509     }
510
511     public <T> T unwrap(java.lang.Class<T> iface) throws SQLException {
512         throw new SQLException("unsupported");
513     }
514
515     public boolean isWrapperFor(java.lang.Class iface) throws SQLException {
516         return false;
517     }
518
519 }
520
521 class DatabaseX extends SQLite.Database {
522
523     static Object lock = new Object();
524
525     public DatabaseX() {
526         super();
527     }
528
529     void wait(int ms) {
530         try {
531             synchronized (lock) {
532                 lock.wait(ms);
533             }
534         } catch (java.lang.Exception e) {
535         }
536     }
537
538     public void exec(String sql, SQLite.Callback cb)
539         throws SQLite.Exception {
540         super.exec(sql, cb);
541         synchronized (lock) {
542             lock.notifyAll();
543         }
544     }
545
546     public void exec(String sql, SQLite.Callback cb, String args[])
547         throws SQLite.Exception {
548         super.exec(sql, cb, args);
549         synchronized (lock) {
550             lock.notifyAll();
551         }
552     }
553
554     public SQLite.TableResult get_table(String sql, String args[])
555         throws SQLite.Exception {
556         SQLite.TableResult ret = super.get_table(sql, args);
557         synchronized (lock) {
558             lock.notifyAll();
559         }
560         return ret;
561     }
562
563     public void get_table(String sql, String args[], SQLite.TableResult tbl)
564         throws SQLite.Exception {
565         super.get_table(sql, args, tbl);
566         synchronized (lock) {
567             lock.notifyAll();
568         }
569     }
570
571 }