Skip to content

Commit

Permalink
Introduced named parameters in the SQL
Browse files Browse the repository at this point in the history
  • Loading branch information
johncurrier committed Oct 25, 2005
1 parent 4baf05f commit 54b3530
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 39 deletions.
16 changes: 11 additions & 5 deletions src/net/sourceforge/schemaspy/dbTypes/db2.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ driverPath=c:/Program Files/IBM/SQLLIB/java/db2java.zip
# or specify "-dbThreads 1" on the command line.
#dbThreads=1

# all of these are optional:
selectViewSql=select text from syscat.views where viewname=? and viewschema=?
selectCheckConstraintsSql=select constname, tabname table_name, text from syscat.checks where tabschema=?
selectTableIdsSql=select tableid table_id, tabname table_name from syscat.tables where tabschema=?
selectIndexIdsSql=select iid index_id, indname index_name, tabname table_name from syscat.indexes where tabschema=?
# all of these selects are optional:
# these named parameters are supported: :schema, :owner, :table and :view

# return text that represents a specific :view / :schema
selectViewSql=select text from syscat.views where viewname=:view and viewschema=:schema

# return table_name, constraint_name and text for a specific :schema
selectCheckConstraintsSql=select constname constraint_name, tabname table_name, text from syscat.checks where tabschema=:schema

selectTableIdsSql=select tableid table_id, tabname table_name from syscat.tables where tabschema=:schema
selectIndexIdsSql=select iid index_id, indname index_name, tabname table_name from syscat.indexes where tabschema=:schema
10 changes: 7 additions & 3 deletions src/net/sourceforge/schemaspy/dbTypes/mssql.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ driverPath=C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC/lib/msbase
# or specify "-dbThreads 1" on the command line.
#dbThreads=1

selectViewSql=select text from syscomments sc, sysobjects so where sc.id=so.id and so.name=?
# all of these selects are optional:
# these named parameters are supported: :schema, :owner, :table and :view

# untested...comment it out if it blows up
#selectCheckConstraintsSql=select distinct a.name constname, text from sysobjects a, syscomments b, sysobjects c where a.id = b.id and a.type = 'C'
# return text that represents a specific :view / :schema
selectViewSql=select text from syscomments sc, sysobjects so where sc.id=so.id and so.name=:table

# return table_name, constraint_name and text for a specific :schema
#selectCheckConstraintsSql=select distinct a.name constraint_name, text from sysobjects a, syscomments b, sysobjects c where a.id = b.id and a.type = 'C'
10 changes: 7 additions & 3 deletions src/net/sourceforge/schemaspy/dbTypes/mysql.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ driverPath=c:/mysql/mysql-connector-java-3.1.8-bin.jar
# or specify "-dbThreads 1" on the command line.
#dbThreads=1

# the following SQL is optional (and untested with MySql)
# the following SQL is optional
# fill it in if you want to see the SQL used to create your views or your check constraints
# send it back to schemaspy.sourceforge.net if it works
# these named parameters are supported: :schema, :owner, :table and :view

#selectViewSql=select text from all_views where view_name=? and owner=?
#selectCheckConstraintsSql=select table_name, constraint_name constname, search_condition text from all_constraints where constraint_type = 'C' and constraint_name not like 'SYS%' and owner = ?
# return text that represents a specific :view / :schema
#selectViewSql=

# return table_name, constraint_name and text for a specific :schema
#selectCheckConstraintsSql=
12 changes: 9 additions & 3 deletions src/net/sourceforge/schemaspy/dbTypes/ora.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@ driverPath=c:/Oracle8I/ora81/jdbc/lib/classes12.zip
# this Oracle driver's metadata services aren't thread safe so limit its access to one thread
dbThreads=1

selectViewSql=select text from all_views where view_name=? and owner=?
selectCheckConstraintsSql=select table_name, constraint_name constname, search_condition text from all_constraints where constraint_type = 'C' and constraint_name not like 'SYS%' and owner = ?
# all of these selects are optional:
# these named parameters are supported: :schema, :owner, :table and :view

# return text that represents a specific :view / :schema
selectViewSql=select text from all_views where view_name=:view and owner=:owner

# return table_name, constraint_name and text for a specific :schema
selectCheckConstraintsSql=select table_name, constraint_name, search_condition text from all_constraints where constraint_type = 'C' and constraint_name not like 'SYS%' and owner = :owner

# Oracle's driver does 'inappropriate things' when you call DatabaseMetaData.getIndexInfo().
# (Oracle Bug No. 2686037 - IMPROVE IMPLEMENTATION OF DATABASEMETADATA.GETINDEXINFO - per Andrea (bsq99)
# This is an opportunity to bypass that 'badness'
selectIndexesSql=select null as table_cat, owner as table_schem, table_name, 0 as NON_UNIQUE, null as index_qualifier, null as index_name, 0 as type, 0 as ordinal_position, null as column_name, null as asc_or_desc, num_rows as cardinality, blocks as pages, null as filter_condition from all_tables where table_name = ? and owner = ? union select null as table_cat, i.owner as table_schem, i.table_name, decode (i.uniqueness, 'UNIQUE', 0, 1), null as index_qualifier, i.index_name, 1 as type, c.column_position as ordinal_position, c.column_name, null as asc_or_desc, i.distinct_keys as cardinality, i.leaf_blocks as pages, null as filter_condition from all_indexes i, all_ind_columns c where i.table_name = ? and i.owner = ? and i.index_name = c.index_name and i.table_owner = c.table_owner and i.table_name = c.table_name and i.owner = c.index_owner
selectIndexesSql=select null as table_cat, owner as table_schem, table_name, 0 as NON_UNIQUE, null as index_qualifier, null as index_name, 0 as type, 0 as ordinal_position, null as column_name, null as asc_or_desc, num_rows as cardinality, blocks as pages, null as filter_condition from all_tables where table_name = :table and owner = :owner union select null as table_cat, i.owner as table_schem, i.table_name, decode (i.uniqueness, 'UNIQUE', 0, 1), null as index_qualifier, i.index_name, 1 as type, c.column_position as ordinal_position, c.column_name, null as asc_or_desc, i.distinct_keys as cardinality, i.leaf_blocks as pages, null as filter_condition from all_indexes i, all_ind_columns c where i.table_name = :table and i.owner = :owner and i.index_name = c.index_name and i.table_owner = c.table_owner and i.table_name = c.table_name and i.owner = c.index_owner
12 changes: 7 additions & 5 deletions src/net/sourceforge/schemaspy/dbTypes/pgsql.properties
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ driverPath=/whereever/postgresql-8.0-312.jdbc3.jar
# or specify "-dbThreads 1" on the command line.
#dbThreads=1

# the following SQL is optional (and untested with MySql)
# fill it in if you want to see the SQL used to create your views or your check constraints
# send it back to schemaspy.sourceforge.net if it works
# all of these selects are optional
# these named parameters are supported: :schema, :owner, :table and :view

#selectViewSql=select text from all_views where view_name=? and owner=?
#selectCheckConstraintsSql=select table_name, constraint_name constname, search_condition text from all_constraints where constraint_type = 'C' and constraint_name not like 'SYS%' and owner = ?
# return text that represents a specific :view / :schema
#selectViewSql=select text from all_views where view_name=:view and owner=:owner

# return table_name, constraint_name and text for a specific :schema
#selectCheckConstraintsSql=select table_name, constraint_name, search_condition text from all_constraints where constraint_type = 'C' and constraint_name not like 'SYS%' and owner = :owner
9 changes: 6 additions & 3 deletions src/net/sourceforge/schemaspy/dbTypes/sybase.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ driverPath=D:/Programme/sybase/jConnect-6_0/classes/jconn3.jar;C:/Programme/syba
# or specify "-dbThreads 1" on the command line.
#dbThreads=1

#selectViewSql=select text from syscomments sc, sysobjects so where sc.id=so.id and so.name=?
# all of these selects are optional:
# these named parameters are supported: :schema, :owner, :table and :view

# untested...comment it out if it blows up
#selectCheckConstraintsSql=select distinct a.name constname, text from sysobjects a, syscomments b, sysobjects c where a.id = b.id and a.type = 'C'
# return text that represents a specific :view / :schema
#selectViewSql=select text from syscomments sc, sysobjects so where sc.id=so.id and so.name=:view

# return table_name, constraint_name and text for a specific :schema
#selectCheckConstraintsSql=select distinct a.name constraint_name, text from sysobjects a, syscomments b, sysobjects c where a.id = b.id and a.type = 'C'
84 changes: 67 additions & 17 deletions src/net/sourceforge/schemaspy/model/Database.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public Database(Connection connection, DatabaseMetaData meta, String name, Strin
this.databaseName = name;
this.schema = schema;
initTables(schema, this.meta, properties, maxThreads);
initViews(schema, this.meta, connection, properties);
initViews(schema, this.meta, properties);
connectTables(this.meta);
}

Expand Down Expand Up @@ -110,13 +110,13 @@ private void initCheckConstraints(Properties properties) throws SQLException {
ResultSet rs = null;

try {
stmt = createStatement(sql);
stmt = prepareStatement(sql, null);
rs = stmt.executeQuery();

while (rs.next()) {
String tableName = rs.getString("table_name");
Table table = (Table)tables.get(tableName.toUpperCase());
table.addCheckConstraint(rs.getString("constname"), rs.getString("text"));
table.addCheckConstraint(rs.getString("constraint_name"), rs.getString("text"));
}
} catch (SQLException sqlException) {
System.err.println();
Expand All @@ -138,7 +138,7 @@ private void initTableIds(Properties properties) throws SQLException {
ResultSet rs = null;

try {
stmt = createStatement(sql);
stmt = prepareStatement(sql, null);
rs = stmt.executeQuery();

while (rs.next()) {
Expand Down Expand Up @@ -167,7 +167,7 @@ private void initIndexIds(Properties properties) throws SQLException {
ResultSet rs = null;

try {
stmt = createStatement(sql);
stmt = prepareStatement(sql, null);
rs = stmt.executeQuery();

while (rs.next()) {
Expand All @@ -192,25 +192,75 @@ private void initIndexIds(Properties properties) throws SQLException {
}
}

private PreparedStatement createStatement(String sql) throws SQLException {
/**
* Create a <code>PreparedStatement</code> from the specified SQL.
* The SQL can contain these named parameters (but <b>not</b> question marks).
* <ol>
* <li>:schema - replaced with the name of the schema
* <li>:owner - alias for :schema
* <li>:table - replaced with the name of the table
* </ol>
* @param sql String - SQL without question marks
* @param tableName String - <code>null</code> if the statement doesn't deal with <code>Table</code>-level details.
* @throws SQLException
* @return PreparedStatement
*/
public PreparedStatement prepareStatement(String sql, String tableName) throws SQLException {
PreparedStatement stmt = null;
if (sql != null) {
try {
stmt = getConnection().prepareStatement(sql);
boolean schemaRequired = sql.indexOf('?') != -1;
if (schemaRequired)
stmt.setString(1, getSchema());
} catch (SQLException exc) {
if (stmt != null)
stmt.close();
throw exc;
StringBuffer sqlBuf = new StringBuffer(sql);
List sqlParams = getSqlParams(sqlBuf, tableName); // modifies sqlBuf

try {
stmt = getConnection().prepareStatement(sqlBuf.toString());

for (int i = 0; i < sqlParams.size(); ++i) {
stmt.setString(i + 1, sqlParams.get(i).toString());
}
} catch (SQLException exc) {
if (stmt != null)
stmt.close();
throw exc;
}

return stmt;
}

private void initViews(String schema, DatabaseMetaData metadata, Connection connection, Properties properties) throws SQLException {
/**
* Replaces named parameters in <code>sql</code> with question marks and
* returns appropriate matching values in the returned <code>List</code> of <code>String</code>s.
*
* @param sql StringBuffer input SQL with named parameters, output named params are replaced with ?'s.
* @param tableName String
* @return List of Strings
*
* @see #prepareStatement(String, String)
*/
private List getSqlParams(StringBuffer sql, String tableName) {
Map namedParams = new HashMap();
namedParams.put(":schema", getSchema());
namedParams.put(":owner", getSchema()); // alias for :schema
if (tableName != null) {
namedParams.put(":table", tableName);
namedParams.put(":view", tableName); // alias for :table
}

List sqlParams = new ArrayList();
int nextColon = sql.indexOf(":");
while (nextColon != -1) {
String paramName = new StringTokenizer(sql.substring(nextColon), " ,").nextToken();
String paramValue = (String)namedParams.get(paramName);
if (paramValue == null)
throw new IllegalArgumentException("Unexpected named parameter '" + paramName + "' found in SQL '" + sql + "'");
sqlParams.add(paramValue);
sql.replace(nextColon, nextColon + paramName.length(), "?"); // replace with a ?
nextColon = sql.indexOf(":", nextColon);
}

return sqlParams;
}


private void initViews(String schema, DatabaseMetaData metadata, Properties properties) throws SQLException {
String[] types = {"VIEW"};
ResultSet rs = null;

Expand Down

0 comments on commit 54b3530

Please sign in to comment.