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