ShopChest/libs/org/sqlite/MetaData.java
2015-09-06 11:58:25 +02:00

1215 lines
40 KiB
Java

/*
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package org.sqlite;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Struct;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
class MetaData implements DatabaseMetaData
{
private Conn conn;
private PreparedStatement getTables = null, getTableTypes = null, getTypeInfo = null, getCatalogs = null,
getSchemas = null, getUDTs = null, getColumnsTblName = null, getSuperTypes = null, getSuperTables = null,
getTablePrivileges = null, getIndexInfo = null, getProcedures = null, getProcedureColumns = null,
getAttributes = null, getBestRowIdentifier = null, getVersionColumns = null, getColumnPrivileges = null;
/** Used by PrepStmt to save generating a new statement every call. */
private PreparedStatement getGeneratedKeys = null;
MetaData(Conn conn) {
this.conn = conn;
}
void checkOpen() throws SQLException {
if (conn == null)
throw new SQLException("connection closed");
}
synchronized void close() throws SQLException {
if (conn == null)
return;
try {
if (getTables != null)
getTables.close();
if (getTableTypes != null)
getTableTypes.close();
if (getTypeInfo != null)
getTypeInfo.close();
if (getCatalogs != null)
getCatalogs.close();
if (getSchemas != null)
getSchemas.close();
if (getUDTs != null)
getUDTs.close();
if (getColumnsTblName != null)
getColumnsTblName.close();
if (getSuperTypes != null)
getSuperTypes.close();
if (getSuperTables != null)
getSuperTables.close();
if (getTablePrivileges != null)
getTablePrivileges.close();
if (getIndexInfo != null)
getIndexInfo.close();
if (getProcedures != null)
getProcedures.close();
if (getProcedureColumns != null)
getProcedureColumns.close();
if (getAttributes != null)
getAttributes.close();
if (getBestRowIdentifier != null)
getBestRowIdentifier.close();
if (getVersionColumns != null)
getVersionColumns.close();
if (getColumnPrivileges != null)
getColumnPrivileges.close();
if (getGeneratedKeys != null)
getGeneratedKeys.close();
getTables = null;
getTableTypes = null;
getTypeInfo = null;
getCatalogs = null;
getSchemas = null;
getUDTs = null;
getColumnsTblName = null;
getSuperTypes = null;
getSuperTables = null;
getTablePrivileges = null;
getIndexInfo = null;
getProcedures = null;
getProcedureColumns = null;
getAttributes = null;
getBestRowIdentifier = null;
getVersionColumns = null;
getColumnPrivileges = null;
getGeneratedKeys = null;
}
finally {
conn = null;
}
}
public Connection getConnection() {
return conn;
}
public int getDatabaseMajorVersion() {
return 3;
}
public int getDatabaseMinorVersion() {
return 0;
}
public int getDriverMajorVersion() {
return 1;
}
public int getDriverMinorVersion() {
return 1;
}
public int getJDBCMajorVersion() {
return 2;
}
public int getJDBCMinorVersion() {
return 1;
}
public int getDefaultTransactionIsolation() {
return Connection.TRANSACTION_SERIALIZABLE;
}
public int getMaxBinaryLiteralLength() {
return 0;
}
public int getMaxCatalogNameLength() {
return 0;
}
public int getMaxCharLiteralLength() {
return 0;
}
public int getMaxColumnNameLength() {
return 0;
}
public int getMaxColumnsInGroupBy() {
return 0;
}
public int getMaxColumnsInIndex() {
return 0;
}
public int getMaxColumnsInOrderBy() {
return 0;
}
public int getMaxColumnsInSelect() {
return 0;
}
public int getMaxColumnsInTable() {
return 0;
}
public int getMaxConnections() {
return 0;
}
public int getMaxCursorNameLength() {
return 0;
}
public int getMaxIndexLength() {
return 0;
}
public int getMaxProcedureNameLength() {
return 0;
}
public int getMaxRowSize() {
return 0;
}
public int getMaxSchemaNameLength() {
return 0;
}
public int getMaxStatementLength() {
return 0;
}
public int getMaxStatements() {
return 0;
}
public int getMaxTableNameLength() {
return 0;
}
public int getMaxTablesInSelect() {
return 0;
}
public int getMaxUserNameLength() {
return 0;
}
public int getResultSetHoldability() {
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
public int getSQLStateType() {
return sqlStateSQL99;
}
public String getDatabaseProductName() {
return "SQLite";
}
public String getDatabaseProductVersion() throws SQLException {
return conn.libversion();
}
public String getDriverName() {
return "SQLiteJDBC";
}
public String getDriverVersion() {
return conn.getDriverVersion();
}
public String getExtraNameCharacters() {
return "";
}
public String getCatalogSeparator() {
return ".";
}
public String getCatalogTerm() {
return "catalog";
}
public String getSchemaTerm() {
return "schema";
}
public String getProcedureTerm() {
return "not_implemented";
}
public String getSearchStringEscape() {
return null;
}
public String getIdentifierQuoteString() {
return " ";
}
public String getSQLKeywords() {
return "";
}
public String getNumericFunctions() {
return "";
}
public String getStringFunctions() {
return "";
}
public String getSystemFunctions() {
return "";
}
public String getTimeDateFunctions() {
return "";
}
public String getURL() {
return conn.url();
}
public String getUserName() {
return null;
}
public boolean allProceduresAreCallable() {
return false;
}
public boolean allTablesAreSelectable() {
return true;
}
public boolean dataDefinitionCausesTransactionCommit() {
return false;
}
public boolean dataDefinitionIgnoredInTransactions() {
return false;
}
public boolean doesMaxRowSizeIncludeBlobs() {
return false;
}
public boolean deletesAreDetected(int type) {
return false;
}
public boolean insertsAreDetected(int type) {
return false;
}
public boolean isCatalogAtStart() {
return true;
}
public boolean locatorsUpdateCopy() {
return false;
}
public boolean nullPlusNonNullIsNull() {
return true;
}
public boolean nullsAreSortedAtEnd() {
return !nullsAreSortedAtStart();
}
public boolean nullsAreSortedAtStart() {
return true;
}
public boolean nullsAreSortedHigh() {
return true;
}
public boolean nullsAreSortedLow() {
return !nullsAreSortedHigh();
}
public boolean othersDeletesAreVisible(int type) {
return false;
}
public boolean othersInsertsAreVisible(int type) {
return false;
}
public boolean othersUpdatesAreVisible(int type) {
return false;
}
public boolean ownDeletesAreVisible(int type) {
return false;
}
public boolean ownInsertsAreVisible(int type) {
return false;
}
public boolean ownUpdatesAreVisible(int type) {
return false;
}
public boolean storesLowerCaseIdentifiers() {
return false;
}
public boolean storesLowerCaseQuotedIdentifiers() {
return false;
}
public boolean storesMixedCaseIdentifiers() {
return true;
}
public boolean storesMixedCaseQuotedIdentifiers() {
return false;
}
public boolean storesUpperCaseIdentifiers() {
return false;
}
public boolean storesUpperCaseQuotedIdentifiers() {
return false;
}
public boolean supportsAlterTableWithAddColumn() {
return false;
}
public boolean supportsAlterTableWithDropColumn() {
return false;
}
public boolean supportsANSI92EntryLevelSQL() {
return false;
}
public boolean supportsANSI92FullSQL() {
return false;
}
public boolean supportsANSI92IntermediateSQL() {
return false;
}
public boolean supportsBatchUpdates() {
return true;
}
public boolean supportsCatalogsInDataManipulation() {
return false;
}
public boolean supportsCatalogsInIndexDefinitions() {
return false;
}
public boolean supportsCatalogsInPrivilegeDefinitions() {
return false;
}
public boolean supportsCatalogsInProcedureCalls() {
return false;
}
public boolean supportsCatalogsInTableDefinitions() {
return false;
}
public boolean supportsColumnAliasing() {
return true;
}
public boolean supportsConvert() {
return false;
}
public boolean supportsConvert(int fromType, int toType) {
return false;
}
public boolean supportsCorrelatedSubqueries() {
return false;
}
public boolean supportsDataDefinitionAndDataManipulationTransactions() {
return true;
}
public boolean supportsDataManipulationTransactionsOnly() {
return false;
}
public boolean supportsDifferentTableCorrelationNames() {
return false;
}
public boolean supportsExpressionsInOrderBy() {
return true;
}
public boolean supportsMinimumSQLGrammar() {
return true;
}
public boolean supportsCoreSQLGrammar() {
return true;
}
public boolean supportsExtendedSQLGrammar() {
return false;
}
public boolean supportsLimitedOuterJoins() {
return true;
}
public boolean supportsFullOuterJoins() {
return false;
}
public boolean supportsGetGeneratedKeys() {
return false;
}
public boolean supportsGroupBy() {
return true;
}
public boolean supportsGroupByBeyondSelect() {
return false;
}
public boolean supportsGroupByUnrelated() {
return false;
}
public boolean supportsIntegrityEnhancementFacility() {
return false;
}
public boolean supportsLikeEscapeClause() {
return false;
}
public boolean supportsMixedCaseIdentifiers() {
return true;
}
public boolean supportsMixedCaseQuotedIdentifiers() {
return false;
}
public boolean supportsMultipleOpenResults() {
return false;
}
public boolean supportsMultipleResultSets() {
return false;
}
public boolean supportsMultipleTransactions() {
return true;
}
public boolean supportsNamedParameters() {
return true;
}
public boolean supportsNonNullableColumns() {
return true;
}
public boolean supportsOpenCursorsAcrossCommit() {
return false;
}
public boolean supportsOpenCursorsAcrossRollback() {
return false;
}
public boolean supportsOpenStatementsAcrossCommit() {
return false;
}
public boolean supportsOpenStatementsAcrossRollback() {
return false;
}
public boolean supportsOrderByUnrelated() {
return false;
}
public boolean supportsOuterJoins() {
return true;
}
public boolean supportsPositionedDelete() {
return false;
}
public boolean supportsPositionedUpdate() {
return false;
}
public boolean supportsResultSetConcurrency(int t, int c) {
return t == ResultSet.TYPE_FORWARD_ONLY && c == ResultSet.CONCUR_READ_ONLY;
}
public boolean supportsResultSetHoldability(int h) {
return h == ResultSet.CLOSE_CURSORS_AT_COMMIT;
}
public boolean supportsResultSetType(int t) {
return t == ResultSet.TYPE_FORWARD_ONLY;
}
public boolean supportsSavepoints() {
return false;
}
public boolean supportsSchemasInDataManipulation() {
return false;
}
public boolean supportsSchemasInIndexDefinitions() {
return false;
}
public boolean supportsSchemasInPrivilegeDefinitions() {
return false;
}
public boolean supportsSchemasInProcedureCalls() {
return false;
}
public boolean supportsSchemasInTableDefinitions() {
return false;
}
public boolean supportsSelectForUpdate() {
return false;
}
public boolean supportsStatementPooling() {
return false;
}
public boolean supportsStoredProcedures() {
return false;
}
public boolean supportsSubqueriesInComparisons() {
return false;
}
public boolean supportsSubqueriesInExists() {
return true;
} // TODO: check
public boolean supportsSubqueriesInIns() {
return true;
} // TODO: check
public boolean supportsSubqueriesInQuantifieds() {
return false;
}
public boolean supportsTableCorrelationNames() {
return false;
}
public boolean supportsTransactionIsolationLevel(int level) {
return level == Connection.TRANSACTION_SERIALIZABLE;
}
public boolean supportsTransactions() {
return true;
}
public boolean supportsUnion() {
return true;
}
public boolean supportsUnionAll() {
return true;
}
public boolean updatesAreDetected(int type) {
return false;
}
public boolean usesLocalFilePerTable() {
return false;
}
public boolean usesLocalFiles() {
return true;
}
public boolean isReadOnly() throws SQLException {
return conn.isReadOnly();
}
public ResultSet getAttributes(String c, String s, String t, String a) throws SQLException {
if (getAttributes == null)
getAttributes = conn.prepareStatement("select " + "null as TYPE_CAT, " + "null as TYPE_SCHEM, "
+ "null as TYPE_NAME, " + "null as ATTR_NAME, " + "null as DATA_TYPE, "
+ "null as ATTR_TYPE_NAME, " + "null as ATTR_SIZE, " + "null as DECIMAL_DIGITS, "
+ "null as NUM_PREC_RADIX, " + "null as NULLABLE, " + "null as REMARKS, " + "null as ATTR_DEF, "
+ "null as SQL_DATA_TYPE, " + "null as SQL_DATETIME_SUB, " + "null as CHAR_OCTET_LENGTH, "
+ "null as ORDINAL_POSITION, " + "null as IS_NULLABLE, " + "null as SCOPE_CATALOG, "
+ "null as SCOPE_SCHEMA, " + "null as SCOPE_TABLE, " + "null as SOURCE_DATA_TYPE limit 0;");
return getAttributes.executeQuery();
}
public ResultSet getBestRowIdentifier(String c, String s, String t, int scope, boolean n) throws SQLException {
if (getBestRowIdentifier == null)
getBestRowIdentifier = conn.prepareStatement("select " + "null as SCOPE, " + "null as COLUMN_NAME, "
+ "null as DATA_TYPE, " + "null as TYPE_NAME, " + "null as COLUMN_SIZE, "
+ "null as BUFFER_LENGTH, " + "null as DECIMAL_DIGITS, " + "null as PSEUDO_COLUMN limit 0;");
return getBestRowIdentifier.executeQuery();
}
public ResultSet getColumnPrivileges(String c, String s, String t, String colPat) throws SQLException {
if (getColumnPrivileges == null)
getColumnPrivileges = conn.prepareStatement("select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, "
+ "null as TABLE_NAME, " + "null as COLUMN_NAME, " + "null as GRANTOR, " + "null as GRANTEE, "
+ "null as PRIVILEGE, " + "null as IS_GRANTABLE limit 0;");
return getColumnPrivileges.executeQuery();
}
public ResultSet getColumns(String c, String s, String tbl, String colPat) throws SQLException {
Statement stat = conn.createStatement();
ResultSet rs;
String sql;
checkOpen();
if (getColumnsTblName == null)
getColumnsTblName = conn.prepareStatement("select tbl_name from sqlite_master where tbl_name like ?;");
// determine exact table name
getColumnsTblName.setString(1, tbl);
rs = getColumnsTblName.executeQuery();
if (!rs.next())
return rs;
tbl = rs.getString(1);
rs.close();
sql = "select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, " + "'" + escape(tbl) + "' as TABLE_NAME, "
+ "cn as COLUMN_NAME, " + "ct as DATA_TYPE, " + "tn as TYPE_NAME, " + "2000000000 as COLUMN_SIZE, "
+ "2000000000 as BUFFER_LENGTH, " + "10 as DECIMAL_DIGITS, " + "10 as NUM_PREC_RADIX, "
+ "colnullable as NULLABLE, " + "null as REMARKS, " + "null as COLUMN_DEF, "
+ "0 as SQL_DATA_TYPE, " + "0 as SQL_DATETIME_SUB, " + "2000000000 as CHAR_OCTET_LENGTH, "
+ "ordpos as ORDINAL_POSITION, " + "(case colnullable when 0 then 'N' when 1 then 'Y' else '' end)"
+ " as IS_NULLABLE, " + "null as SCOPE_CATLOG, " + "null as SCOPE_SCHEMA, "
+ "null as SCOPE_TABLE, " + "null as SOURCE_DATA_TYPE from (";
// the command "pragma table_info('tablename')" does not embed
// like a normal select statement so we must extract the information
// and then build a resultset from unioned select statements
rs = stat.executeQuery("pragma table_info ('" + escape(tbl) + "');");
boolean colFound = false;
for (int i = 0; rs.next(); i++) {
String colName = rs.getString(2);
String colType = rs.getString(3);
String colNotNull = rs.getString(4);
int colNullable = 2;
if (colNotNull != null)
colNullable = colNotNull.equals("0") ? 1 : 0;
if (colFound)
sql += " union all ";
colFound = true;
colType = colType == null ? "TEXT" : colType.toUpperCase();
int colJavaType = -1;
if (colType.equals("INT") || colType.equals("INTEGER"))
colJavaType = Types.INTEGER;
else if (colType.equals("TEXT"))
colJavaType = Types.VARCHAR;
else if (colType.equals("FLOAT"))
colJavaType = Types.FLOAT;
else
colJavaType = Types.VARCHAR;
sql += "select " + i + " as ordpos, " + colNullable + " as colnullable, '" + colJavaType + "' as ct, '"
+ escape(colName) + "' as cn, '" + escape(colType) + "' as tn";
if (colPat != null)
sql += " where upper(cn) like upper('" + escape(colPat) + "')";
}
sql += colFound ? ");" : "select null as ordpos, null as colnullable, " + "null as cn, null as tn) limit 0;";
rs.close();
return stat.executeQuery(sql);
}
public ResultSet getCrossReference(String pc, String ps, String pt, String fc, String fs, String ft)
throws SQLException {
if (pt == null)
return getExportedKeys(fc, fs, ft);
if (ft == null)
return getImportedKeys(pc, ps, pt);
StringBuilder query = new StringBuilder();
query.append(String.format("select %s as PKTABLE_CAT, %s as PKTABLE_SCHEM, %s as PKTABLE_NAME, ", quote(pc),
quote(ps), quote(pt))
+ "'' as PKCOLUMN_NAME, "
+ String.format("%s as FKTABLE_CAT, %s as FKTABLE_SCHEM, %s as FKTABLE_NAME, ", quote(fc), quote(fs),
quote(ft))
+ "'' as FKCOLUMN_NAME, -1 as KEY_SEQ, 3 as UPDATE_RULE, "
+ "3 as DELETE_RULE, '' as FK_NAME, '' as PK_NAME, "
+ Integer.toString(importedKeyInitiallyDeferred)
+ " as DEFERRABILITY limit 0;");
return conn.createStatement().executeQuery(query.toString());
}
public ResultSet getSchemas() throws SQLException {
if (getSchemas == null)
getSchemas = conn.prepareStatement("select " + "null as TABLE_SCHEM, " + "null as TABLE_CATALOG "
+ "limit 0;");
getSchemas.clearParameters();
return getSchemas.executeQuery();
}
public ResultSet getCatalogs() throws SQLException {
if (getCatalogs == null)
getCatalogs = conn.prepareStatement("select null as TABLE_CAT limit 0;");
getCatalogs.clearParameters();
return getCatalogs.executeQuery();
}
public ResultSet getPrimaryKeys(String c, String s, String table) throws SQLException {
String sql;
ResultSet rs;
Statement stat = conn.createStatement();
rs = stat.executeQuery("pragma table_info('" + escape(table) + "');");
sql = "select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, " + "'" + escape(table) + "' as TABLE_NAME, "
+ "cn as COLUMN_NAME, " + "0 as KEY_SEQ, " + "null as PK_NAME from (";
int i;
for (i = 0; rs.next(); i++) {
String colName = rs.getString(2);
if (!rs.getBoolean(6)) {
i--;
continue;
}
if (i > 0)
sql += " union all ";
sql += "select '" + escape(colName) + "' as cn";
}
sql += i == 0 ? "select null as cn) limit 0;" : ");";
rs.close();
return stat.executeQuery(sql);
}
private static String quote(String tableName) {
if (tableName == null)
return "null";
else
return String.format("'%s'", tableName);
}
public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException {
StringBuilder exportedKeysQuery = new StringBuilder();
exportedKeysQuery.append(String.format("select %s as PKTABLE_CAT, %s as PKTABLE_SCHEM, %s as PKTABLE_NAME, ",
quote(catalog), quote(schema), quote(table))
+ String.format("pcn as PKCOLUMN_NAME, %s as FKTABLE_CAT, %s as FKTABLE_SCHEM, ", quote(catalog),
quote(schema))
+ "fkn as FKTABLE_NAME, fcn as FKCOLUMN_NAME, "
+ "ks as KEY_SEQ, "
+ "ur as UPDATE_RULE, "
+ "dr as DELETE_RULE, "
+ "'' as FK_NAME, "
+ "'' as PK_NAME, "
+ Integer.toString(importedKeyInitiallyDeferred) + " as DEFERRABILITY from (");
// retrieve table list
String tableListQuery = String.format("select name from sqlite_master where type = 'table'");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(tableListQuery);
ArrayList<String> tableList = new ArrayList<String>();
while (rs.next())
tableList.add(rs.getString(1));
rs.close();
// find imported keys for each table
int count = 0;
for (String targetTable : tableList) {
String foreignKeyQuery = String.format("pragma foreign_key_list('%s');", escape(targetTable));
try {
ResultSet fk = stat.executeQuery(foreignKeyQuery);
for (; fk.next();) {
int keySeq = fk.getInt(2) + 1;
String PKTabName = fk.getString(3);
String FKColName = fk.getString(4);
String PKColName = fk.getString(5);
String updateRule = fk.getString(6);
String deleteRule = fk.getString(7);
if (PKTabName == null || !PKTabName.equals(table))
continue;
if (count > 0)
exportedKeysQuery.append(" union all ");
exportedKeysQuery.append("select " + Integer.toString(keySeq) + " as ks," + "'"
+ escape(targetTable) + "' as fkn," + "'" + escape(FKColName) + "' as fcn," + "'"
+ escape(PKColName) + "' as pcn," + String.format("case '%s' ", escape(updateRule))
+ String.format("when 'NO ACTION' then %d ", importedKeyNoAction)
+ String.format("when 'CASCADE' then %d ", importedKeyCascade)
+ String.format("when 'RESTRICT' then %d ", importedKeyRestrict)
+ String.format("when 'SET NULL' then %d ", importedKeySetNull)
+ String.format("when 'SET DEFAULT' then %d ", importedKeySetDefault) + "end as ur,"
+ String.format("case '%s' ", escape(deleteRule))
+ String.format("when 'NO ACTION' then %d ", importedKeyNoAction)
+ String.format("when 'CASCADE' then %d ", importedKeyCascade)
+ String.format("when 'RESTRICT' then %d ", importedKeyRestrict)
+ String.format("when 'SET NULL' then %d ", importedKeySetNull)
+ String.format("when 'SET DEFAULT' then %d ", importedKeySetDefault) + "end as dr");
count++;
}
exportedKeysQuery.append(");");
fk.close();
}
catch (SQLException e) {
// continue
}
}
String sql = (count > 0) ? exportedKeysQuery.toString() : (String.format(
"select %s as PKTABLE_CAT, %s as PKTABLE_SCHEM, %s as PKTABLE_NAME, ", quote(catalog), quote(schema),
quote(table))
+ "'' as PKCOLUMN_NAME, "
+ String.format("%s as FKTABLE_CAT, %s as FKTABLE_SCHEM, ", quote(catalog), quote(schema))
+ "'' as FKTABLE_NAME, "
+ "'' as FKCOLUMN_NAME, "
+ "-1 as KEY_SEQ, "
+ "3 as UPDATE_RULE, "
+ "3 as DELETE_RULE, " + "'' as FK_NAME, " + "'' as PK_NAME, " + "5 as DEFERRABILITY limit 0;");
return stat.executeQuery(sql);
}
public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException {
String sql;
ResultSet rs = null;
Statement stat = conn.createStatement();
sql = String.format("select %s as PKTABLE_CAT, %s as PKTABLE_SCHEM, ", quote(catalog), quote(schema))
+ String
.format(
"ptn as PKTABLE_NAME, pcn as PKCOLUMN_NAME, %s as FKTABLE_CAT, %s as FKTABLE_SCHEM, %s as FKTABLE_NAME, ",
quote(catalog), quote(schema), quote(table)) + "fcn as FKCOLUMN_NAME, "
+ "ks as KEY_SEQ, " + "ur as UPDATE_RULE, " + "dr as DELETE_RULE, " + "'' as FK_NAME, "
+ "'' as PK_NAME, " + Integer.toString(importedKeyInitiallyDeferred) + " as DEFERRABILITY from (";
// Use a try catch block to avoid "query does not return ResultSet" error
try {
rs = stat.executeQuery("pragma foreign_key_list('" + escape(table) + "');");
int i;
for (i = 0; rs.next(); i++) {
int keySeq = rs.getInt(2) + 1;
String PKTabName = rs.getString(3);
String FKColName = rs.getString(4);
String PKColName = rs.getString(5);
String updateRule = rs.getString(6);
String deleteRule = rs.getString(7);
if (i > 0)
sql += " union all ";
sql += String.format("select %d as ks,", keySeq)
+ String.format("'%s' as ptn, '%s' as fcn, '%s' as pcn,", escape(PKTabName), escape(FKColName),
escape(PKColName)) + String.format("case '%s' ", escape(updateRule))
+ String.format("when 'NO ACTION' then %d ", importedKeyNoAction)
+ String.format("when 'CASCADE' then %d ", importedKeyCascade)
+ String.format("when 'RESTRICT' then %d ", importedKeyRestrict)
+ String.format("when 'SET NULL' then %d ", importedKeySetNull)
+ String.format("when 'SET DEFAULT' then %d ", importedKeySetDefault) + "end as ur,"
+ String.format("case '%s' ", escape(deleteRule))
+ String.format("when 'NO ACTION' then %d ", importedKeyNoAction)
+ String.format("when 'CASCADE' then %d ", importedKeyCascade)
+ String.format("when 'RESTRICT' then %d ", importedKeyRestrict)
+ String.format("when 'SET NULL' then %d ", importedKeySetNull)
+ String.format("when 'SET DEFAULT' then %d ", importedKeySetDefault) + "end as dr";
}
sql += ");";
rs.close();
}
catch (SQLException e) {
sql += "select -1 as ks, '' as ptn, '' as fcn, '' as pcn, " + importedKeyNoAction + " as ur, "
+ importedKeyNoAction + " as dr) limit 0;";
}
return stat.executeQuery(sql);
}
public ResultSet getIndexInfo(String c, String s, String t, boolean u, boolean approximate) throws SQLException {
String sql;
ResultSet rs = null;
Statement stat = conn.createStatement();
sql = "select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, " + "'" + escape(t) + "' as TABLE_NAME, "
+ "un as NON_UNIQUE, " + "null as INDEX_QUALIFIER, " + "n as INDEX_NAME, "
+ Integer.toString(tableIndexOther) + " as TYPE, " + "op as ORDINAL_POSITION, " + "cn as COLUMN_NAME, "
+ "null as ASC_OR_DESC, " + "0 as CARDINALITY, " + "0 as PAGES, " + "null as FILTER_CONDITION from (";
// Use a try catch block to avoid "query does not return ResultSet" error
try {
ArrayList<ArrayList> indexList = new ArrayList<ArrayList>();
rs = stat.executeQuery("pragma index_list('" + escape(t) + "');");
while (rs.next()) {
indexList.add(new ArrayList());
indexList.get(indexList.size() - 1).add(rs.getString(2));
indexList.get(indexList.size() - 1).add(rs.getInt(3));
}
rs.close();
int i = 0;
Iterator indexIterator = indexList.iterator();
ArrayList currentIndex;
while (indexIterator.hasNext()) {
currentIndex = (ArrayList) indexIterator.next();
String indexName = currentIndex.get(0).toString();
int unique = (Integer) currentIndex.get(1);
rs = stat.executeQuery("pragma index_info('" + escape(indexName) + "');");
for (; rs.next(); i++) {
int ordinalPosition = rs.getInt(1) + 1;
String colName = rs.getString(3);
if (i > 0)
sql += " union all ";
sql += "select " + Integer.toString(1 - unique) + " as un," + "'" + escape(indexName) + "' as n,"
+ Integer.toString(ordinalPosition) + " as op," + "'" + escape(colName) + "' as cn";
i++;
}
rs.close();
}
sql += ");";
}
catch (SQLException e) {
sql += "select null as un, null as n, null as op, null as cn) limit 0;";
}
return stat.executeQuery(sql);
}
public ResultSet getProcedureColumns(String c, String s, String p, String colPat) throws SQLException {
if (getProcedures == null)
getProcedureColumns = conn.prepareStatement("select " + "null as PROCEDURE_CAT, "
+ "null as PROCEDURE_SCHEM, " + "null as PROCEDURE_NAME, " + "null as COLUMN_NAME, "
+ "null as COLUMN_TYPE, " + "null as DATA_TYPE, " + "null as TYPE_NAME, " + "null as PRECISION, "
+ "null as LENGTH, " + "null as SCALE, " + "null as RADIX, " + "null as NULLABLE, "
+ "null as REMARKS limit 0;");
return getProcedureColumns.executeQuery();
}
public ResultSet getProcedures(String c, String s, String p) throws SQLException {
if (getProcedures == null)
getProcedures = conn.prepareStatement("select " + "null as PROCEDURE_CAT, " + "null as PROCEDURE_SCHEM, "
+ "null as PROCEDURE_NAME, " + "null as UNDEF1, " + "null as UNDEF2, " + "null as UNDEF3, "
+ "null as REMARKS, " + "null as PROCEDURE_TYPE limit 0;");
return getProcedures.executeQuery();
}
public ResultSet getSuperTables(String c, String s, String t) throws SQLException {
if (getSuperTables == null)
getSuperTables = conn.prepareStatement("select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, "
+ "null as TABLE_NAME, " + "null as SUPERTABLE_NAME limit 0;");
return getSuperTables.executeQuery();
}
public ResultSet getSuperTypes(String c, String s, String t) throws SQLException {
if (getSuperTypes == null)
getSuperTypes = conn.prepareStatement("select " + "null as TYPE_CAT, " + "null as TYPE_SCHEM, "
+ "null as TYPE_NAME, " + "null as SUPERTYPE_CAT, " + "null as SUPERTYPE_SCHEM, "
+ "null as SUPERTYPE_NAME limit 0;");
return getSuperTypes.executeQuery();
}
public ResultSet getTablePrivileges(String c, String s, String t) throws SQLException {
if (getTablePrivileges == null)
getTablePrivileges = conn.prepareStatement("select " + "null as TABLE_CAT, " + "null as TABLE_SCHEM, "
+ "null as TABLE_NAME, " + "null as GRANTOR, " + "null as GRANTEE, " + "null as PRIVILEGE, "
+ "null as IS_GRANTABLE limit 0;");
return getTablePrivileges.executeQuery();
}
public synchronized ResultSet getTables(String c, String s, String t, String[] types) throws SQLException {
checkOpen();
t = (t == null || "".equals(t)) ? "%" : t.toUpperCase();
String sql = "select" + " null as TABLE_CAT," + " null as TABLE_SCHEM," + " name as TABLE_NAME,"
+ " upper(type) as TABLE_TYPE," + " null as REMARKS," + " null as TYPE_CAT," + " null as TYPE_SCHEM,"
+ " null as TYPE_NAME," + " null as SELF_REFERENCING_COL_NAME," + " null as REF_GENERATION"
+ " from (select name, type from sqlite_master union all"
+ " select name, type from sqlite_temp_master)" + " where TABLE_NAME like '" + escape(t) + "'";
if (types != null) {
sql += " and TABLE_TYPE in (";
for (int i = 0; i < types.length; i++) {
if (i > 0)
sql += ", ";
sql += "'" + types[i].toUpperCase() + "'";
}
sql += ")";
}
sql += ";";
return conn.createStatement().executeQuery(sql);
}
public ResultSet getTableTypes() throws SQLException {
checkOpen();
if (getTableTypes == null)
getTableTypes = conn.prepareStatement("select 'TABLE' as TABLE_TYPE"
+ " union select 'VIEW' as TABLE_TYPE;");
getTableTypes.clearParameters();
return getTableTypes.executeQuery();
}
public ResultSet getTypeInfo() throws SQLException {
if (getTypeInfo == null) {
getTypeInfo = conn.prepareStatement("select " + "tn as TYPE_NAME, " + "dt as DATA_TYPE, "
+ "0 as PRECISION, " + "null as LITERAL_PREFIX, " + "null as LITERAL_SUFFIX, "
+ "null as CREATE_PARAMS, "
+ typeNullable
+ " as NULLABLE, "
+ "1 as CASE_SENSITIVE, "
+ typeSearchable
+ " as SEARCHABLE, "
+ "0 as UNSIGNED_ATTRIBUTE, "
+ "0 as FIXED_PREC_SCALE, "
+ "0 as AUTO_INCREMENT, "
+ "null as LOCAL_TYPE_NAME, "
+ "0 as MINIMUM_SCALE, "
+ "0 as MAXIMUM_SCALE, "
+ "0 as SQL_DATA_TYPE, "
+ "0 as SQL_DATETIME_SUB, "
+ "10 as NUM_PREC_RADIX from ("
+ " select 'BLOB' as tn, "
+ Types.BLOB
+ " as dt union"
+ " select 'NULL' as tn, "
+ Types.NULL
+ " as dt union"
+ " select 'REAL' as tn, "
+ Types.REAL
+ " as dt union"
+ " select 'TEXT' as tn, "
+ Types.VARCHAR
+ " as dt union"
+ " select 'INTEGER' as tn, "
+ Types.INTEGER + " as dt" + ") order by TYPE_NAME;");
}
getTypeInfo.clearParameters();
return getTypeInfo.executeQuery();
}
public ResultSet getUDTs(String c, String s, String t, int[] types) throws SQLException {
if (getUDTs == null)
getUDTs = conn.prepareStatement("select " + "null as TYPE_CAT, " + "null as TYPE_SCHEM, "
+ "null as TYPE_NAME, " + "null as CLASS_NAME, " + "null as DATA_TYPE, " + "null as REMARKS, "
+ "null as BASE_TYPE " + "limit 0;");
getUDTs.clearParameters();
return getUDTs.executeQuery();
}
public ResultSet getVersionColumns(String c, String s, String t) throws SQLException {
if (getVersionColumns == null)
getVersionColumns = conn.prepareStatement("select " + "null as SCOPE, " + "null as COLUMN_NAME, "
+ "null as DATA_TYPE, " + "null as TYPE_NAME, " + "null as COLUMN_SIZE, "
+ "null as BUFFER_LENGTH, " + "null as DECIMAL_DIGITS, " + "null as PSEUDO_COLUMN limit 0;");
return getVersionColumns.executeQuery();
}
ResultSet getGeneratedKeys() throws SQLException {
if (getGeneratedKeys == null)
getGeneratedKeys = conn.prepareStatement("select last_insert_rowid();");
return getGeneratedKeys.executeQuery();
}
/** Replace all instances of ' with '' */
private String escape(final String val) {
// TODO: this function is ugly, pass this work off to SQLite, then we
// don't have to worry about Unicode 4, other characters needing
// escaping, etc.
int len = val.length();
StringBuffer buf = new StringBuffer(len);
for (int i = 0; i < len; i++) {
if (val.charAt(i) == '\'')
buf.append('\'');
buf.append(val.charAt(i));
}
return buf.toString();
}
public Struct createStruct(String t, Object[] attr) throws SQLException {
throw new SQLException("Not yet implemented by SQLite JDBC driver");
}
public ResultSet getFunctionColumns(String a, String b, String c, String d) throws SQLException {
throw new SQLException("Not yet implemented by SQLite JDBC driver");
}
}