1 package SQLite.JDBC2z;
2 
3 import java.sql.Connection;
4 import java.sql.DatabaseMetaData;
5 import java.sql.ResultSet;
6 import java.sql.RowIdLifetime;
7 import java.sql.SQLException;
8 import java.sql.Types;
9 import java.util.Hashtable;
10 
11 public class JDBCDatabaseMetaData implements DatabaseMetaData {
12 
13     private JDBCConnection conn;
14 
JDBCDatabaseMetaData(JDBCConnection conn)15     public JDBCDatabaseMetaData(JDBCConnection conn) {
16 	this.conn = conn;
17     }
18 
19     @Override
allProceduresAreCallable()20     public boolean allProceduresAreCallable() throws SQLException {
21 	return false;
22     }
23 
24     @Override
allTablesAreSelectable()25     public boolean allTablesAreSelectable() throws SQLException {
26 	return true;
27     }
28 
29     @Override
getURL()30     public String getURL() throws SQLException {
31 	return conn.url;
32     }
33 
34     @Override
getUserName()35     public String getUserName() throws SQLException {
36 	return "";
37     }
38 
39     @Override
isReadOnly()40     public boolean isReadOnly() throws SQLException {
41 	return false;
42     }
43 
44     @Override
nullsAreSortedHigh()45     public boolean nullsAreSortedHigh() throws SQLException {
46 	return false;
47     }
48 
49     @Override
nullsAreSortedLow()50     public boolean nullsAreSortedLow() throws SQLException {
51 	return false;
52     }
53 
54     @Override
nullsAreSortedAtStart()55     public boolean nullsAreSortedAtStart() throws SQLException {
56 	return false;
57     }
58 
59     @Override
nullsAreSortedAtEnd()60     public boolean nullsAreSortedAtEnd() throws SQLException {
61 	return false;
62     }
63 
64     @Override
getDatabaseProductName()65     public String getDatabaseProductName() throws SQLException {
66 	return "SQLite";
67     }
68 
69     @Override
getDatabaseProductVersion()70     public String getDatabaseProductVersion() throws SQLException {
71 	return SQLite.Database.version();
72     }
73 
74     @Override
getDriverName()75     public String getDriverName() throws SQLException {
76 	return "SQLite/JDBC";
77     }
78 
79     @Override
getDriverVersion()80     public String getDriverVersion() throws SQLException {
81 	return "" + SQLite.JDBC.MAJORVERSION + "." +
82 	    SQLite.Constants.drv_minor;
83     }
84 
85     @Override
getDriverMajorVersion()86     public int getDriverMajorVersion() {
87 	return SQLite.JDBC.MAJORVERSION;
88     }
89 
90     @Override
getDriverMinorVersion()91     public int getDriverMinorVersion() {
92 	return SQLite.Constants.drv_minor;
93     }
94 
95     @Override
usesLocalFiles()96     public boolean usesLocalFiles() throws SQLException {
97 	return true;
98     }
99 
100     @Override
usesLocalFilePerTable()101     public boolean usesLocalFilePerTable() throws SQLException {
102 	return false;
103     }
104 
105     @Override
supportsMixedCaseIdentifiers()106     public boolean supportsMixedCaseIdentifiers() throws SQLException {
107 	return false;
108     }
109 
110     @Override
storesUpperCaseIdentifiers()111     public boolean storesUpperCaseIdentifiers() throws SQLException {
112 	return false;
113     }
114 
115     @Override
storesLowerCaseIdentifiers()116     public boolean storesLowerCaseIdentifiers() throws SQLException {
117 	return false;
118     }
119 
120     @Override
storesMixedCaseIdentifiers()121     public boolean storesMixedCaseIdentifiers() throws SQLException {
122 	return true;
123     }
124 
125     @Override
supportsMixedCaseQuotedIdentifiers()126     public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
127 	return false;
128     }
129 
130     @Override
storesUpperCaseQuotedIdentifiers()131     public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
132 	return false;
133     }
134 
135     @Override
storesLowerCaseQuotedIdentifiers()136     public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
137 	return false;
138     }
139 
140     @Override
storesMixedCaseQuotedIdentifiers()141     public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
142 	return true;
143     }
144 
145     @Override
getIdentifierQuoteString()146     public String getIdentifierQuoteString() throws SQLException {
147 	return "\"";
148     }
149 
150     @Override
getSQLKeywords()151     public String getSQLKeywords() throws SQLException {
152 	return "SELECT,UPDATE,CREATE,TABLE,VIEW,DELETE,FROM,WHERE" +
153 	    ",COMMIT,ROLLBACK,TRIGGER";
154     }
155 
156     @Override
getNumericFunctions()157     public String getNumericFunctions() throws SQLException {
158 	return "";
159     }
160 
161     @Override
getStringFunctions()162     public String getStringFunctions() throws SQLException {
163 	return "";
164     }
165 
166     @Override
getSystemFunctions()167     public String getSystemFunctions() throws SQLException {
168 	return "";
169     }
170 
171     @Override
getTimeDateFunctions()172     public String getTimeDateFunctions() throws SQLException {
173 	return "";
174     }
175 
176     @Override
getSearchStringEscape()177     public String getSearchStringEscape() throws SQLException {
178 	return "\\";
179     }
180 
181     @Override
getExtraNameCharacters()182     public String getExtraNameCharacters() throws SQLException {
183 	return "";
184     }
185 
186     @Override
supportsAlterTableWithAddColumn()187     public boolean supportsAlterTableWithAddColumn() throws SQLException {
188 	return false;
189     }
190 
191     @Override
supportsAlterTableWithDropColumn()192     public boolean supportsAlterTableWithDropColumn() throws SQLException {
193 	return false;
194     }
195 
196     @Override
supportsColumnAliasing()197     public boolean supportsColumnAliasing() throws SQLException {
198 	return true;
199     }
200 
201     @Override
nullPlusNonNullIsNull()202     public boolean nullPlusNonNullIsNull() throws SQLException {
203 	return false;
204     }
205 
206     @Override
supportsConvert()207     public boolean supportsConvert() throws SQLException {
208 	return false;
209     }
210 
211     @Override
supportsConvert(int fromType, int toType)212     public boolean supportsConvert(int fromType, int toType)
213 	throws SQLException {
214 	return false;
215     }
216 
217     @Override
supportsTableCorrelationNames()218     public boolean supportsTableCorrelationNames() throws SQLException {
219 	return true;
220     }
221 
222     @Override
supportsDifferentTableCorrelationNames()223     public boolean supportsDifferentTableCorrelationNames()
224 	throws SQLException {
225 	return false;
226     }
227 
228     @Override
supportsExpressionsInOrderBy()229     public boolean supportsExpressionsInOrderBy() throws SQLException {
230 	return true;
231     }
232 
233     @Override
supportsOrderByUnrelated()234     public boolean supportsOrderByUnrelated() throws SQLException {
235 	return true;
236     }
237 
238     @Override
supportsGroupBy()239     public boolean supportsGroupBy() throws SQLException {
240 	return true;
241     }
242 
243     @Override
supportsGroupByUnrelated()244     public boolean supportsGroupByUnrelated() throws SQLException {
245 	return true;
246     }
247 
248     @Override
supportsGroupByBeyondSelect()249     public boolean supportsGroupByBeyondSelect() throws SQLException {
250 	return false;
251     }
252 
253     @Override
supportsLikeEscapeClause()254     public boolean supportsLikeEscapeClause() throws SQLException {
255 	return false;
256     }
257 
258     @Override
supportsMultipleResultSets()259     public boolean supportsMultipleResultSets() throws SQLException {
260 	return false;
261     }
262 
263     @Override
supportsMultipleTransactions()264     public boolean supportsMultipleTransactions() throws SQLException {
265 	return false;
266     }
267 
268     @Override
supportsNonNullableColumns()269     public boolean supportsNonNullableColumns() throws SQLException {
270 	return true;
271     }
272 
273     @Override
supportsMinimumSQLGrammar()274     public boolean supportsMinimumSQLGrammar() throws SQLException {
275 	return true;
276     }
277 
278     @Override
supportsCoreSQLGrammar()279     public boolean supportsCoreSQLGrammar() throws SQLException {
280 	return false;
281     }
282 
283     @Override
supportsExtendedSQLGrammar()284     public boolean supportsExtendedSQLGrammar() throws SQLException {
285 	return false;
286     }
287 
288     @Override
supportsANSI92EntryLevelSQL()289     public boolean supportsANSI92EntryLevelSQL() throws SQLException {
290 	return true;
291     }
292 
293     @Override
supportsANSI92IntermediateSQL()294     public boolean supportsANSI92IntermediateSQL() throws SQLException {
295 	return false;
296     }
297 
298     @Override
supportsANSI92FullSQL()299     public boolean supportsANSI92FullSQL() throws SQLException {
300 	return false;
301     }
302 
303     @Override
supportsIntegrityEnhancementFacility()304     public boolean supportsIntegrityEnhancementFacility()
305 	throws SQLException {
306 	return false;
307     }
308 
309     @Override
supportsOuterJoins()310     public boolean supportsOuterJoins() throws SQLException {
311 	return false;
312     }
313 
314     @Override
supportsFullOuterJoins()315     public boolean supportsFullOuterJoins() throws SQLException {
316 	return false;
317     }
318 
319     @Override
supportsLimitedOuterJoins()320     public boolean supportsLimitedOuterJoins() throws SQLException {
321 	return false;
322     }
323 
324     @Override
getSchemaTerm()325     public String getSchemaTerm() throws SQLException {
326 	return "";
327     }
328 
329     @Override
getProcedureTerm()330     public String getProcedureTerm() throws SQLException {
331 	return "";
332     }
333 
334     @Override
getCatalogTerm()335     public String getCatalogTerm() throws SQLException {
336 	return "";
337     }
338 
339     @Override
isCatalogAtStart()340     public boolean isCatalogAtStart() throws SQLException {
341 	return false;
342     }
343 
344     @Override
getCatalogSeparator()345     public String getCatalogSeparator() throws SQLException {
346 	return "";
347     }
348 
349     @Override
supportsSchemasInDataManipulation()350     public boolean supportsSchemasInDataManipulation() throws SQLException {
351 	return false;
352     }
353 
354     @Override
supportsSchemasInProcedureCalls()355     public boolean supportsSchemasInProcedureCalls() throws SQLException {
356 	return false;
357     }
358 
359     @Override
supportsSchemasInTableDefinitions()360     public boolean supportsSchemasInTableDefinitions() throws SQLException {
361 	return false;
362     }
363 
364     @Override
supportsSchemasInIndexDefinitions()365     public boolean supportsSchemasInIndexDefinitions() throws SQLException {
366 	return false;
367     }
368 
369     @Override
supportsSchemasInPrivilegeDefinitions()370     public boolean supportsSchemasInPrivilegeDefinitions()
371 	throws SQLException {
372 	return false;
373     }
374 
375     @Override
supportsCatalogsInDataManipulation()376     public boolean supportsCatalogsInDataManipulation() throws SQLException {
377 	return false;
378     }
379 
380     @Override
supportsCatalogsInProcedureCalls()381     public boolean supportsCatalogsInProcedureCalls() throws SQLException {
382 	return false;
383     }
384 
385     @Override
supportsCatalogsInTableDefinitions()386     public boolean supportsCatalogsInTableDefinitions() throws SQLException {
387 	return false;
388     }
389 
390     @Override
supportsCatalogsInIndexDefinitions()391     public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
392 	return false;
393     }
394 
395     @Override
supportsCatalogsInPrivilegeDefinitions()396     public boolean supportsCatalogsInPrivilegeDefinitions()
397 	throws SQLException {
398 	return false;
399     }
400 
401     @Override
supportsPositionedDelete()402     public boolean supportsPositionedDelete() throws SQLException {
403 	return false;
404     }
405 
406     @Override
supportsPositionedUpdate()407     public boolean supportsPositionedUpdate() throws SQLException {
408 	return false;
409     }
410 
411     @Override
supportsSelectForUpdate()412     public boolean supportsSelectForUpdate() throws SQLException {
413 	return false;
414     }
415 
416     @Override
supportsStoredProcedures()417     public boolean supportsStoredProcedures() throws SQLException {
418 	return false;
419     }
420 
421     @Override
supportsSubqueriesInComparisons()422     public boolean supportsSubqueriesInComparisons() throws SQLException {
423 	return true;
424     }
425 
426     @Override
supportsSubqueriesInExists()427     public boolean supportsSubqueriesInExists() throws SQLException {
428 	return true;
429     }
430 
431     @Override
supportsSubqueriesInIns()432     public boolean supportsSubqueriesInIns() throws SQLException {
433 	return true;
434     }
435 
436     @Override
supportsSubqueriesInQuantifieds()437     public boolean supportsSubqueriesInQuantifieds() throws SQLException {
438 	return false;
439     }
440 
441     @Override
supportsCorrelatedSubqueries()442     public boolean supportsCorrelatedSubqueries() throws SQLException {
443 	return false;
444     }
445 
446     @Override
supportsUnion()447     public boolean supportsUnion() throws SQLException {
448 	return true;
449     }
450 
451     @Override
supportsUnionAll()452     public boolean supportsUnionAll() throws SQLException {
453 	return true;
454     }
455 
456     @Override
supportsOpenCursorsAcrossCommit()457     public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
458 	return false;
459     }
460 
461     @Override
supportsOpenCursorsAcrossRollback()462     public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
463 	return false;
464     }
465 
466     @Override
supportsOpenStatementsAcrossCommit()467     public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
468 	return false;
469     }
470 
471     @Override
supportsOpenStatementsAcrossRollback()472     public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
473 	return false;
474     }
475 
476     @Override
getMaxBinaryLiteralLength()477     public int getMaxBinaryLiteralLength() throws SQLException {
478 	return 0;
479     }
480 
481     @Override
getMaxCharLiteralLength()482     public int getMaxCharLiteralLength() throws SQLException {
483 	return 0;
484     }
485 
486     @Override
getMaxColumnNameLength()487     public int getMaxColumnNameLength() throws SQLException {
488 	return 0;
489     }
490 
491     @Override
getMaxColumnsInGroupBy()492     public int getMaxColumnsInGroupBy() throws SQLException {
493 	return 0;
494     }
495 
496     @Override
getMaxColumnsInIndex()497     public int getMaxColumnsInIndex() throws SQLException {
498 	return 0;
499     }
500 
501     @Override
getMaxColumnsInOrderBy()502     public int getMaxColumnsInOrderBy() throws SQLException {
503 	return 0;
504     }
505 
506     @Override
getMaxColumnsInSelect()507     public int getMaxColumnsInSelect() throws SQLException {
508 	return 0;
509     }
510 
511     @Override
getMaxColumnsInTable()512     public int getMaxColumnsInTable() throws SQLException {
513 	return 0;
514     }
515 
516     @Override
getMaxConnections()517     public int getMaxConnections() throws SQLException {
518 	return 0;
519     }
520 
521     @Override
getMaxCursorNameLength()522     public int getMaxCursorNameLength() throws SQLException {
523 	return 8;
524     }
525 
526     @Override
getMaxIndexLength()527     public int getMaxIndexLength() throws SQLException {
528 	return 0;
529     }
530 
531     @Override
getMaxSchemaNameLength()532     public int getMaxSchemaNameLength() throws SQLException {
533 	return 0;
534     }
535 
536     @Override
getMaxProcedureNameLength()537     public int getMaxProcedureNameLength() throws SQLException {
538 	return 0;
539     }
540 
541     @Override
getMaxCatalogNameLength()542     public int getMaxCatalogNameLength() throws SQLException {
543 	return 0;
544     }
545 
546     @Override
getMaxRowSize()547     public int getMaxRowSize() throws SQLException {
548 	return 0;
549     }
550 
551     @Override
doesMaxRowSizeIncludeBlobs()552     public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
553 	return true;
554     }
555 
556     @Override
getMaxStatementLength()557     public int getMaxStatementLength() throws SQLException {
558 	return 0;
559     }
560 
561     @Override
getMaxStatements()562     public int getMaxStatements() throws SQLException {
563 	return 0;
564     }
565 
566     @Override
getMaxTableNameLength()567     public int getMaxTableNameLength() throws SQLException {
568 	return 0;
569     }
570 
571     @Override
getMaxTablesInSelect()572     public int getMaxTablesInSelect() throws SQLException {
573 	return 0;
574     }
575 
576     @Override
getMaxUserNameLength()577     public int getMaxUserNameLength() throws SQLException {
578 	return 0;
579     }
580 
581     @Override
getDefaultTransactionIsolation()582     public int getDefaultTransactionIsolation() throws SQLException {
583 	return Connection.TRANSACTION_SERIALIZABLE;
584     }
585 
586     @Override
supportsTransactions()587     public boolean supportsTransactions() throws SQLException {
588 	return true;
589     }
590 
591     @Override
supportsTransactionIsolationLevel(int level)592     public boolean supportsTransactionIsolationLevel(int level)
593 	throws SQLException {
594 	return level == Connection.TRANSACTION_SERIALIZABLE;
595     }
596 
597     @Override
supportsDataDefinitionAndDataManipulationTransactions()598     public boolean supportsDataDefinitionAndDataManipulationTransactions()
599 	throws SQLException {
600 	return true;
601     }
602 
603     @Override
supportsDataManipulationTransactionsOnly()604     public boolean supportsDataManipulationTransactionsOnly()
605 	throws SQLException {
606 	return false;
607     }
608 
609     @Override
dataDefinitionCausesTransactionCommit()610     public boolean dataDefinitionCausesTransactionCommit()
611 	throws SQLException {
612 	return false;
613     }
614 
615     @Override
dataDefinitionIgnoredInTransactions()616     public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
617 	return false;
618     }
619 
620     @Override
getProcedures(String catalog, String schemaPattern, String procedureNamePattern)621     public ResultSet getProcedures(String catalog, String schemaPattern,
622 				   String procedureNamePattern)
623 	throws SQLException {
624 	return null;
625     }
626 
627     @Override
getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern)628     public ResultSet getProcedureColumns(String catalog,
629 					 String schemaPattern,
630 					 String procedureNamePattern,
631 					 String columnNamePattern)
632 	throws SQLException {
633 	return null;
634     }
635 
636     @Override
getTables(String catalog, String schemaPattern, String tableNamePattern, String types[])637     public ResultSet getTables(String catalog, String schemaPattern,
638 			       String tableNamePattern, String types[])
639 	throws SQLException {
640 	JDBCStatement s = new JDBCStatement(conn);
641 	StringBuilder sb = new StringBuilder(
642 		  "SELECT '' AS 'TABLE_CAT', " +
643 		  "'' AS 'TABLE_SCHEM', " +
644 		  "tbl_name AS 'TABLE_NAME', " +
645 		  "upper(type) AS 'TABLE_TYPE', " +
646 		  "'' AS REMARKS FROM sqlite_master " +
647 		  "WHERE tbl_name like ");
648 	if (tableNamePattern != null) {
649 	    sb.append(SQLite.Shell.sql_quote(tableNamePattern));
650 	} else {
651 	    sb.append("'%'");
652 	}
653 	sb.append(" AND ");
654 	if (types == null || types.length == 0) {
655 	    sb.append("(type = 'table' or type = 'view')");
656 	} else {
657 	    sb.append("(");
658 	    String sep = "";
659 	    for (int i = 0; i < types.length; i++) {
660 		sb.append(sep);
661 		sb.append("type = ");
662 		sb.append(SQLite.Shell.sql_quote(types[i].toLowerCase()));
663 		sep = " or ";
664 	    }
665 	    sb.append(")");
666 	}
667 	ResultSet rs = null;
668 	try {
669 	    rs = s.executeQuery(sb.toString());
670 	    s.close();
671 	} catch (SQLException e) {
672 	    throw e;
673 	} finally {
674 	    s.close();
675 	}
676 	return rs;
677     }
678 
679     @Override
getSchemas()680     public ResultSet getSchemas() throws SQLException {
681 	String cols[] = { "TABLE_SCHEM" };
682 	SQLite.TableResult tr = new SQLite.TableResult();
683 	tr.columns(cols);
684 	String row[] = { "" };
685 	tr.newrow(row);
686 	JDBCResultSet rs = new JDBCResultSet(tr, null);
687 	return rs;
688     }
689 
690     @Override
getCatalogs()691     public ResultSet getCatalogs() throws SQLException {
692 	String cols[] = { "TABLE_CAT" };
693 	SQLite.TableResult tr = new SQLite.TableResult();
694 	tr.columns(cols);
695 	String row[] = { "" };
696 	tr.newrow(row);
697 	JDBCResultSet rs = new JDBCResultSet(tr, null);
698 	return rs;
699     }
700 
701     @Override
getTableTypes()702     public ResultSet getTableTypes() throws SQLException {
703 	String cols[] = { "TABLE_TYPE" };
704 	SQLite.TableResult tr = new SQLite.TableResult();
705 	tr.columns(cols);
706 	String row[] = new String[1];
707 	row[0] = "TABLE";
708 	tr.newrow(row);
709 	row = new String[1];
710 	row[0] = "VIEW";
711 	tr.newrow(row);
712 	JDBCResultSet rs = new JDBCResultSet(tr, null);
713 	return rs;
714     }
715 
716     @Override
getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)717     public ResultSet getColumns(String catalog, String schemaPattern,
718 				String tableNamePattern,
719 				String columnNamePattern)
720 	throws SQLException {
721 	if (conn.db == null) {
722 	    throw new SQLException("connection closed.");
723 	}
724 	JDBCStatement s = new JDBCStatement(conn);
725 	JDBCResultSet rs0 = null;
726 	try {
727 	    try {
728 		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
729 	    } catch (SQLite.Exception se) {
730 		throw new SQLException("schema reload failed", se);
731 	    }
732 	    rs0 = (JDBCResultSet)
733 		(s.executeQuery("PRAGMA table_info(" +
734 				SQLite.Shell.sql_quote(tableNamePattern) +
735 				")"));
736 	    s.close();
737 	} catch (SQLException e) {
738 	    throw e;
739 	} finally {
740 	    s.close();
741 	}
742 	if (rs0.tr.nrows < 1) {
743 	    throw new SQLException("no such table: " + tableNamePattern);
744 	}
745 	String cols[] = {
746 	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
747 	    "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME",
748 	    "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS",
749 	    "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
750 	    "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
751 	    "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE"
752 	};
753 	int types[] = {
754 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
755 	    Types.VARCHAR, Types.SMALLINT, Types.VARCHAR,
756 	    Types.INTEGER, Types.INTEGER, Types.INTEGER,
757 	    Types.INTEGER, Types.INTEGER, Types.VARCHAR,
758 	    Types.VARCHAR, Types.INTEGER, Types.INTEGER,
759 	    Types.INTEGER, Types.INTEGER, Types.VARCHAR
760 	};
761 	TableResultX tr = new TableResultX();
762 	tr.columns(cols);
763 	tr.sql_types(types);
764 	JDBCResultSet rs = new JDBCResultSet(tr, null);
765 	if (rs0.tr != null && rs0.tr.nrows > 0) {
766 	    Hashtable<String, Integer> h = new Hashtable<String, Integer>();
767 	    for (int i = 0; i < rs0.tr.ncolumns; i++) {
768 		h.put(rs0.tr.column[i], Integer.valueOf(i));
769 	    }
770 	    if (columnNamePattern != null &&
771 		columnNamePattern.charAt(0) == '%') {
772 		columnNamePattern = null;
773 	    }
774 	    for (int i = 0; i < rs0.tr.nrows; i++) {
775 		String r0[] = (String [])(rs0.tr.rows.elementAt(i));
776 		int col = h.get("name").intValue();
777 		if (columnNamePattern != null) {
778 		    if (r0[col].compareTo(columnNamePattern) != 0) {
779 			continue;
780 		    }
781 		}
782 		String row[] = new String[cols.length];
783 		row[0]  = "";
784 		row[1]  = "";
785 		row[2]  = tableNamePattern;
786 		row[3]  = r0[col];
787 		col = h.get("type").intValue();
788 		String typeStr = r0[col];
789 		int type = mapSqlType(typeStr);
790 		row[4]  = "" + type;
791 		row[5]  = mapTypeName(type);
792 		row[6]  = "" + getD(typeStr, type);
793 		row[7]  = "" + getM(typeStr, type);
794 		row[8]  = "10";
795 		row[9]  = "0";
796 		row[11] = null;
797 		col = h.get("dflt_value").intValue();
798 		row[12] = r0[col];
799 		row[13] = "0";
800 		row[14] = "0";
801 		row[15] = "65536";
802 		col = h.get("cid").intValue();
803 		row[16] = Integer.toString(Integer.parseInt(r0[col]) + 1);
804 		col = h.get("notnull").intValue();
805 		row[17] = (r0[col].charAt(0) == '0') ? "YES" : "NO";
806 		row[10] = (r0[col].charAt(0) == '0') ? "" + columnNullable :
807 			  "" + columnNoNulls;
808 		tr.newrow(row);
809 	    }
810 	}
811 	return rs;
812     }
813 
814     @Override
getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)815     public ResultSet getColumnPrivileges(String catalog, String schema,
816 					 String table,
817 					 String columnNamePattern)
818 	throws SQLException {
819 	String cols[] = {
820 	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
821 	    "COLUMN_NAME", "GRANTOR", "GRANTEE",
822 	    "PRIVILEGE", "IS_GRANTABLE"
823 	};
824 	int types[] = {
825 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
826 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
827 	    Types.VARCHAR, Types.VARCHAR
828 	};
829 	TableResultX tr = new TableResultX();
830 	tr.columns(cols);
831 	tr.sql_types(types);
832 	JDBCResultSet rs = new JDBCResultSet(tr, null);
833 	return rs;
834     }
835 
836     @Override
getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)837     public ResultSet getTablePrivileges(String catalog, String schemaPattern,
838 					String tableNamePattern)
839 	throws SQLException {
840 	String cols[] = {
841 	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
842 	    "COLUMN_NAME", "GRANTOR", "GRANTEE",
843 	    "PRIVILEGE", "IS_GRANTABLE"
844 	};
845 	int types[] = {
846 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
847 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
848 	    Types.VARCHAR, Types.VARCHAR
849 	};
850 	TableResultX tr = new TableResultX();
851 	tr.columns(cols);
852 	tr.sql_types(types);
853 	JDBCResultSet rs = new JDBCResultSet(tr, null);
854 	return rs;
855     }
856 
857     @Override
getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)858     public ResultSet getBestRowIdentifier(String catalog, String schema,
859 					  String table, int scope,
860 					  boolean nullable)
861 	throws SQLException {
862 	JDBCStatement s0 = new JDBCStatement(conn);
863 	JDBCResultSet rs0 = null;
864 	JDBCStatement s1 = new JDBCStatement(conn);
865 	JDBCResultSet rs1 = null;
866 	try {
867 	    try {
868 		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
869 	    } catch (SQLite.Exception se) {
870 		throw new SQLException("schema reload failed", se);
871 	    }
872 	    rs0 = (JDBCResultSet)
873 		(s0.executeQuery("PRAGMA index_list(" +
874 				 SQLite.Shell.sql_quote(table) + ")"));
875 	    rs1 = (JDBCResultSet)
876 		(s1.executeQuery("PRAGMA table_info(" +
877 				 SQLite.Shell.sql_quote(table) + ")"));
878 	} catch (SQLException e) {
879 	    throw e;
880 	} finally {
881 	    s0.close();
882 	    s1.close();
883 	}
884 	String cols[] = {
885 	    "SCOPE", "COLUMN_NAME", "DATA_TYPE",
886 	    "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
887 	    "DECIMAL_DIGITS", "PSEUDO_COLUMN"
888 	};
889 	int types[] = {
890 	    Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
891 	    Types.VARCHAR, Types.INTEGER, Types.INTEGER,
892 	    Types.SMALLINT, Types.SMALLINT
893 	};
894 	TableResultX tr = new TableResultX();
895 	tr.columns(cols);
896 	tr.sql_types(types);
897 	JDBCResultSet rs = new JDBCResultSet(tr, null);
898 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0 &&
899 	    rs1 != null && rs1.tr != null && rs1.tr.nrows > 0) {
900 	    Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
901 	    for (int i = 0; i < rs0.tr.ncolumns; i++) {
902 		h0.put(rs0.tr.column[i], Integer.valueOf(i));
903 	    }
904 	    Hashtable<String, Integer> h1 = new Hashtable<String, Integer>();
905 	    for (int i = 0; i < rs1.tr.ncolumns; i++) {
906 		h1.put(rs1.tr.column[i], Integer.valueOf(i));
907 	    }
908 	    for (int i = 0; i < rs0.tr.nrows; i++) {
909 		String r0[] = (String [])(rs0.tr.rows.elementAt(i));
910 		int col = h0.get("unique").intValue();
911 		String uniq = r0[col];
912 		col = h0.get("name").intValue();
913 		String iname = r0[col];
914 		if (uniq.charAt(0) == '0') {
915 		    continue;
916 		}
917 		JDBCStatement s2 = new JDBCStatement(conn);
918 		JDBCResultSet rs2 = null;
919 		try {
920 		    rs2 = (JDBCResultSet)
921 			(s2.executeQuery("PRAGMA index_info(" +
922 					 SQLite.Shell.sql_quote(iname) + ")"));
923 		} catch (SQLException e) {
924 		} finally {
925 		    s2.close();
926 		}
927 		if (rs2 == null || rs2.tr == null || rs2.tr.nrows <= 0) {
928 		    continue;
929 		}
930 		Hashtable<String, Integer> h2 =
931 		    new Hashtable<String, Integer>();
932 		for (int k = 0; k < rs2.tr.ncolumns; k++) {
933 		    h2.put(rs2.tr.column[k], Integer.valueOf(k));
934 		}
935 		for (int k = 0; k < rs2.tr.nrows; k++) {
936 		    String r2[] = (String [])(rs2.tr.rows.elementAt(k));
937 		    col = h2.get("name").intValue();
938 		    String cname = r2[col];
939 		    for (int m = 0; m < rs1.tr.nrows; m++) {
940 			String r1[] = (String [])(rs1.tr.rows.elementAt(m));
941 			col = h1.get("name").intValue();
942 			if (cname.compareTo(r1[col]) == 0) {
943 			    String row[] = new String[cols.length];
944 			    row[0] = "" + scope;
945 			    row[1] = cname;
946 			    row[2] = "" + Types.VARCHAR;
947 			    row[3] = "VARCHAR";
948 			    row[4] = "65536";
949 			    row[5] = "0";
950 			    row[6] = "0";
951 			    row[7] = "" + bestRowNotPseudo;
952 			    tr.newrow(row);
953 			}
954 		    }
955 		}
956 	    }
957 	}
958 	if (tr.nrows <= 0) {
959 	    String row[] = new String[cols.length];
960 	    row[0] = "" + scope;
961 	    row[1] = "_ROWID_";
962 	    row[2] = "" + Types.INTEGER;
963 	    row[3] = "INTEGER";
964 	    row[4] = "10";
965 	    row[5] = "0";
966 	    row[6] = "0";
967 	    row[7] = "" + bestRowPseudo;
968 	    tr.newrow(row);
969 	}
970 	return rs;
971     }
972 
973     @Override
getVersionColumns(String catalog, String schema, String table)974     public ResultSet getVersionColumns(String catalog, String schema,
975 				       String table) throws SQLException {
976 	String cols[] = {
977 	    "SCOPE", "COLUMN_NAME", "DATA_TYPE",
978 	    "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
979 	    "DECIMAL_DIGITS", "PSEUDO_COLUMN"
980 	};
981 	int types[] = {
982 	    Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
983 	    Types.VARCHAR, Types.INTEGER, Types.INTEGER,
984 	    Types.SMALLINT, Types.SMALLINT
985 	};
986 	TableResultX tr = new TableResultX();
987 	tr.columns(cols);
988 	tr.sql_types(types);
989 	JDBCResultSet rs = new JDBCResultSet(tr, null);
990 	return rs;
991     }
992 
993     @Override
getPrimaryKeys(String catalog, String schema, String table)994     public ResultSet getPrimaryKeys(String catalog, String schema,
995 				    String table) throws SQLException {
996 	JDBCStatement s0 = new JDBCStatement(conn);
997 	JDBCResultSet rs0 = null;
998 	try {
999 	    try {
1000 		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
1001 	    } catch (SQLite.Exception se) {
1002 		throw new SQLException("schema reload failed", se);
1003 	    }
1004 	    rs0 = (JDBCResultSet)
1005 		(s0.executeQuery("PRAGMA index_list(" +
1006 				 SQLite.Shell.sql_quote(table) + ")"));
1007 	} catch (SQLException e) {
1008 	    throw e;
1009 	} finally {
1010 	    s0.close();
1011 	}
1012 	String cols[] = {
1013 	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
1014 	    "COLUMN_NAME", "KEY_SEQ", "PK_NAME"
1015 	};
1016 	int types[] = {
1017 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1018 	    Types.VARCHAR, Types.SMALLINT, Types.VARCHAR
1019 	};
1020 	TableResultX tr = new TableResultX();
1021 	tr.columns(cols);
1022 	tr.sql_types(types);
1023 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1024 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
1025 	    Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
1026 	    for (int i = 0; i < rs0.tr.ncolumns; i++) {
1027 		h0.put(rs0.tr.column[i], Integer.valueOf(i));
1028 	    }
1029 	    for (int i = 0; i < rs0.tr.nrows; i++) {
1030 		String r0[] = (String [])(rs0.tr.rows.elementAt(i));
1031 		int col = h0.get("unique").intValue();
1032 		String uniq = r0[col];
1033 		col = h0.get("name").intValue();
1034 		String iname = r0[col];
1035 		if (uniq.charAt(0) == '0') {
1036 		    continue;
1037 		}
1038 		JDBCStatement s1 = new JDBCStatement(conn);
1039 		JDBCResultSet rs1 = null;
1040 		try {
1041 		    rs1 = (JDBCResultSet)
1042 			(s1.executeQuery("PRAGMA index_info(" +
1043 					 SQLite.Shell.sql_quote(iname) + ")"));
1044 		} catch (SQLException e) {
1045 		} finally {
1046 		    s1.close();
1047 		}
1048 		if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
1049 		    continue;
1050 		}
1051 		Hashtable<String, Integer> h1 =
1052 		    new Hashtable<String, Integer>();
1053 		for (int k = 0; k < rs1.tr.ncolumns; k++) {
1054 		    h1.put(rs1.tr.column[k], Integer.valueOf(k));
1055 		}
1056 		for (int k = 0; k < rs1.tr.nrows; k++) {
1057 		    String r1[] = (String [])(rs1.tr.rows.elementAt(k));
1058 		    String row[] = new String[cols.length];
1059 		    row[0]  = "";
1060 		    row[1]  = "";
1061 		    row[2]  = table;
1062 		    col = h1.get("name").intValue();
1063 		    row[3] = r1[col];
1064 		    col = h1.get("seqno").intValue();
1065 		    row[4]  = Integer.toString(Integer.parseInt(r1[col]) + 1);
1066 		    row[5]  = iname;
1067 		    tr.newrow(row);
1068 		}
1069 	    }
1070 	}
1071 	if (tr.nrows > 0) {
1072 	    return rs;
1073 	}
1074 	JDBCStatement s1 = new JDBCStatement(conn);
1075 	try {
1076 	    rs0 = (JDBCResultSet)
1077 		(s1.executeQuery("PRAGMA table_info(" +
1078 				 SQLite.Shell.sql_quote(table) + ")"));
1079 	} catch (SQLException e) {
1080 	    throw e;
1081 	} finally {
1082 	    s1.close();
1083 	}
1084 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
1085 	    Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
1086 	    for (int i = 0; i < rs0.tr.ncolumns; i++) {
1087 		h0.put(rs0.tr.column[i], Integer.valueOf(i));
1088 	    }
1089 	    for (int i = 0; i < rs0.tr.nrows; i++) {
1090 		String r0[] = (String [])(rs0.tr.rows.elementAt(i));
1091 		int col = h0.get("type").intValue();
1092 		String type = r0[col];
1093 		if (!type.equalsIgnoreCase("integer")) {
1094 		    continue;
1095 		}
1096 		col = h0.get("pk").intValue();
1097 		String pk = r0[col];
1098 		if (pk.charAt(0) == '0') {
1099 		    continue;
1100 		}
1101 		String row[] = new String[cols.length];
1102 		row[0]  = "";
1103 		row[1]  = "";
1104 		row[2]  = table;
1105 		col = h0.get("name").intValue();
1106 		row[3] = r0[col];
1107 		col = h0.get("cid").intValue();
1108 		row[4] = Integer.toString(Integer.parseInt(r0[col]) + 1);
1109 		row[5] = "";
1110 		tr.newrow(row);
1111 	    }
1112 	}
1113 	return rs;
1114     }
1115 
internalImportedKeys(String table, String pktable, JDBCResultSet in, TableResultX out)1116     private void internalImportedKeys(String table, String pktable,
1117 				      JDBCResultSet in, TableResultX out) {
1118 	Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
1119 	for (int i = 0; i < in.tr.ncolumns; i++) {
1120 	    h0.put(in.tr.column[i], Integer.valueOf(i));
1121 	}
1122 	for (int i = 0; i < in.tr.nrows; i++) {
1123 	    String r0[] = (String [])(in.tr.rows.elementAt(i));
1124 	    int col = h0.get("table").intValue();
1125 	    String pktab = r0[col];
1126 	    if (pktable != null && !pktable.equalsIgnoreCase(pktab)) {
1127 		continue;
1128 	    }
1129 	    col = h0.get("from").intValue();
1130 	    String fkcol = r0[col];
1131 	    col = h0.get("to").intValue();
1132 	    String pkcol = r0[col];
1133 	    col = h0.get("seq").intValue();
1134 	    String seq = r0[col];
1135 	    String row[] = new String[out.ncolumns];
1136 	    row[0]  = "";
1137 	    row[1]  = "";
1138 	    row[2]  = pktab;
1139 	    row[3]  = pkcol;
1140 	    row[4]  = "";
1141 	    row[5]  = "";
1142 	    row[6]  = table;
1143 	    row[7]  = fkcol == null ? pkcol : fkcol;
1144 	    row[8]  = Integer.toString(Integer.parseInt(seq) + 1);
1145 	    row[9]  =
1146 		"" + java.sql.DatabaseMetaData.importedKeyNoAction;
1147 	    row[10] =
1148 		"" + java.sql.DatabaseMetaData.importedKeyNoAction;
1149 	    row[11] = null;
1150 	    row[12] = null;
1151 	    row[13] =
1152 		"" + java.sql.DatabaseMetaData.importedKeyNotDeferrable;
1153 	    out.newrow(row);
1154 	}
1155     }
1156 
1157     @Override
getImportedKeys(String catalog, String schema, String table)1158     public ResultSet getImportedKeys(String catalog, String schema,
1159 				     String table) throws SQLException {
1160 	JDBCStatement s0 = new JDBCStatement(conn);
1161 	JDBCResultSet rs0 = null;
1162 	try {
1163 	    try {
1164 		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
1165 	    } catch (SQLite.Exception se) {
1166 		throw new SQLException("schema reload failed", se);
1167 	    }
1168 	    rs0 = (JDBCResultSet)
1169 		(s0.executeQuery("PRAGMA foreign_key_list(" +
1170 				 SQLite.Shell.sql_quote(table) + ")"));
1171 	} catch (SQLException e) {
1172 	    throw e;
1173 	} finally {
1174 	    s0.close();
1175 	}
1176 	String cols[] = {
1177 	    "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
1178 	    "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
1179 	    "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
1180 	    "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
1181 	    "PK_NAME", "DEFERRABILITY"
1182 	};
1183 	int types[] = {
1184 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1185 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1186 	    Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
1187 	    Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
1188 	    Types.VARCHAR, Types.SMALLINT
1189 	};
1190 	TableResultX tr = new TableResultX();
1191 	tr.columns(cols);
1192 	tr.sql_types(types);
1193 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1194 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
1195 	    internalImportedKeys(table, null, rs0, tr);
1196 	}
1197 	return rs;
1198     }
1199 
1200     @Override
getExportedKeys(String catalog, String schema, String table)1201     public ResultSet getExportedKeys(String catalog, String schema,
1202 				     String table) throws SQLException {
1203 	String cols[] = {
1204 	    "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
1205 	    "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
1206 	    "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
1207 	    "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
1208 	    "PK_NAME", "DEFERRABILITY"
1209 	};
1210 	int types[] = {
1211 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1212 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1213 	    Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
1214 	    Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
1215 	    Types.VARCHAR, Types.SMALLINT
1216 	};
1217 	TableResultX tr = new TableResultX();
1218 	tr.columns(cols);
1219 	tr.sql_types(types);
1220 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1221 	return rs;
1222     }
1223 
1224     @Override
getCrossReference(String primaryCatalog, String primarySchema, String primaryTable, String foreignCatalog, String foreignSchema, String foreignTable)1225     public ResultSet getCrossReference(String primaryCatalog,
1226 				       String primarySchema,
1227 				       String primaryTable,
1228 				       String foreignCatalog,
1229 				       String foreignSchema,
1230 				       String foreignTable)
1231 	throws SQLException {
1232 	JDBCResultSet rs0 = null;
1233 	if (foreignTable != null && foreignTable.charAt(0) != '%') {
1234 	    JDBCStatement s0 = new JDBCStatement(conn);
1235 	    try {
1236 		try {
1237 		    conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
1238 		} catch (SQLite.Exception se) {
1239 		    throw new SQLException("schema reload failed", se);
1240 		}
1241 		rs0 = (JDBCResultSet)
1242 		    (s0.executeQuery("PRAGMA foreign_key_list(" +
1243 				     SQLite.Shell.sql_quote(foreignTable) + ")"));
1244 	    } catch (SQLException e) {
1245 		throw e;
1246 	    } finally {
1247 		s0.close();
1248 	    }
1249 	}
1250 	String cols[] = {
1251 	    "PKTABLE_CAT", "PKTABLE_SCHEM", "PKTABLE_NAME",
1252 	    "PKCOLUMN_NAME", "FKTABLE_CAT", "FKTABLE_SCHEM",
1253 	    "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
1254 	    "UPDATE_RULE", "DELETE_RULE", "FK_NAME",
1255 	    "PK_NAME", "DEFERRABILITY"
1256 	};
1257 	int types[] = {
1258 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1259 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1260 	    Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
1261 	    Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
1262 	    Types.VARCHAR, Types.SMALLINT
1263 	};
1264 	TableResultX tr = new TableResultX();
1265 	tr.columns(cols);
1266 	tr.sql_types(types);
1267 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1268 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
1269 	    String pktable = null;
1270 	    if (primaryTable != null && primaryTable.charAt(0) != '%') {
1271 		pktable = primaryTable;
1272 	    }
1273 	    internalImportedKeys(foreignTable, pktable, rs0, tr);
1274 	}
1275 	return rs;
1276     }
1277 
1278     @Override
getTypeInfo()1279     public ResultSet getTypeInfo() throws SQLException {
1280 	String cols[] = {
1281 	    "TYPE_NAME", "DATA_TYPE", "PRECISION",
1282 	    "LITERAL_PREFIX", "LITERAL_SUFFIX", "CREATE_PARAMS",
1283 	    "NULLABLE", "CASE_SENSITIVE", "SEARCHABLE",
1284 	    "UNSIGNED_ATTRIBUTE", "FIXED_PREC_SCALE", "AUTO_INCREMENT",
1285 	    "LOCAL_TYPE_NAME", "MINIMUM_SCALE", "MAXIMUM_SCALE",
1286 	    "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "NUM_PREC_RADIX"
1287 	};
1288 	int types[] = {
1289 	    Types.VARCHAR, Types.SMALLINT, Types.INTEGER,
1290 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1291 	    Types.SMALLINT, Types.BIT, Types.SMALLINT,
1292 	    Types.BIT, Types.BIT, Types.BIT,
1293 	    Types.VARCHAR, Types.SMALLINT, Types.SMALLINT,
1294 	    Types.INTEGER, Types.INTEGER, Types.INTEGER
1295 	};
1296 	TableResultX tr = new TableResultX();
1297 	tr.columns(cols);
1298 	tr.sql_types(types);
1299 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1300 	String row1[] = {
1301 	    "VARCHAR", "" + Types.VARCHAR, "65536",
1302 	    "'", "'", null,
1303 	    "" + typeNullable, "1", "" + typeSearchable,
1304 	    "0", "0", "0",
1305 	    null, "0", "0",
1306 	    "0", "0", "0"
1307 	};
1308 	tr.newrow(row1);
1309 	String row2[] = {
1310 	    "INTEGER", "" + Types.INTEGER, "32",
1311 	    null, null, null,
1312 	    "" + typeNullable, "0", "" + typeSearchable,
1313 	    "0", "0", "1",
1314 	    null, "0", "0",
1315 	    "0", "0", "2"
1316 	};
1317 	tr.newrow(row2);
1318 	String row3[] = {
1319 	    "DOUBLE", "" + Types.DOUBLE, "16",
1320 	    null, null, null,
1321 	    "" + typeNullable, "0", "" + typeSearchable,
1322 	    "0", "0", "1",
1323 	    null, "0", "0",
1324 	    "0", "0", "10"
1325 	};
1326 	tr.newrow(row3);
1327 	String row4[] = {
1328 	    "FLOAT", "" + Types.FLOAT, "7",
1329 	    null, null, null,
1330 	    "" + typeNullable, "0", "" + typeSearchable,
1331 	    "0", "0", "1",
1332 	    null, "0", "0",
1333 	    "0", "0", "10"
1334 	};
1335 	tr.newrow(row4);
1336 	String row5[] = {
1337 	    "SMALLINT", "" + Types.SMALLINT, "16",
1338 	    null, null, null,
1339 	    "" + typeNullable, "0", "" + typeSearchable,
1340 	    "0", "0", "1",
1341 	    null, "0", "0",
1342 	    "0", "0", "2"
1343 	};
1344 	tr.newrow(row5);
1345 	String row6[] = {
1346 	    "BIT", "" + Types.BIT, "1",
1347 	    null, null, null,
1348 	    "" + typeNullable, "0", "" + typeSearchable,
1349 	    "0", "0", "1",
1350 	    null, "0", "0",
1351 	    "0", "0", "2"
1352 	};
1353 	tr.newrow(row6);
1354 	String row7[] = {
1355 	    "TIMESTAMP", "" + Types.TIMESTAMP, "30",
1356 	    null, null, null,
1357 	    "" + typeNullable, "0", "" + typeSearchable,
1358 	    "0", "0", "1",
1359 	    null, "0", "0",
1360 	    "0", "0", "0"
1361 	};
1362 	tr.newrow(row7);
1363 	String row8[] = {
1364 	    "DATE", "" + Types.DATE, "10",
1365 	    null, null, null,
1366 	    "" + typeNullable, "0", "" + typeSearchable,
1367 	    "0", "0", "1",
1368 	    null, "0", "0",
1369 	    "0", "0", "0"
1370 	};
1371 	tr.newrow(row8);
1372 	String row9[] = {
1373 	    "TIME", "" + Types.TIME, "8",
1374 	    null, null, null,
1375 	    "" + typeNullable, "0", "" + typeSearchable,
1376 	    "0", "0", "1",
1377 	    null, "0", "0",
1378 	    "0", "0", "0"
1379 	};
1380 	tr.newrow(row9);
1381 	String row10[] = {
1382 	    "BINARY", "" + Types.BINARY, "65536",
1383 	    null, null, null,
1384 	    "" + typeNullable, "0", "" + typeSearchable,
1385 	    "0", "0", "1",
1386 	    null, "0", "0",
1387 	    "0", "0", "0"
1388 	};
1389 	tr.newrow(row10);
1390 	String row11[] = {
1391 	    "VARBINARY", "" + Types.VARBINARY, "65536",
1392 	    null, null, null,
1393 	    "" + typeNullable, "0", "" + typeSearchable,
1394 	    "0", "0", "1",
1395 	    null, "0", "0",
1396 	    "0", "0", "0"
1397 	};
1398 	tr.newrow(row11);
1399 	String row12[] = {
1400 	    "REAL", "" + Types.REAL, "16",
1401 	    null, null, null,
1402 	    "" + typeNullable, "0", "" + typeSearchable,
1403 	    "0", "0", "1",
1404 	    null, "0", "0",
1405 	    "0", "0", "10"
1406 	};
1407 	tr.newrow(row12);
1408 	return rs;
1409     }
1410 
1411     @Override
getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)1412     public ResultSet getIndexInfo(String catalog, String schema, String table,
1413 				  boolean unique, boolean approximate)
1414 	throws SQLException {
1415 	JDBCStatement s0 = new JDBCStatement(conn);
1416 	JDBCResultSet rs0 = null;
1417 	try {
1418 	    try {
1419 		conn.db.exec("SELECT 1 FROM sqlite_master LIMIT 1", null);
1420 	    } catch (SQLite.Exception se) {
1421 		throw new SQLException("schema reload failed", se);
1422 	    }
1423 	    rs0 = (JDBCResultSet)
1424 		(s0.executeQuery("PRAGMA index_list(" +
1425 				 SQLite.Shell.sql_quote(table) + ")"));
1426 	} catch (SQLException e) {
1427 	    throw e;
1428 	} finally {
1429 	    s0.close();
1430 	}
1431 	String cols[] = {
1432 	    "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
1433 	    "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME",
1434 	    "TYPE", "ORDINAL_POSITION", "COLUMN_NAME",
1435 	    "ASC_OR_DESC", "CARDINALITY", "PAGES",
1436 	    "FILTER_CONDITION"
1437 	};
1438 	int types[] = {
1439 	    Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
1440 	    Types.BIT, Types.VARCHAR, Types.VARCHAR,
1441 	    Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
1442 	    Types.VARCHAR, Types.INTEGER, Types.INTEGER,
1443 	    Types.VARCHAR
1444 	};
1445 	TableResultX tr = new TableResultX();
1446 	tr.columns(cols);
1447 	tr.sql_types(types);
1448 	JDBCResultSet rs = new JDBCResultSet(tr, null);
1449 	if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
1450 	    Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
1451 	    for (int i = 0; i < rs0.tr.ncolumns; i++) {
1452 		h0.put(rs0.tr.column[i], Integer.valueOf(i));
1453 	    }
1454 	    for (int i = 0; i < rs0.tr.nrows; i++) {
1455 		String r0[] = (String [])(rs0.tr.rows.elementAt(i));
1456 		int col = h0.get("unique").intValue();
1457 		String uniq = r0[col];
1458 		col = h0.get("name").intValue();
1459 		String iname = r0[col];
1460 		if (unique && uniq.charAt(0) == '0') {
1461 		    continue;
1462 		}
1463 		JDBCStatement s1 = new JDBCStatement(conn);
1464 		JDBCResultSet rs1 = null;
1465 		try {
1466 		    rs1 = (JDBCResultSet)
1467 			(s1.executeQuery("PRAGMA index_info(" +
1468 					 SQLite.Shell.sql_quote(iname) + ")"));
1469 		} catch (SQLException e) {
1470 		} finally {
1471 		    s1.close();
1472 		}
1473 		if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
1474 		    continue;
1475 		}
1476 		Hashtable<String, Integer> h1 =
1477 		    new Hashtable<String, Integer>();
1478 		for (int k = 0; k < rs1.tr.ncolumns; k++) {
1479 		    h1.put(rs1.tr.column[k], Integer.valueOf(k));
1480 		}
1481 		for (int k = 0; k < rs1.tr.nrows; k++) {
1482 		    String r1[] = (String [])(rs1.tr.rows.elementAt(k));
1483 		    String row[] = new String[cols.length];
1484 		    row[0]  = "";
1485 		    row[1]  = "";
1486 		    row[2]  = table;
1487 		    row[3]  = (uniq.charAt(0) != '0' ||
1488 			(iname.charAt(0) == '(' &&
1489 			 iname.indexOf(" autoindex ") > 0)) ? "0" : "1";
1490 		    row[4]  = "";
1491 		    row[5]  = iname;
1492 		    row[6]  = "" + tableIndexOther;
1493 		    col = h1.get("seqno").intValue();
1494 		    row[7]  = Integer.toString(Integer.parseInt(r1[col]) + 1);
1495 		    col = h1.get("name").intValue();
1496 		    row[8]  = r1[col];
1497 		    row[9]  = "A";
1498 		    row[10] = "0";
1499 		    row[11] = "0";
1500 		    row[12] = null;
1501 		    tr.newrow(row);
1502 		}
1503 	    }
1504 	}
1505 	return rs;
1506     }
1507 
1508     @Override
supportsResultSetType(int type)1509     public boolean supportsResultSetType(int type) throws SQLException {
1510 	return type == ResultSet.TYPE_FORWARD_ONLY ||
1511 	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
1512 	    type == ResultSet.TYPE_SCROLL_SENSITIVE;
1513     }
1514 
1515     @Override
supportsResultSetConcurrency(int type, int concurrency)1516     public boolean supportsResultSetConcurrency(int type, int concurrency)
1517 	throws SQLException {
1518 	if (type == ResultSet.TYPE_FORWARD_ONLY ||
1519 	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
1520 	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
1521 	    return concurrency == ResultSet.CONCUR_READ_ONLY ||
1522 		concurrency == ResultSet.CONCUR_UPDATABLE;
1523 	}
1524 	return false;
1525     }
1526 
1527     @Override
ownUpdatesAreVisible(int type)1528     public boolean ownUpdatesAreVisible(int type) throws SQLException {
1529 	if (type == ResultSet.TYPE_FORWARD_ONLY ||
1530 	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
1531 	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
1532 	    return true;
1533 	}
1534 	return false;
1535     }
1536 
1537     @Override
ownDeletesAreVisible(int type)1538     public boolean ownDeletesAreVisible(int type) throws SQLException {
1539 	if (type == ResultSet.TYPE_FORWARD_ONLY ||
1540 	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
1541 	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
1542 	    return true;
1543 	}
1544 	return false;
1545     }
1546 
1547     @Override
ownInsertsAreVisible(int type)1548     public boolean ownInsertsAreVisible(int type) throws SQLException {
1549 	if (type == ResultSet.TYPE_FORWARD_ONLY ||
1550 	    type == ResultSet.TYPE_SCROLL_INSENSITIVE ||
1551 	    type == ResultSet.TYPE_SCROLL_SENSITIVE) {
1552 	    return true;
1553 	}
1554 	return false;
1555     }
1556 
1557     @Override
othersUpdatesAreVisible(int type)1558     public boolean othersUpdatesAreVisible(int type) throws SQLException {
1559 	return false;
1560     }
1561 
1562     @Override
othersDeletesAreVisible(int type)1563     public boolean othersDeletesAreVisible(int type) throws SQLException {
1564 	return false;
1565     }
1566 
1567     @Override
othersInsertsAreVisible(int type)1568     public boolean othersInsertsAreVisible(int type) throws SQLException {
1569 	return false;
1570     }
1571 
1572     @Override
updatesAreDetected(int type)1573     public boolean updatesAreDetected(int type) throws SQLException {
1574 	return false;
1575     }
1576 
1577     @Override
deletesAreDetected(int type)1578     public boolean deletesAreDetected(int type) throws SQLException {
1579 	return false;
1580     }
1581 
1582     @Override
insertsAreDetected(int type)1583     public boolean insertsAreDetected(int type) throws SQLException {
1584 	return false;
1585     }
1586 
1587     @Override
supportsBatchUpdates()1588     public boolean supportsBatchUpdates() throws SQLException {
1589 	return true;
1590     }
1591 
1592     @Override
getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)1593     public ResultSet getUDTs(String catalog, String schemaPattern,
1594 		      String typeNamePattern, int[] types)
1595 	throws SQLException {
1596 	return null;
1597     }
1598 
1599     @Override
getConnection()1600     public Connection getConnection() throws SQLException {
1601 	return conn;
1602     }
1603 
mapTypeName(int type)1604     static String mapTypeName(int type) {
1605 	switch (type) {
1606 	case Types.INTEGER:	return "integer";
1607 	case Types.SMALLINT:	return "smallint";
1608 	case Types.FLOAT:	return "float";
1609 	case Types.DOUBLE:	return "double";
1610 	case Types.TIMESTAMP:	return "timestamp";
1611 	case Types.DATE:	return "date";
1612 	case Types.TIME:	return "time";
1613 	case Types.BINARY:	return "binary";
1614 	case Types.VARBINARY:	return "varbinary";
1615 	case Types.REAL:	return "real";
1616 	}
1617 	return "varchar";
1618     }
1619 
mapSqlType(String type)1620     static int mapSqlType(String type) {
1621 	if (type == null) {
1622 	    return Types.VARCHAR;
1623 	}
1624 	type = type.toLowerCase();
1625 	if (type.startsWith("inter")) {
1626 	    return Types.VARCHAR;
1627 	}
1628 	if (type.startsWith("numeric") ||
1629 	    type.startsWith("int")) {
1630 	    return Types.INTEGER;
1631 	}
1632 	if (type.startsWith("tinyint") ||
1633 	    type.startsWith("smallint")) {
1634 	    return Types.SMALLINT;
1635 	}
1636 	if (type.startsWith("float")) {
1637 	    return Types.FLOAT;
1638 	}
1639 	if (type.startsWith("double")) {
1640 	    return Types.DOUBLE;
1641 	}
1642 	if (type.startsWith("datetime") ||
1643 	    type.startsWith("timestamp")) {
1644 	    return Types.TIMESTAMP;
1645 	}
1646 	if (type.startsWith("date")) {
1647 	    return Types.DATE;
1648 	}
1649 	if (type.startsWith("time")) {
1650 	    return Types.TIME;
1651 	}
1652 	if (type.startsWith("blob")) {
1653 	    return Types.BINARY;
1654 	}
1655 	if (type.startsWith("binary")) {
1656 	    return Types.BINARY;
1657 	}
1658 	if (type.startsWith("varbinary")) {
1659 	    return Types.VARBINARY;
1660 	}
1661 	if (type.startsWith("real")) {
1662 	    return Types.REAL;
1663 	}
1664 	return Types.VARCHAR;
1665     }
1666 
getM(String typeStr, int type)1667     static int getM(String typeStr, int type) {
1668 	int m = 65536;
1669 	switch (type) {
1670 	case Types.INTEGER:	m = 11; break;
1671 	case Types.SMALLINT:	m = 6;  break;
1672 	case Types.FLOAT:	m = 25; break;
1673 	case Types.REAL:
1674 	case Types.DOUBLE:	m = 54; break;
1675 	case Types.TIMESTAMP:	return 30;
1676 	case Types.DATE:	return 10;
1677 	case Types.TIME:	return 8;
1678 	}
1679 	typeStr = typeStr.toLowerCase();
1680 	int i1 = typeStr.indexOf('(');
1681 	if (i1 > 0) {
1682 	    ++i1;
1683 	    int i2 = typeStr.indexOf(',', i1);
1684 	    if (i2 < 0) {
1685 		i2 = typeStr.indexOf(')', i1);
1686 	    }
1687 	    if (i2 - i1 > 0) {
1688 		String num = typeStr.substring(i1, i2);
1689 		try {
1690 		    m = java.lang.Integer.parseInt(num, 10);
1691 		} catch (NumberFormatException e) {
1692 		}
1693 	    }
1694 	}
1695 	return m;
1696     }
1697 
getD(String typeStr, int type)1698     static int getD(String typeStr, int type) {
1699 	int d = 0;
1700 	switch (type) {
1701 	case Types.INTEGER:	d = 10; break;
1702 	case Types.SMALLINT:	d = 5;  break;
1703 	case Types.FLOAT:	d = 24; break;
1704 	case Types.REAL:
1705 	case Types.DOUBLE:	d = 53; break;
1706 	default:		return getM(typeStr, type);
1707 	}
1708 	typeStr = typeStr.toLowerCase();
1709 	int i1 = typeStr.indexOf('(');
1710 	if (i1 > 0) {
1711 	    ++i1;
1712 	    int i2 = typeStr.indexOf(',', i1);
1713 	    if (i2 < 0) {
1714 		return getM(typeStr, type);
1715 	    }
1716 	    i1 = i2;
1717 	    i2 = typeStr.indexOf(')', i1);
1718 	    if (i2 - i1 > 0) {
1719 		String num = typeStr.substring(i1, i2);
1720 		try {
1721 		    d = java.lang.Integer.parseInt(num, 10);
1722 		} catch (NumberFormatException e) {
1723 		}
1724 	    }
1725 	}
1726 	return d;
1727     }
1728 
1729     @Override
supportsSavepoints()1730     public boolean supportsSavepoints() {
1731 	return false;
1732     }
1733 
1734     @Override
supportsNamedParameters()1735     public boolean supportsNamedParameters() {
1736 	return false;
1737     }
1738 
1739     @Override
supportsMultipleOpenResults()1740     public boolean supportsMultipleOpenResults() {
1741 	return false;
1742     }
1743 
1744     @Override
supportsGetGeneratedKeys()1745     public boolean supportsGetGeneratedKeys() {
1746 	return false;
1747     }
1748 
1749     @Override
supportsResultSetHoldability(int x)1750     public boolean supportsResultSetHoldability(int x) {
1751 	return false;
1752     }
1753 
1754     @Override
supportsStatementPooling()1755     public boolean supportsStatementPooling() {
1756 	return false;
1757     }
1758 
1759     @Override
locatorsUpdateCopy()1760     public boolean locatorsUpdateCopy() throws SQLException {
1761 	throw new SQLException("not supported");
1762     }
1763 
1764     @Override
getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)1765     public ResultSet getSuperTypes(String catalog, String schemaPattern,
1766 			    String typeNamePattern)
1767 	throws SQLException {
1768 	throw new SQLException("not supported");
1769     }
1770 
1771     @Override
getSuperTables(String catalog, String schemaPattern, String tableNamePattern)1772     public ResultSet getSuperTables(String catalog, String schemaPattern,
1773 				    String tableNamePattern)
1774 	throws SQLException {
1775 	throw new SQLException("not supported");
1776     }
1777 
1778     @Override
getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)1779     public ResultSet getAttributes(String catalog, String schemaPattern,
1780 				   String typeNamePattern,
1781 				   String attributeNamePattern)
1782 	throws SQLException {
1783 	throw new SQLException("not supported");
1784     }
1785 
1786     @Override
getResultSetHoldability()1787     public int getResultSetHoldability() throws SQLException {
1788 	return ResultSet.HOLD_CURSORS_OVER_COMMIT;
1789     }
1790 
1791     @Override
getDatabaseMajorVersion()1792     public int getDatabaseMajorVersion() {
1793 	return SQLite.JDBC.MAJORVERSION;
1794     }
1795 
1796     @Override
getDatabaseMinorVersion()1797     public int getDatabaseMinorVersion() {
1798 	return SQLite.Constants.drv_minor;
1799     }
1800 
1801     @Override
getJDBCMajorVersion()1802     public int getJDBCMajorVersion() {
1803 	return 1;
1804     }
1805 
1806     @Override
getJDBCMinorVersion()1807     public int getJDBCMinorVersion() {
1808 	return 0;
1809     }
1810 
1811     @Override
getSQLStateType()1812     public int getSQLStateType() throws SQLException {
1813 	return sqlStateXOpen;
1814     }
1815 
1816     @Override
getRowIdLifetime()1817     public RowIdLifetime getRowIdLifetime() throws SQLException {
1818 	return RowIdLifetime.ROWID_UNSUPPORTED;
1819     }
1820 
1821     @Override
getSchemas(String cat, String schema)1822     public ResultSet getSchemas(String cat, String schema)
1823 	throws SQLException {
1824 	throw new SQLException("not supported");
1825     }
1826 
1827     @Override
supportsStoredFunctionsUsingCallSyntax()1828     public boolean supportsStoredFunctionsUsingCallSyntax()
1829 	throws SQLException {
1830 	return false;
1831     }
1832 
1833     @Override
autoCommitFailureClosesAllResultSets()1834     public boolean autoCommitFailureClosesAllResultSets()
1835 	throws SQLException {
1836 	return false;
1837     }
1838 
1839     @Override
getClientInfoProperties()1840     public ResultSet getClientInfoProperties() throws SQLException {
1841 	throw new SQLException("unsupported");
1842     }
1843 
1844     @Override
getFunctions(String cat, String schema, String func)1845     public ResultSet getFunctions(String cat, String schema, String func)
1846 	throws SQLException {
1847 	throw new SQLException("unsupported");
1848     }
1849 
1850     @Override
getFunctionColumns(String cat, String schema, String func, String colpat)1851     public ResultSet getFunctionColumns(String cat, String schema,
1852 					String func, String colpat)
1853 	throws SQLException {
1854 	throw new SQLException("unsupported");
1855     }
1856 
1857     @Override
unwrap(java.lang.Class<T> iface)1858     public <T> T unwrap(java.lang.Class<T> iface) throws SQLException {
1859 	throw new SQLException("unsupported");
1860     }
1861 
1862     @Override
isWrapperFor(java.lang.Class iface)1863     public boolean isWrapperFor(java.lang.Class iface) throws SQLException {
1864 	return false;
1865     }
1866 
1867 }
1868