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