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