You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@metamodel.apache.org by ka...@apache.org on 2014/05/18 21:40:05 UTC

git commit: METAMODEL-56: Fixed metadata of converted JDBC LOBs.

Repository: incubator-metamodel
Updated Branches:
  refs/heads/master 7c21e0652 -> bd54b1e0d


METAMODEL-56: Fixed metadata of converted JDBC LOBs.

Project: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/commit/bd54b1e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/tree/bd54b1e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-metamodel/diff/bd54b1e0

Branch: refs/heads/master
Commit: bd54b1e0d04b697f3d8c882ddafb66de9562c14d
Parents: 7c21e06
Author: Kasper Sørensen <i....@gmail.com>
Authored: Sun May 18 21:39:13 2014 +0200
Committer: Kasper Sørensen <i....@gmail.com>
Committed: Sun May 18 21:39:13 2014 +0200

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../apache/metamodel/jdbc/JdbcDataContext.java  |  12 +-
 .../org/apache/metamodel/jdbc/JdbcDataSet.java  |  27 +-
 .../metamodel/jdbc/JdbcMetadataLoader.java      | 770 ++++++++++---------
 .../org/apache/metamodel/jdbc/JdbcUtils.java    |   3 +
 .../metamodel/jdbc/JdbcTestTemplates.java       |  67 +-
 6 files changed, 452 insertions(+), 428 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9c46fad..d32a9d9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -2,6 +2,7 @@ Apache MetaModel 4.1.0-incubating
 
  * [METAMODEL-13] - Added support for Apache HBase via the new module "MetaModel-hbase"
  * [METAMODEL-54] - ColumnType converted from enum to interface to allow for further specialization in modules
+ * [METAMODEL-56] - Made separate column types for converted JDBC LOBs - "CLOB as String" and "BLOB as bytes".
  * [METAMODEL-41] - Added a parser for SimpleTableDef objects (SimpleTableDefParser). It parses statements similar to CREATE TABLE statements, although without the "CREATE TABLE" prefix. For example: foo (bar INTEGER, baz VARCHAR)
  * [METAMODEL-11] - New module "MetaModel-spring" which adds a convenient FactoryBean to produce various types of DataContext objects based on externalizable parameters, for Spring framework users.
  * [METAMODEL-32] - Fixed thread-safety issue in Excel module when tables (sheets) metadata is updated.

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
index 6a4b8a0..a20924c 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataContext.java
@@ -51,7 +51,10 @@ import org.apache.metamodel.jdbc.dialects.PostgresqlQueryRewriter;
 import org.apache.metamodel.jdbc.dialects.SQLServerQueryRewriter;
 import org.apache.metamodel.query.CompiledQuery;
 import org.apache.metamodel.query.Query;
+import org.apache.metamodel.schema.ColumnType;
+import org.apache.metamodel.schema.ColumnTypeImpl;
 import org.apache.metamodel.schema.Schema;
+import org.apache.metamodel.schema.SuperColumnType;
 import org.apache.metamodel.schema.TableType;
 import org.apache.metamodel.util.FileHelper;
 import org.slf4j.Logger;
@@ -64,7 +67,7 @@ public class JdbcDataContext extends AbstractDataContext implements UpdateableDa
 
     public static final String SYSTEM_PROPERTY_BATCH_UPDATES = "metamodel.jdbc.batch.updates";
     public static final String SYSTEM_PROPERTY_CONVERT_LOBS = "metamodel.jdbc.convert.lobs";
-    
+
     public static final String SYSTEM_PROPERTY_COMPILED_QUERY_POOL_MAX_SIZE = "metamodel.jdbc.compiledquery.pool.max.size";
     public static final String SYSTEM_PROPERTY_COMPILED_QUERY_POOL_MIN_EVICTABLE_IDLE_TIME_MILLIS = "metamodel.jdbc.compiledquery.pool.idle.timeout";
     public static final String SYSTEM_PROPERTY_COMPILED_QUERY_POOL_TIME_BETWEEN_EVICTION_RUNS_MILLIS = "metamodel.jdbc.compiledquery.pool.eviction.period.millis";
@@ -77,6 +80,11 @@ public class JdbcDataContext extends AbstractDataContext implements UpdateableDa
     public static final String DATABASE_PRODUCT_DB2 = "DB2";
     public static final String DATABASE_PRODUCT_DB2_PREFIX = "DB2/";
 
+    public static final ColumnType COLUMN_TYPE_CLOB_AS_STRING = new ColumnTypeImpl("CLOB",
+            SuperColumnType.LITERAL_TYPE, String.class, true);
+    public static final ColumnType COLUMN_TYPE_BLOB_AS_BYTES = new ColumnTypeImpl("BLOB", SuperColumnType.BINARY_TYPE,
+            byte[].class, true);
+
     private static final Logger logger = LoggerFactory.getLogger(JdbcDataContext.class);
 
     private final FetchSizeCalculator _fetchSizeCalculator;
@@ -748,7 +756,7 @@ public class JdbcDataContext extends AbstractDataContext implements UpdateableDa
     public void executeUpdate(final UpdateScript update) {
         final JdbcUpdateCallback updateCallback;
 
-        if (_supportsBatchUpdates && update instanceof BatchUpdateScript) { 
+        if (_supportsBatchUpdates && update instanceof BatchUpdateScript) {
             updateCallback = new JdbcBatchUpdateCallback(this);
         } else {
             updateCallback = new JdbcSimpleUpdateCallback(this);

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataSet.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataSet.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataSet.java
index e730b6a..aebe4d4 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataSet.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcDataSet.java
@@ -41,8 +41,6 @@ import org.slf4j.LoggerFactory;
 
 /**
  * DataSet implementation that wraps a JDBC resultset.
- * 
- * @author Kasper Sørensen
  */
 final class JdbcDataSet extends AbstractDataSet {
 
@@ -163,22 +161,22 @@ final class JdbcDataSet extends AbstractDataSet {
                         return _resultSet.getTimestamp(columnIndex);
                     } else if (type == ColumnType.BLOB) {
                         final Blob blob = _resultSet.getBlob(columnIndex);
-                        if (isLobConversionEnabled()) {
-                            final InputStream inputStream = blob.getBinaryStream();
-                            final byte[] bytes = FileHelper.readAsBytes(inputStream);
-                            return bytes;
-                        }
                         return blob;
+                    } else if (type == JdbcDataContext.COLUMN_TYPE_BLOB_AS_BYTES) {
+                        final Blob blob = _resultSet.getBlob(columnIndex);
+                        final InputStream inputStream = blob.getBinaryStream();
+                        final byte[] bytes = FileHelper.readAsBytes(inputStream);
+                        return bytes;
                     } else if (type.isBinary()) {
                         return _resultSet.getBytes(columnIndex);
                     } else if (type == ColumnType.CLOB || type == ColumnType.NCLOB) {
                         final Clob clob = _resultSet.getClob(columnIndex);
-                        if (isLobConversionEnabled()) {
-                            final Reader reader = clob.getCharacterStream();
-                            final String result = FileHelper.readAsString(reader);
-                            return result;
-                        }
                         return clob;
+                    } else if (type == JdbcDataContext.COLUMN_TYPE_CLOB_AS_STRING) {
+                        final Clob clob = _resultSet.getClob(columnIndex);
+                        final Reader reader = clob.getCharacterStream();
+                        final String result = FileHelper.readAsString(reader);
+                        return result;
                     } else if (type.isBoolean()) {
                         return _resultSet.getBoolean(columnIndex);
                     }
@@ -191,11 +189,6 @@ final class JdbcDataSet extends AbstractDataSet {
         return _resultSet.getObject(columnIndex);
     }
 
-    private boolean isLobConversionEnabled() {
-        final String systemProperty = System.getProperty(JdbcDataContext.SYSTEM_PROPERTY_CONVERT_LOBS);
-        return "true".equals(systemProperty);
-    }
-
     /**
      * {@inheritDoc}
      */

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcMetadataLoader.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcMetadataLoader.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcMetadataLoader.java
index 85c2514..54ad378 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcMetadataLoader.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcMetadataLoader.java
@@ -44,384 +44,396 @@ import org.slf4j.LoggerFactory;
  */
 final class JdbcMetadataLoader implements MetadataLoader {
 
-	private static final Logger logger = LoggerFactory.getLogger(JdbcMetadataLoader.class);
-
-	private final JdbcDataContext _dataContext;
-	private final boolean _usesCatalogsAsSchemas;
-	private final String _identifierQuoteString;
-
-	// these three sets contains the system identifies of whether specific items
-	// have been loaded for tables/schemas. Using system identities avoid having
-	// to call equals(...) method etc. while doing lazy loading of these items.
-	// Invoking equals(...) would be prone to stack overflows ...
-	private final Set<Integer> _loadedRelations;
-	private final Set<Integer> _loadedColumns;
-	private final Set<Integer> _loadedIndexes;
-	private final Set<Integer> _loadedPrimaryKeys;
-
-	public JdbcMetadataLoader(JdbcDataContext dataContext, boolean usesCatalogsAsSchemas, String identifierQuoteString) {
-		_dataContext = dataContext;
-		_usesCatalogsAsSchemas = usesCatalogsAsSchemas;
-		_identifierQuoteString = identifierQuoteString;
-		_loadedRelations = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
-		_loadedColumns = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
-		_loadedIndexes = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
-		_loadedPrimaryKeys = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
-	}
-
-	@Override
-	public void loadTables(JdbcSchema schema) {
-		final Connection connection = _dataContext.getConnection();
-		try {
-			final DatabaseMetaData metaData = connection.getMetaData();
-
-			// Creates string array to represent the table types
-			final String[] types = JdbcUtils.getTableTypesAsStrings(_dataContext.getTableTypes());
-			loadTables(schema, metaData, types);
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve table metadata for " + schema.getName());
-		} finally {
-			_dataContext.close(connection, null, null);
-		}
-	}
-
-	private void loadTables(JdbcSchema schema, DatabaseMetaData metaData, String[] types) {
-		String catalogName = _dataContext.getCatalogName();
-
-		ResultSet rs = null;
-		try {
-			if (logger.isDebugEnabled()) {
-				logger.debug("Querying for table types " + Arrays.toString(types) + " in catalog: " + catalogName
-						+ ", schema: " + schema.getName());
-			}
-			if (_usesCatalogsAsSchemas) {
-				rs = metaData.getTables(schema.getName(), null, null, types);
-			} else {
-				rs = metaData.getTables(catalogName, schema.getName(), null, types);
-			}
-			schema.clearTables();
-			int tableNumber = -1;
-			while (rs.next()) {
-				tableNumber++;
-				String tableCatalog = rs.getString(1);
-				String tableSchema = rs.getString(2);
-				String tableName = rs.getString(3);
-				String tableTypeName = rs.getString(4);
-				TableType tableType = TableType.getTableType(tableTypeName);
-				String tableRemarks = rs.getString(5);
-
-				if (logger.isDebugEnabled()) {
-					logger.debug("Found table: tableCatalog=" + tableCatalog + ",tableSchema=" + tableSchema
-							+ ",tableName=" + tableName);
-				}
-
-				if (tableSchema == null) {
-					tableSchema = tableCatalog;
-				}
-
-				JdbcTable table = new JdbcTable(tableName, tableType, schema, this);
-				table.setRemarks(tableRemarks);
-				table.setQuote(_identifierQuoteString);
-				schema.addTable(table);
-			}
-
-			final int tablesReturned = tableNumber + 1;
-			if (tablesReturned == 0) {
-				logger.info("No table metadata records returned for schema '{}'", schema.getName());
-			} else {
-				logger.debug("Returned {} table metadata records for schema '{}'", new Object[] { tablesReturned,
-						schema.getName() });
-			}
-
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve table metadata for " + schema.getName());
-		} finally {
-			_dataContext.close(null, rs, null);
-		}
-	}
-
-	@Override
-	public void loadIndexes(JdbcTable table) {
-		final int identity = System.identityHashCode(table);
-		if (_loadedIndexes.contains(identity)) {
-			return;
-		}
-		synchronized (this) {
-			if (_loadedIndexes.contains(identity)) {
-				return;
-			}
-
-			final Connection connection = _dataContext.getConnection();
-			try {
-				DatabaseMetaData metaData = connection.getMetaData();
-				loadIndexes(table, metaData);
-				_loadedIndexes.add(identity);
-			} catch (SQLException e) {
-				throw JdbcUtils.wrapException(e, "load indexes");
-			} finally {
-				_dataContext.close(connection, null, null);
-			}
-		}
-	}
-
-	@Override
-	public void loadPrimaryKeys(JdbcTable table) {
-		final int identity = System.identityHashCode(table);
-		if (_loadedPrimaryKeys.contains(identity)) {
-			return;
-		}
-		synchronized (this) {
-			if (_loadedPrimaryKeys.contains(identity)) {
-				return;
-			}
-			final Connection connection = _dataContext.getConnection();
-			try {
-				DatabaseMetaData metaData = connection.getMetaData();
-				loadPrimaryKeys(table, metaData);
-				_loadedPrimaryKeys.add(identity);
-			} catch (SQLException e) {
-				throw JdbcUtils.wrapException(e, "load primary keys");
-			} finally {
-				_dataContext.close(connection, null, null);
-			}
-		}
-	}
-
-	private void loadPrimaryKeys(JdbcTable table, DatabaseMetaData metaData) throws MetaModelException {
-		Schema schema = table.getSchema();
-		ResultSet rs = null;
-
-		try {
-			if (_usesCatalogsAsSchemas) {
-				rs = metaData.getPrimaryKeys(schema.getName(), null, table.getName());
-			} else {
-				rs = metaData.getPrimaryKeys(_dataContext.getCatalogName(), schema.getName(), table.getName());
-			}
-			while (rs.next()) {
-				String columnName = rs.getString(4);
-				if (columnName != null) {
-					MutableColumn column = (MutableColumn) table.getColumnByName(columnName);
-					if (column != null) {
-						column.setPrimaryKey(true);
-					} else {
-						logger.error("Indexed column \"{}\" could not be found in table: {}", columnName, table);
-					}
-				}
-			}
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve primary keys for " + table.getName());
-		} finally {
-			_dataContext.close(null, rs, null);
-		}
-	}
-
-	private void loadIndexes(Table table, DatabaseMetaData metaData) throws MetaModelException {
-		Schema schema = table.getSchema();
-		ResultSet rs = null;
-		// Ticket #170: IndexInfo is nice-to-have, not need-to-have, so
-		// we will do a nice failover on SQLExceptions
-		try {
-			if (_usesCatalogsAsSchemas) {
-				rs = metaData.getIndexInfo(schema.getName(), null, table.getName(), false, true);
-			} else {
-				rs = metaData.getIndexInfo(_dataContext.getCatalogName(), schema.getName(), table.getName(), false,
-						true);
-			}
-			while (rs.next()) {
-				String columnName = rs.getString(9);
-				if (columnName != null) {
-					MutableColumn column = (MutableColumn) table.getColumnByName(columnName);
-					if (column != null) {
-						column.setIndexed(true);
-					} else {
-						logger.error("Indexed column \"{}\" could not be found in table: {}", columnName, table);
-					}
-				}
-			}
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve index information for " + table.getName());
-		} finally {
-			_dataContext.close(null, rs, null);
-		}
-	}
-
-	/**
-	 * Loads column metadata (no indexes though) for a table
-	 * 
-	 * @param table
-	 */
-	@Override
-	public void loadColumns(JdbcTable table) {
-		final int identity = System.identityHashCode(table);
-		if (_loadedColumns.contains(identity)) {
-			return;
-		}
-		synchronized (this) {
-			if (_loadedColumns.contains(identity)) {
-				return;
-			}
-
-			final Connection connection = _dataContext.getConnection();
-			try {
-				DatabaseMetaData metaData = connection.getMetaData();
-				loadColumns(table, metaData);
-				_loadedColumns.add(identity);
-			} catch (Exception e) {
-				logger.error("Could not load columns for table: " + table, e);
-			} finally {
-				_dataContext.close(connection, null, null);
-			}
-		}
-	}
-
-	private void loadColumns(JdbcTable table, DatabaseMetaData metaData) {
-		final Schema schema = table.getSchema();
-		ResultSet rs = null;
-		try {
-			if (logger.isDebugEnabled()) {
-				logger.debug("Querying for columns in table: " + table.getName());
-			}
-			int columnNumber = -1;
-			if (_usesCatalogsAsSchemas) {
-				rs = metaData.getColumns(schema.getName(), null, table.getName(), null);
-			} else {
-				rs = metaData.getColumns(_dataContext.getCatalogName(), schema.getName(), table.getName(), null);
-			}
-			while (rs.next()) {
-				columnNumber++;
-				final String columnName = rs.getString(4);
-				if (_identifierQuoteString == null && new StringTokenizer(columnName).countTokens() > 1) {
-					logger.warn("column name contains whitespace: \"" + columnName + "\".");
-				}
-
-				final int jdbcType = rs.getInt(5);
-				final String nativeType = rs.getString(6);
-				final Integer columnSize = rs.getInt(7);
-
-				if (logger.isDebugEnabled()) {
-					logger.debug("Found column: table=" + table.getName() + ",columnName=" + columnName
-							+ ",nativeType=" + nativeType + ",columnSize=" + columnSize);
-				}
-
-				final ColumnType columnType = _dataContext.getQueryRewriter().getColumnType(jdbcType, nativeType,
-						columnSize);
-
-				final int jdbcNullable = rs.getInt(11);
-				final Boolean nullable;
-				if (jdbcNullable == DatabaseMetaData.columnNullable) {
-					nullable = true;
-				} else if (jdbcNullable == DatabaseMetaData.columnNoNulls) {
-					nullable = false;
-				} else {
-					nullable = null;
-				}
-
-				final String remarks = rs.getString(12);
-
-				final JdbcColumn column = new JdbcColumn(columnName, columnType, table, columnNumber, nullable);
-				column.setRemarks(remarks);
-				column.setNativeType(nativeType);
-				column.setColumnSize(columnSize);
-				column.setQuote(_identifierQuoteString);
-				table.addColumn(column);
-			}
-
-			final int columnsReturned = columnNumber + 1;
-			if (columnsReturned == 0) {
-				logger.info("No column metadata records returned for table '{}' in schema '{}'", table.getName(),
-						schema.getName());
-			} else {
-				logger.debug("Returned {} column metadata records for table '{}' in schema '{}'", new Object[] {
-						columnsReturned, table.getName(), schema.getName() });
-			}
-
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve table metadata for " + table.getName());
-		} finally {
-			_dataContext.close(null, rs, null);
-		}
-	}
-
-	@Override
-	public void loadRelations(JdbcSchema schema) {
-		final int identity = System.identityHashCode(schema);
-		if (_loadedRelations.contains(identity)) {
-			return;
-		}
-		synchronized (this) {
-			if (_loadedRelations.contains(identity)) {
-				return;
-			}
-			final Connection connection = _dataContext.getConnection();
-			try {
-				final Table[] tables = schema.getTables();
-				final DatabaseMetaData metaData = connection.getMetaData();
-				for (Table table : tables) {
-					loadRelations(table, metaData);
-				}
-				_loadedRelations.add(identity);
-			} catch (Exception e) {
-				logger.error("Could not load relations for schema: " + schema, e);
-			} finally {
-				_dataContext.close(connection, null, null);
-			}
-		}
-	}
-
-	private void loadRelations(Table table, DatabaseMetaData metaData) {
-		Schema schema = table.getSchema();
-		ResultSet rs = null;
-		try {
-			if (_usesCatalogsAsSchemas) {
-				rs = metaData.getImportedKeys(schema.getName(), null, table.getName());
-			} else {
-				rs = metaData.getImportedKeys(_dataContext.getCatalogName(), schema.getName(), table.getName());
-			}
-			loadRelations(rs, schema);
-		} catch (SQLException e) {
-			throw JdbcUtils.wrapException(e, "retrieve imported keys for " + table.getName());
-		} finally {
-			_dataContext.close(null, rs, null);
-		}
-	}
-
-	private void loadRelations(ResultSet rs, Schema schema) throws SQLException {
-		while (rs.next()) {
-			String pkTableName = rs.getString(3);
-			String pkColumnName = rs.getString(4);
-
-			Column pkColumn = null;
-			Table pkTable = schema.getTableByName(pkTableName);
-			if (pkTable != null) {
-				pkColumn = pkTable.getColumnByName(pkColumnName);
-			}
-			if (logger.isDebugEnabled()) {
-				logger.debug("Found primary key relation: tableName=" + pkTableName + ",columnName=" + pkColumnName
-						+ ", matching column: " + pkColumn);
-			}
-
-			String fkTableName = rs.getString(7);
-			String fkColumnName = rs.getString(8);
-			Column fkColumn = null;
-			Table fkTable = schema.getTableByName(fkTableName);
-			if (fkTable != null) {
-				fkColumn = fkTable.getColumnByName(fkColumnName);
-			}
-			if (logger.isDebugEnabled()) {
-				logger.debug("Found foreign key relation: tableName=" + fkTableName + ",columnName=" + fkColumnName
-						+ ", matching column: " + fkColumn);
-			}
-
-			if (pkColumn == null || fkColumn == null) {
-				logger.error(
-						"Could not find relation columns: pkTableName={},pkColumnName={},fkTableName={},fkColumnName={}",
-						new Object[] { pkTableName, pkColumnName, fkTableName, fkColumnName });
-				logger.error("pkColumn={}", pkColumn);
-				logger.error("fkColumn={}", fkColumn);
-			} else {
-				MutableRelationship.createRelationship(new Column[] { pkColumn }, new Column[] { fkColumn });
-			}
-		}
-	}
+    private static final Logger logger = LoggerFactory.getLogger(JdbcMetadataLoader.class);
+
+    private final JdbcDataContext _dataContext;
+    private final boolean _usesCatalogsAsSchemas;
+    private final String _identifierQuoteString;
+
+    // these three sets contains the system identifies of whether specific items
+    // have been loaded for tables/schemas. Using system identities avoid having
+    // to call equals(...) method etc. while doing lazy loading of these items.
+    // Invoking equals(...) would be prone to stack overflows ...
+    private final Set<Integer> _loadedRelations;
+    private final Set<Integer> _loadedColumns;
+    private final Set<Integer> _loadedIndexes;
+    private final Set<Integer> _loadedPrimaryKeys;
+
+    public JdbcMetadataLoader(JdbcDataContext dataContext, boolean usesCatalogsAsSchemas, String identifierQuoteString) {
+        _dataContext = dataContext;
+        _usesCatalogsAsSchemas = usesCatalogsAsSchemas;
+        _identifierQuoteString = identifierQuoteString;
+        _loadedRelations = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
+        _loadedColumns = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
+        _loadedIndexes = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
+        _loadedPrimaryKeys = Collections.newSetFromMap(new ConcurrentHashMap<Integer, Boolean>());
+    }
+
+    @Override
+    public void loadTables(JdbcSchema schema) {
+        final Connection connection = _dataContext.getConnection();
+        try {
+            final DatabaseMetaData metaData = connection.getMetaData();
+
+            // Creates string array to represent the table types
+            final String[] types = JdbcUtils.getTableTypesAsStrings(_dataContext.getTableTypes());
+            loadTables(schema, metaData, types);
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve table metadata for " + schema.getName());
+        } finally {
+            _dataContext.close(connection, null, null);
+        }
+    }
+
+    private void loadTables(JdbcSchema schema, DatabaseMetaData metaData, String[] types) {
+        String catalogName = _dataContext.getCatalogName();
+
+        ResultSet rs = null;
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Querying for table types " + Arrays.toString(types) + " in catalog: " + catalogName
+                        + ", schema: " + schema.getName());
+            }
+            if (_usesCatalogsAsSchemas) {
+                rs = metaData.getTables(schema.getName(), null, null, types);
+            } else {
+                rs = metaData.getTables(catalogName, schema.getName(), null, types);
+            }
+            schema.clearTables();
+            int tableNumber = -1;
+            while (rs.next()) {
+                tableNumber++;
+                String tableCatalog = rs.getString(1);
+                String tableSchema = rs.getString(2);
+                String tableName = rs.getString(3);
+                String tableTypeName = rs.getString(4);
+                TableType tableType = TableType.getTableType(tableTypeName);
+                String tableRemarks = rs.getString(5);
+
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Found table: tableCatalog=" + tableCatalog + ",tableSchema=" + tableSchema
+                            + ",tableName=" + tableName);
+                }
+
+                if (tableSchema == null) {
+                    tableSchema = tableCatalog;
+                }
+
+                JdbcTable table = new JdbcTable(tableName, tableType, schema, this);
+                table.setRemarks(tableRemarks);
+                table.setQuote(_identifierQuoteString);
+                schema.addTable(table);
+            }
+
+            final int tablesReturned = tableNumber + 1;
+            if (tablesReturned == 0) {
+                logger.info("No table metadata records returned for schema '{}'", schema.getName());
+            } else {
+                logger.debug("Returned {} table metadata records for schema '{}'", new Object[] { tablesReturned,
+                        schema.getName() });
+            }
+
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve table metadata for " + schema.getName());
+        } finally {
+            _dataContext.close(null, rs, null);
+        }
+    }
+
+    @Override
+    public void loadIndexes(JdbcTable table) {
+        final int identity = System.identityHashCode(table);
+        if (_loadedIndexes.contains(identity)) {
+            return;
+        }
+        synchronized (this) {
+            if (_loadedIndexes.contains(identity)) {
+                return;
+            }
+
+            final Connection connection = _dataContext.getConnection();
+            try {
+                DatabaseMetaData metaData = connection.getMetaData();
+                loadIndexes(table, metaData);
+                _loadedIndexes.add(identity);
+            } catch (SQLException e) {
+                throw JdbcUtils.wrapException(e, "load indexes");
+            } finally {
+                _dataContext.close(connection, null, null);
+            }
+        }
+    }
+
+    @Override
+    public void loadPrimaryKeys(JdbcTable table) {
+        final int identity = System.identityHashCode(table);
+        if (_loadedPrimaryKeys.contains(identity)) {
+            return;
+        }
+        synchronized (this) {
+            if (_loadedPrimaryKeys.contains(identity)) {
+                return;
+            }
+            final Connection connection = _dataContext.getConnection();
+            try {
+                DatabaseMetaData metaData = connection.getMetaData();
+                loadPrimaryKeys(table, metaData);
+                _loadedPrimaryKeys.add(identity);
+            } catch (SQLException e) {
+                throw JdbcUtils.wrapException(e, "load primary keys");
+            } finally {
+                _dataContext.close(connection, null, null);
+            }
+        }
+    }
+
+    private void loadPrimaryKeys(JdbcTable table, DatabaseMetaData metaData) throws MetaModelException {
+        Schema schema = table.getSchema();
+        ResultSet rs = null;
+
+        try {
+            if (_usesCatalogsAsSchemas) {
+                rs = metaData.getPrimaryKeys(schema.getName(), null, table.getName());
+            } else {
+                rs = metaData.getPrimaryKeys(_dataContext.getCatalogName(), schema.getName(), table.getName());
+            }
+            while (rs.next()) {
+                String columnName = rs.getString(4);
+                if (columnName != null) {
+                    MutableColumn column = (MutableColumn) table.getColumnByName(columnName);
+                    if (column != null) {
+                        column.setPrimaryKey(true);
+                    } else {
+                        logger.error("Indexed column \"{}\" could not be found in table: {}", columnName, table);
+                    }
+                }
+            }
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve primary keys for " + table.getName());
+        } finally {
+            _dataContext.close(null, rs, null);
+        }
+    }
+
+    private void loadIndexes(Table table, DatabaseMetaData metaData) throws MetaModelException {
+        Schema schema = table.getSchema();
+        ResultSet rs = null;
+        // Ticket #170: IndexInfo is nice-to-have, not need-to-have, so
+        // we will do a nice failover on SQLExceptions
+        try {
+            if (_usesCatalogsAsSchemas) {
+                rs = metaData.getIndexInfo(schema.getName(), null, table.getName(), false, true);
+            } else {
+                rs = metaData.getIndexInfo(_dataContext.getCatalogName(), schema.getName(), table.getName(), false,
+                        true);
+            }
+            while (rs.next()) {
+                String columnName = rs.getString(9);
+                if (columnName != null) {
+                    MutableColumn column = (MutableColumn) table.getColumnByName(columnName);
+                    if (column != null) {
+                        column.setIndexed(true);
+                    } else {
+                        logger.error("Indexed column \"{}\" could not be found in table: {}", columnName, table);
+                    }
+                }
+            }
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve index information for " + table.getName());
+        } finally {
+            _dataContext.close(null, rs, null);
+        }
+    }
+
+    /**
+     * Loads column metadata (no indexes though) for a table
+     * 
+     * @param table
+     */
+    @Override
+    public void loadColumns(JdbcTable table) {
+        final int identity = System.identityHashCode(table);
+        if (_loadedColumns.contains(identity)) {
+            return;
+        }
+        synchronized (this) {
+            if (_loadedColumns.contains(identity)) {
+                return;
+            }
+
+            final Connection connection = _dataContext.getConnection();
+            try {
+                DatabaseMetaData metaData = connection.getMetaData();
+                loadColumns(table, metaData);
+                _loadedColumns.add(identity);
+            } catch (Exception e) {
+                logger.error("Could not load columns for table: " + table, e);
+            } finally {
+                _dataContext.close(connection, null, null);
+            }
+        }
+    }
+
+    private boolean isLobConversionEnabled() {
+        final String systemProperty = System.getProperty(JdbcDataContext.SYSTEM_PROPERTY_CONVERT_LOBS);
+        return "true".equals(systemProperty);
+    }
+
+    private void loadColumns(JdbcTable table, DatabaseMetaData metaData) {
+        final boolean convertLobs = isLobConversionEnabled();
+        final Schema schema = table.getSchema();
+        ResultSet rs = null;
+        try {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Querying for columns in table: " + table.getName());
+            }
+            int columnNumber = -1;
+            if (_usesCatalogsAsSchemas) {
+                rs = metaData.getColumns(schema.getName(), null, table.getName(), null);
+            } else {
+                rs = metaData.getColumns(_dataContext.getCatalogName(), schema.getName(), table.getName(), null);
+            }
+            while (rs.next()) {
+                columnNumber++;
+                final String columnName = rs.getString(4);
+                if (_identifierQuoteString == null && new StringTokenizer(columnName).countTokens() > 1) {
+                    logger.warn("column name contains whitespace: \"" + columnName + "\".");
+                }
+
+                final int jdbcType = rs.getInt(5);
+                final String nativeType = rs.getString(6);
+                final Integer columnSize = rs.getInt(7);
+
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Found column: table=" + table.getName() + ",columnName=" + columnName
+                            + ",nativeType=" + nativeType + ",columnSize=" + columnSize);
+                }
+
+                ColumnType columnType = _dataContext.getQueryRewriter().getColumnType(jdbcType, nativeType, columnSize);
+                if (convertLobs) {
+                    if (columnType == ColumnType.CLOB || columnType == ColumnType.NCLOB) {
+                        columnType = JdbcDataContext.COLUMN_TYPE_CLOB_AS_STRING;
+                    } else if (columnType == ColumnType.BLOB) {
+                        columnType = JdbcDataContext.COLUMN_TYPE_BLOB_AS_BYTES;
+                    }
+                }
+
+                final int jdbcNullable = rs.getInt(11);
+                final Boolean nullable;
+                if (jdbcNullable == DatabaseMetaData.columnNullable) {
+                    nullable = true;
+                } else if (jdbcNullable == DatabaseMetaData.columnNoNulls) {
+                    nullable = false;
+                } else {
+                    nullable = null;
+                }
+
+                final String remarks = rs.getString(12);
+
+                final JdbcColumn column = new JdbcColumn(columnName, columnType, table, columnNumber, nullable);
+                column.setRemarks(remarks);
+                column.setNativeType(nativeType);
+                column.setColumnSize(columnSize);
+                column.setQuote(_identifierQuoteString);
+                table.addColumn(column);
+            }
+
+            final int columnsReturned = columnNumber + 1;
+            if (columnsReturned == 0) {
+                logger.info("No column metadata records returned for table '{}' in schema '{}'", table.getName(),
+                        schema.getName());
+            } else {
+                logger.debug("Returned {} column metadata records for table '{}' in schema '{}'", new Object[] {
+                        columnsReturned, table.getName(), schema.getName() });
+            }
+
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve table metadata for " + table.getName());
+        } finally {
+            _dataContext.close(null, rs, null);
+        }
+    }
+
+    @Override
+    public void loadRelations(JdbcSchema schema) {
+        final int identity = System.identityHashCode(schema);
+        if (_loadedRelations.contains(identity)) {
+            return;
+        }
+        synchronized (this) {
+            if (_loadedRelations.contains(identity)) {
+                return;
+            }
+            final Connection connection = _dataContext.getConnection();
+            try {
+                final Table[] tables = schema.getTables();
+                final DatabaseMetaData metaData = connection.getMetaData();
+                for (Table table : tables) {
+                    loadRelations(table, metaData);
+                }
+                _loadedRelations.add(identity);
+            } catch (Exception e) {
+                logger.error("Could not load relations for schema: " + schema, e);
+            } finally {
+                _dataContext.close(connection, null, null);
+            }
+        }
+    }
+
+    private void loadRelations(Table table, DatabaseMetaData metaData) {
+        Schema schema = table.getSchema();
+        ResultSet rs = null;
+        try {
+            if (_usesCatalogsAsSchemas) {
+                rs = metaData.getImportedKeys(schema.getName(), null, table.getName());
+            } else {
+                rs = metaData.getImportedKeys(_dataContext.getCatalogName(), schema.getName(), table.getName());
+            }
+            loadRelations(rs, schema);
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "retrieve imported keys for " + table.getName());
+        } finally {
+            _dataContext.close(null, rs, null);
+        }
+    }
+
+    private void loadRelations(ResultSet rs, Schema schema) throws SQLException {
+        while (rs.next()) {
+            String pkTableName = rs.getString(3);
+            String pkColumnName = rs.getString(4);
+
+            Column pkColumn = null;
+            Table pkTable = schema.getTableByName(pkTableName);
+            if (pkTable != null) {
+                pkColumn = pkTable.getColumnByName(pkColumnName);
+            }
+            if (logger.isDebugEnabled()) {
+                logger.debug("Found primary key relation: tableName=" + pkTableName + ",columnName=" + pkColumnName
+                        + ", matching column: " + pkColumn);
+            }
+
+            String fkTableName = rs.getString(7);
+            String fkColumnName = rs.getString(8);
+            Column fkColumn = null;
+            Table fkTable = schema.getTableByName(fkTableName);
+            if (fkTable != null) {
+                fkColumn = fkTable.getColumnByName(fkColumnName);
+            }
+            if (logger.isDebugEnabled()) {
+                logger.debug("Found foreign key relation: tableName=" + fkTableName + ",columnName=" + fkColumnName
+                        + ", matching column: " + fkColumn);
+            }
+
+            if (pkColumn == null || fkColumn == null) {
+                logger.error(
+                        "Could not find relation columns: pkTableName={},pkColumnName={},fkTableName={},fkColumnName={}",
+                        new Object[] { pkTableName, pkColumnName, fkTableName, fkColumnName });
+                logger.error("pkColumn={}", pkColumn);
+                logger.error("fkColumn={}", fkColumn);
+            } else {
+                MutableRelationship.createRelationship(new Column[] { pkColumn }, new Column[] { fkColumn });
+            }
+        }
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java
index 87e584f..4969bae 100644
--- a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcUtils.java
@@ -42,6 +42,9 @@ import org.apache.metamodel.util.FormatHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * Various internal utility methods for the JDBC module of MetaModel.
+ */
 public final class JdbcUtils {
 
 	private static final Logger logger = LoggerFactory

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/bd54b1e0/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
----------------------------------------------------------------------
diff --git a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
index 8fc878c..0e24d21 100644
--- a/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
+++ b/jdbc/src/test/java/org/apache/metamodel/jdbc/JdbcTestTemplates.java
@@ -187,7 +187,8 @@ public class JdbcTestTemplates {
         assertFalse(ds.next());
 
         // regular IN (with string)
-        ds = dc.query().from(schema.getTableByName("test_table")).selectCount().where("code").in("C01", "C02").execute();
+        ds = dc.query().from(schema.getTableByName("test_table")).selectCount().where("code").in("C01", "C02")
+                .execute();
         assertTrue(ds.next());
         assertEquals("2", ds.getRow().getValue(0).toString());
         assertFalse(ds.next());
@@ -200,8 +201,8 @@ public class JdbcTestTemplates {
 
         // irregular IN (with null value) - (currently uses SQL's standard way
         // of understanding NULL - see ticket #1058)
-        Query query = dc.query().from(schema.getTableByName("test_table")).selectCount().where("code").in("foobar", null, "baz")
-                .toQuery();
+        Query query = dc.query().from(schema.getTableByName("test_table")).selectCount().where("code")
+                .in("foobar", null, "baz").toQuery();
         String sql = dc.getQueryRewriter().rewriteQuery(query);
 
         assertTrue(sql, sql.endsWith(" IN ('foobar' , 'baz')"));
@@ -272,12 +273,12 @@ public class JdbcTestTemplates {
             @Override
             public void run(UpdateCallback cb) {
                 Table table = cb.createTable(schema, "test_table").withColumn("id").ofType(ColumnType.INTEGER)
-                        .withColumn("birthdate1").ofType(ColumnType.DATE).withColumn("birthdate2").ofType(ColumnType.TIMESTAMP)
-                        .execute();
+                        .withColumn("birthdate1").ofType(ColumnType.DATE).withColumn("birthdate2")
+                        .ofType(ColumnType.TIMESTAMP).execute();
 
                 cb.insertInto(table).value("id", "1").value("birthdate1", null).execute();
-                cb.insertInto(table).value("id", 2).value("birthdate1", "2011-12-21").value("birthdate2", "2011-12-21 14:00:00")
-                        .execute();
+                cb.insertInto(table).value("id", 2).value("birthdate1", "2011-12-21")
+                        .value("birthdate2", "2011-12-21 14:00:00").execute();
             }
         });
 
@@ -302,8 +303,8 @@ public class JdbcTestTemplates {
         assertFalse(ds.next());
         ds.close();
 
-        ds = dc.query().from("test_table").select("id").where("birthdate2").greaterThan(DateUtils.get(2011, Month.DECEMBER, 20))
-                .execute();
+        ds = dc.query().from("test_table").select("id").where("birthdate2")
+                .greaterThan(DateUtils.get(2011, Month.DECEMBER, 20)).execute();
         assertTrue(ds.next());
         assertEquals("Row[values=[2]]", ds.getRow().toString());
         assertFalse(ds.next());
@@ -330,8 +331,8 @@ public class JdbcTestTemplates {
         });
     }
 
-    public static void createInsertAndUpdateDateTypes(final JdbcDataContext dc, final Schema schema, final String tableName)
-            throws Exception {
+    public static void createInsertAndUpdateDateTypes(final JdbcDataContext dc, final Schema schema,
+            final String tableName) throws Exception {
         if (schema.getTableByName(tableName) != null) {
             dc.executeUpdate(new UpdateScript() {
                 @Override
@@ -344,8 +345,9 @@ public class JdbcTestTemplates {
         dc.executeUpdate(new BatchUpdateScript() {
             @Override
             public void run(UpdateCallback cb) {
-                Table table = cb.createTable(schema, tableName).withColumn("id").asPrimaryKey().ofType(ColumnType.INTEGER)
-                        .withColumn("birthdate").ofType(ColumnType.DATE).withColumn("wakemeup").ofType(ColumnType.TIME).execute();
+                Table table = cb.createTable(schema, tableName).withColumn("id").asPrimaryKey()
+                        .ofType(ColumnType.INTEGER).withColumn("birthdate").ofType(ColumnType.DATE)
+                        .withColumn("wakemeup").ofType(ColumnType.TIME).execute();
 
                 // insert record 1
                 {
@@ -381,22 +383,25 @@ public class JdbcTestTemplates {
             }
         });
 
-        DataSet ds = dc.query().from(schema.getTableByName(tableName)).select("id", "birthdate", "wakemeup").orderBy("id")
-                .execute();
+        DataSet ds = dc.query().from(schema.getTableByName(tableName)).select("id", "birthdate", "wakemeup")
+                .orderBy("id").execute();
         assertTrue(ds.next());
         assertEquals("1", ds.getRow().getValue(0).toString());
         assertEquals("1982-04-20", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("07:55:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("07:55:00"));
 
         assertTrue(ds.next());
         assertEquals("2", ds.getRow().getValue(0).toString());
         assertEquals("1982-04-21", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("18:35:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("18:35:00"));
 
         assertTrue(ds.next());
         assertEquals("3", ds.getRow().getValue(0).toString());
         assertEquals("2011-12-21", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("12:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("12:00"));
 
         assertFalse(ds.next());
         ds.close();
@@ -413,27 +418,31 @@ public class JdbcTestTemplates {
                 cal.set(Calendar.MINUTE, 00);
                 Date wakeUpTime = cal.getTime();
 
-                callback.update(schema.getTableByName(tableName)).value("birthdate", DateUtils.get(1982, Month.APRIL, 21))
-                        .value("wakemeup", wakeUpTime).where("birthdate").isEquals(DateUtils.get(1982, Month.APRIL, 20))
-                        .execute();
+                callback.update(schema.getTableByName(tableName))
+                        .value("birthdate", DateUtils.get(1982, Month.APRIL, 21)).value("wakemeup", wakeUpTime)
+                        .where("birthdate").isEquals(DateUtils.get(1982, Month.APRIL, 20)).execute();
             }
         });
 
-        ds = dc.query().from(schema.getTableByName(tableName)).select("id", "birthdate", "wakemeup").orderBy("id").execute();
+        ds = dc.query().from(schema.getTableByName(tableName)).select("id", "birthdate", "wakemeup").orderBy("id")
+                .execute();
         assertTrue(ds.next());
         assertEquals("1", ds.getRow().getValue(0).toString());
         assertEquals("1982-04-21", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("08:00:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("08:00:00"));
 
         assertTrue(ds.next());
         assertEquals("2", ds.getRow().getValue(0).toString());
         assertEquals("1982-04-21", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("18:35:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("18:35:00"));
 
         assertTrue(ds.next());
         assertEquals("3", ds.getRow().getValue(0).toString());
         assertEquals("2011-12-21", ds.getRow().getValue(1).toString());
-        assertTrue("Actual value was: " + ds.getRow().getValue(2), ds.getRow().getValue(2).toString().startsWith("12:00"));
+        assertTrue("Actual value was: " + ds.getRow().getValue(2),
+                ds.getRow().getValue(2).toString().startsWith("12:00"));
 
         assertFalse(ds.next());
         ds.close();
@@ -449,15 +458,15 @@ public class JdbcTestTemplates {
     }
 
     public static void convertClobToString(JdbcDataContext dc) {
-        System.setProperty(JdbcDataContext.SYSTEM_PROPERTY_CONVERT_LOBS, "");
+        System.setProperty(JdbcDataContext.SYSTEM_PROPERTY_CONVERT_LOBS, "true");
 
         final Schema schema = dc.getDefaultSchema();
 
         dc.executeUpdate(new UpdateScript() {
             @Override
             public void run(UpdateCallback callback) {
-                Table table = callback.createTable(schema, "clob_test_table").withColumn("id").ofType(ColumnType.INTEGER)
-                        .asPrimaryKey().withColumn("foo").ofType(ColumnType.CLOB).execute();
+                Table table = callback.createTable(schema, "clob_test_table").withColumn("id")
+                        .ofType(ColumnType.INTEGER).asPrimaryKey().withColumn("foo").ofType(ColumnType.CLOB).execute();
 
                 callback.insertInto(table).value("id", 1).value("foo", "baaaaz").execute();
 
@@ -485,8 +494,6 @@ public class JdbcTestTemplates {
         assertFalse(ds.next());
         ds.close();
 
-        System.setProperty(JdbcDataContext.SYSTEM_PROPERTY_CONVERT_LOBS, "true");
-
         ds = dc.query().from(schema, "clob_test_table").select("id", "foo").orderBy("id").execute();
         assertTrue(ds.next());
         assertEquals("Row[values=[1, baaaaz]]", ds.getRow().toString());