Changeset: 8ef30c92231d for MonetDB URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=8ef30c92231d Modified Files: java/src/main/java/nl/cwi/monetdb/util/SQLExporter.java Branch: Jun2016 Log Message:
Improve SQLExporter methods dumpSchema(), resultSetToSQL() and resultSetToTable() Use less method calls by keeping intermediate return values and reuse them. Added rs.wasNull when fetching resultset column values to correctly identify whether the value was null or not. diffs (truncated from 328 to 300 lines): diff --git a/java/src/main/java/nl/cwi/monetdb/util/SQLExporter.java b/java/src/main/java/nl/cwi/monetdb/util/SQLExporter.java --- a/java/src/main/java/nl/cwi/monetdb/util/SQLExporter.java +++ b/java/src/main/java/nl/cwi/monetdb/util/SQLExporter.java @@ -26,10 +26,10 @@ public class SQLExporter extends Exporte private int outputMode; private Stack<String> lastSchema; - public final static int TYPE_OUTPUT = 1; + public final static int TYPE_OUTPUT = 1; public final static int VALUE_INSERT = 0; - public final static int VALUE_COPY = 1; - public final static int VALUE_TABLE = 2; + public final static int VALUE_COPY = 1; + public final static int VALUE_TABLE = 2; public SQLExporter(PrintWriter out) { super(out); @@ -40,11 +40,11 @@ public class SQLExporter extends Exporte * This method performs all required lookups to find all relations and * column information, as well as additional indices. * - * @param dbmd a DatabaseMetaData object to query on - * @param type the type of the object, e.g. VIEW, TABLE + * @param dbmd a DatabaseMetaData object to query on (not null) + * @param type the type of the object, e.g. VIEW, TABLE (not null) * @param catalog the catalog the object is in - * @param schema the schema the object is in - * @param name the table to describe in SQL CREATE format + * @param schema the schema the object is in (not null) + * @param name the table to describe in SQL CREATE format (not null) * @throws SQLException if a database related error occurs */ public void dumpSchema( @@ -55,6 +55,13 @@ public class SQLExporter extends Exporte String name) throws SQLException { + assert dbmd != null; + assert type != null; + assert schema != null; + assert name != null; + + String fqname = (!useSchema ? dq(schema) + "." : "") + dq(name); + if (useSchema) changeSchema(schema); @@ -63,18 +70,14 @@ public class SQLExporter extends Exporte String[] types = new String[1]; types[0] = type; ResultSet tbl = dbmd.getTables(catalog, schema, name, types); - if (!tbl.next()) throw new SQLException("Whoops no data for " + name); + if (!tbl.next()) throw new SQLException("Whoops no meta data for view " + fqname); // This will probably only work for MonetDB - String remarks = tbl.getString("REMARKS"); + String remarks = tbl.getString("REMARKS"); // for MonetDB driver this contains the view definition if (remarks == null) { - out.println("-- invalid " + type + " " + - (!useSchema ? dq(schema) + "." : "") + dq(name) + - ": no definition found"); + out.println("-- invalid " + type + " " + fqname + ": no definition found"); } else { - out.print("CREATE " + type + " " + - (!useSchema ? dq(schema) + "." : "") + dq(name)); - out.print(" AS "); + out.print("CREATE " + type + " " + fqname + " AS "); out.println(remarks.replaceFirst("create view [^ ]+ as", "").trim()); } return; @@ -82,10 +85,9 @@ public class SQLExporter extends Exporte int i; String s; - out.println("CREATE " + type + " " + - (!useSchema ? dq(schema) + "." : "") + dq(name) + " ("); + out.println("CREATE " + type + " " + fqname + " ("); - // put all columns with their type in place + // add all columns with their type, nullability and default definition ResultSet cols = dbmd.getColumns(catalog, schema, name, null); ResultSetMetaData rsmd = cols.getMetaData(); int colwidth = rsmd.getColumnDisplaySize(cols.findColumn("COLUMN_NAME")); @@ -113,28 +115,31 @@ public class SQLExporter extends Exporte // print column type out.print(s + repeat(' ', typewidth - s.length())); - // do some type specifics - if (ctype == Types.FLOAT || - ctype == Types.VARCHAR || - ctype == Types.LONGVARCHAR || - ctype == Types.CHAR - ) { - if (size <= 0) throw - new SQLException("Illegal value for precision of type " + cols.getString("TYPE_NAME") + " (" + size + ")"); - out.print("(" + size + ")"); - } else if (ctype == Types.CLOB) { - if (size > 0) out.print("(" + size + ")"); - } else if (ctype == Types.DECIMAL || - ctype == Types.NUMERIC - ) { - if (digits < 0) throw - new SQLException("Illegal value for scale of decimal type (" + digits + ")"); - out.print("(" + size + "," + digits + ")"); - } else if (ctype == Types.TIMESTAMP || - ctype == Types.TIME - ) { - out.print("(" + (size - 1) + ")"); - if (digits != 0) out.print(" WITH TIME ZONE"); + // do some MonetDB type specifics + switch (ctype) { + case Types.CHAR: + case Types.VARCHAR: + case Types.LONGVARCHAR: + case Types.CLOB: + case Types.BLOB: + case Types.FLOAT: + if (size > 0) + out.print("(" + size + ")"); + break; + case Types.TIME: + case Types.TIMESTAMP: + if (size > 1) + out.print("(" + (size - 1) + ")"); + if (digits != 0) + out.print(" WITH TIME ZONE"); + break; + case Types.DECIMAL: + case Types.NUMERIC: + if (digits != 0) + out.print("(" + size + "," + digits + ")"); + else + out.print("(" + size + ")"); + break; } if (cols.getInt("NULLABLE") == DatabaseMetaData.columnNoNulls) out.print("\tNOT NULL"); @@ -143,14 +148,11 @@ public class SQLExporter extends Exporte } cols.close(); - // the primary key constraint + // add the primary key constraint definition // unfortunately some idiot defined that getPrimaryKeys() // returns the primary key columns sorted by column name, not // key sequence order. So we have to sort ourself :( - cols = dbmd.getPrimaryKeys( - catalog, - schema, - name); + cols = dbmd.getPrimaryKeys(catalog, schema, name); // first make an 'index' of the KEY_SEQ column SortedMap<Integer, Integer> seqIndex = new TreeMap<Integer, Integer>(); for (i = 1; cols.next(); i++) { @@ -177,7 +179,7 @@ public class SQLExporter extends Exporte } cols.close(); - // unique constraints + // add unique constraint definitions cols = dbmd.getIndexInfo(catalog, schema, name, true, true); while (cols.next()) { String idxname = cols.getString("INDEX_NAME"); @@ -197,7 +199,7 @@ public class SQLExporter extends Exporte } cols.close(); - // foreign keys + // add foreign keys definitions cols = dbmd.getImportedKeys(catalog, schema, name); while (cols.next()) { out.println(","); @@ -236,14 +238,14 @@ public class SQLExporter extends Exporte } cols.close(); out.println(); - // end the create statement + // end the create table statement out.println(");"); - // create indexes + // create the non unique indexes defined for this table cols = dbmd.getIndexInfo(catalog, schema, name, false, true); while (cols.next()) { if (!cols.getBoolean("NON_UNIQUE")) { - // we already covered this one as UNIQUE + // we already covered this one as UNIQUE constraint in the CREATE TABLE continue; } else { String idxname = cols.getString("INDEX_NAME"); @@ -333,13 +335,14 @@ public class SQLExporter extends Exporte statement += dq(rsmd.getTableName(1)) + " VALUES ("; int cols = rsmd.getColumnCount(); - int[] types = new int[cols]; - for (int i = 0; i < cols; i++) { - switch (rsmd.getColumnType(i + 1)) { + short[] types = new short[cols +1]; + for (int i = 1; i <= cols; i++) { + switch (rsmd.getColumnType(i)) { case Types.CHAR: case Types.VARCHAR: case Types.LONGVARCHAR: case Types.CLOB: + case Types.BLOB: case Types.DATE: case Types.TIME: case Types.TIMESTAMP: @@ -367,17 +370,18 @@ public class SQLExporter extends Exporte while (rs.next()) { out.print(statement); for (int i = 1; i <= cols; i++) { + String val = rs.getString(i); if (i > 1) out.print(", "); - if (rs.getString(i) == null) { + if (val == null || rs.wasNull()) { out.print("NULL"); continue; } - switch (types[i - 1]) { + switch (types[i]) { case AS_IS: - out.print(rs.getString(i)); + out.print(val); break; case QUOTE: - out.print(q(rs.getString(i))); + out.print(q(val)); break; } } @@ -386,7 +390,7 @@ public class SQLExporter extends Exporte } public void resultSetToSQLDump(ResultSet rs) { - // write copy into statement + // TODO: write copy into statement } /** @@ -397,60 +401,64 @@ public class SQLExporter extends Exporte */ public void resultSetToTable(ResultSet rs) throws SQLException { ResultSetMetaData md = rs.getMetaData(); - // find the widths of the columns - int[] width = new int[md.getColumnCount()]; - for (int j = 0; j < md.getColumnCount(); j++) { - if (md.getColumnDisplaySize(j + 1) == 0) { - width[j] = md.getColumnLabel(j + 1).length(); - } else { - width[j] = Math.max(md.getColumnDisplaySize(j + 1), md.getColumnLabel(j + 1).length()); - } - if (md.isNullable(j + 1) != ResultSetMetaData.columnNoNulls) { + int cols = md.getColumnCount(); + // find the presentation widths of the columns + int[] width = new int[cols +1]; + for (int j = 1; j <= cols; j++) { + int displaySize = md.getColumnDisplaySize(j); + int labelLength = md.getColumnLabel(j).length(); + width[j] = (displaySize > labelLength) ? displaySize : labelLength; + if (md.isNullable(j) != ResultSetMetaData.columnNoNulls) { width[j] = Math.max("<NULL>".length(), width[j]); } } + // print header out.print("+"); - for (int j = 0; j < width.length; j++) - out.print("-" + repeat('-', width[j]) + "-+"); + for (int j = 1; j < width.length; j++) + out.print(repeat('-', width[j] +1) + "-+"); out.println(); out.print("|"); - for (int j = 0; j < width.length; j++) { - out.print(" " + md.getColumnLabel(j + 1) + repeat(' ', width[j] - md.getColumnLabel(j + 1).length()) + " |"); + for (int j = 1; j < width.length; j++) { + String colLabel = md.getColumnLabel(j); + out.print(" " + colLabel + repeat(' ', width[j] - colLabel.length()) + " |"); } out.println(); out.print("+"); - for (int j = 0; j < width.length; j++) + for (int j = 1; j < width.length; j++) out.print("=" + repeat('=', width[j]) + "=+"); out.println(); + // print data of each row from resultset int count = 0; for (; rs.next(); count++) { out.print("|"); - for (int j = 0; j < width.length; j++) { - Object rdata = rs.getObject(j + 1); + for (int j = 1; j < width.length; j++) { + Object rdata = rs.getObject(j); String data; - if (rdata == null) { + if (rdata == null || rs.wasNull()) { data = "<NULL>"; _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list