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 2013/07/22 10:10:22 UTC

[09/64] [partial] Hard rename of all 'org/eobjects' folders to 'org/apache'.

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/full/src/main/java/org/apache/metamodel/DataContextFactory.java
----------------------------------------------------------------------
diff --git a/full/src/main/java/org/apache/metamodel/DataContextFactory.java b/full/src/main/java/org/apache/metamodel/DataContextFactory.java
new file mode 100644
index 0000000..5b5598b
--- /dev/null
+++ b/full/src/main/java/org/apache/metamodel/DataContextFactory.java
@@ -0,0 +1,591 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.util.Collection;
+
+import javax.sql.DataSource;
+
+import org.ektorp.http.StdHttpClient.Builder;
+import org.eobjects.metamodel.access.AccessDataContext;
+import org.eobjects.metamodel.couchdb.CouchDbDataContext;
+import org.eobjects.metamodel.csv.CsvConfiguration;
+import org.eobjects.metamodel.csv.CsvDataContext;
+import org.eobjects.metamodel.excel.ExcelConfiguration;
+import org.eobjects.metamodel.excel.ExcelDataContext;
+import org.eobjects.metamodel.fixedwidth.FixedWidthConfiguration;
+import org.eobjects.metamodel.fixedwidth.FixedWidthDataContext;
+import org.eobjects.metamodel.jdbc.JdbcDataContext;
+import org.eobjects.metamodel.mongodb.MongoDbDataContext;
+import org.eobjects.metamodel.openoffice.OpenOfficeDataContext;
+import org.eobjects.metamodel.salesforce.SalesforceDataContext;
+import org.eobjects.metamodel.schema.TableType;
+import org.eobjects.metamodel.sugarcrm.SugarCrmDataContext;
+import org.eobjects.metamodel.util.FileHelper;
+import org.eobjects.metamodel.xml.XmlDomDataContext;
+import org.xml.sax.InputSource;
+
+import com.mongodb.DB;
+import com.mongodb.Mongo;
+
+/**
+ * A factory for DataContext objects. This class substantially easens the task
+ * of creating and initializing DataContext objects and/or their strategies for
+ * reading datastores.
+ * 
+ * @see DataContext
+ */
+public class DataContextFactory {
+
+    public static final char DEFAULT_CSV_SEPARATOR_CHAR = CsvConfiguration.DEFAULT_SEPARATOR_CHAR;
+    public static final char DEFAULT_CSV_QUOTE_CHAR = CsvConfiguration.DEFAULT_QUOTE_CHAR;
+
+    private DataContextFactory() {
+        // Prevent instantiation
+    }
+
+    /**
+     * Creates a composite DataContext based on a set of delegate DataContexts.
+     * 
+     * Composite DataContexts enables cross-DataContext querying and unified
+     * schema exploration
+     * 
+     * @param delegates
+     *            an array/var-args of delegate DataContexts
+     * @return a DataContext that matches the request
+     */
+    public static DataContext createCompositeDataContext(DataContext... delegates) {
+        return new CompositeDataContext(delegates);
+    }
+
+    /**
+     * Creates a composite DataContext based on a set of delegate DataContexts.
+     * 
+     * Composite DataContexts enables cross-DataContext querying and unified
+     * schema exploration
+     * 
+     * @param delegates
+     *            a collection of delegate DataContexts
+     * @return a DataContext that matches the request
+     */
+    public static DataContext createCompositeDataContext(Collection<DataContext> delegates) {
+        return new CompositeDataContext(delegates);
+    }
+
+    /**
+     * Creates a DataContext based on a MS Access (.mdb) file
+     * 
+     * @param filename
+     *            the path to a MS Access (.mdb) file
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createAccessDataContext(String filename) {
+        return new AccessDataContext(filename);
+    }
+
+    /**
+     * Creates a DataContext based on a MS Access (.mdb) file
+     * 
+     * @param file
+     *            a MS Access (.mdb) file
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createAccessDataContext(File file) {
+        return new AccessDataContext(file);
+    }
+
+    /**
+     * Creates a DataContext that connects to a Salesforce.com instance.
+     * 
+     * @param username
+     *            the Salesforce username
+     * @param password
+     *            the Salesforce password
+     * @param securityToken
+     *            the Salesforce security token
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createSalesforceDataContext(String username, String password, String securityToken) {
+        return new SalesforceDataContext(username, password, securityToken);
+    }
+
+    /**
+     * Create a DataContext that connects to a SugarCRM system.
+     * 
+     * @param baseUrl
+     *            the base URL of the system, e.g. http://localhost/sugarcrm
+     * @param username
+     *            the SugarCRM username
+     * @param password
+     *            the SugarCRM password
+     * @param applicationName
+     *            the name of the application you are connecting with
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createSugarCrmDataContext(String baseUrl, String username, String password, String applicationName) {
+        return new SugarCrmDataContext(baseUrl, username, password, applicationName);
+    }
+
+    /**
+     * Creates a DataContext based on a CSV file
+     * 
+     * @param file
+     *            a CSV file
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createCsvDataContext(File file) {
+        return createCsvDataContext(file, DEFAULT_CSV_SEPARATOR_CHAR, DEFAULT_CSV_QUOTE_CHAR);
+    }
+
+    /**
+     * Creates a DataContext based on a CSV file
+     * 
+     * @param file
+     *            a CSV file
+     * @param separatorChar
+     *            the char to use for separating values
+     * @param quoteChar
+     *            the char used for quoting values (typically if they include
+     *            the separator char)
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar) {
+        return createCsvDataContext(file, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
+    }
+
+    /**
+     * Creates a DataContext based on a CSV file
+     * 
+     * @param file
+     *            a CSV file
+     * @param separatorChar
+     *            the char to use for separating values
+     * @param quoteChar
+     *            the char used for quoting values (typically if they include
+     *            the separator char)
+     * @param encoding
+     *            the character encoding of the file
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar, String encoding) {
+        CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
+                quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR);
+        CsvDataContext dc = new CsvDataContext(file, configuration);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on a CSV file
+     * 
+     * @param file
+     *            a CSV file
+     * @param configuration
+     *            the CSV configuration to use
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createCsvDataContext(File file, CsvConfiguration configuration) {
+        CsvDataContext dc = new CsvDataContext(file, configuration);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on CSV-content through an input stream
+     * 
+     * @param inputStream
+     *            the input stream to read from
+     * @param separatorChar
+     *            the char to use for separating values
+     * @param quoteChar
+     *            the char used for quoting values (typically if they include
+     *            the separator char)
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar) {
+        return createCsvDataContext(inputStream, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
+    }
+
+    /**
+     * Creates a DataContext based on CSV-content through an input stream
+     * 
+     * @param inputStream
+     *            the input stream to read from
+     * @param separatorChar
+     *            the char to use for separating values
+     * @param quoteChar
+     *            the char used for quoting values (typically if they include
+     *            the separator char)
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar, String encoding) {
+        CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
+                quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR);
+        CsvDataContext dc = new CsvDataContext(inputStream, configuration);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on CSV-content through an input stream
+     * 
+     * @param inputStream
+     *            the input stream to read from
+     * @param configuration
+     *            the CSV configuration to use
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createCsvDataContext(InputStream inputStream, CsvConfiguration configuration) {
+        CsvDataContext dc = new CsvDataContext(inputStream, configuration);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on a fixed width file.
+     * 
+     * @param file
+     *            the file to read from.
+     * @param fileEncoding
+     *            the character encoding of the file.
+     * @param fixedValueWidth
+     *            the (fixed) width of values in the file.
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth) {
+        return createFixedWidthDataContext(file, new FixedWidthConfiguration(FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE,
+                fileEncoding, fixedValueWidth));
+    }
+
+    /**
+     * Creates a DataContext based on a fixed width file.
+     * 
+     * @param file
+     *            the file to read from.
+     * @param configuration
+     *            the fixed width configuration to use
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createFixedWidthDataContext(File file, FixedWidthConfiguration configuration) {
+        FixedWidthDataContext dc = new FixedWidthDataContext(file, configuration);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on a fixed width file.
+     * 
+     * @param file
+     *            the file to read from.
+     * @param fileEncoding
+     *            the character encoding of the file.
+     * @param fixedValueWidth
+     *            the (fixed) width of values in the file.
+     * @param headerLineNumber
+     *            the line number of the column headers.
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth,
+            int headerLineNumber) {
+        return createFixedWidthDataContext(file, new FixedWidthConfiguration(FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE,
+                fileEncoding, fixedValueWidth));
+    }
+
+    /**
+     * Creates a DataContet based on an Excel spreadsheet file
+     * 
+     * @param file
+     *            an excel spreadsheet file
+     * @param configuration
+     *            the configuration with metadata for reading the spreadsheet
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createExcelDataContext(File file, ExcelConfiguration configuration) {
+        return new ExcelDataContext(file, configuration);
+    }
+
+    /**
+     * Creates a DataContext based on an Excel spreadsheet file
+     * 
+     * @param file
+     *            an Excel spreadsheet file
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createExcelDataContext(File file) {
+        return createExcelDataContext(file, new ExcelConfiguration());
+    }
+
+    /**
+     * Creates a DataContext based on XML-content from an input source.
+     * 
+     * Tables are created by examining the data in the XML file, NOT by reading
+     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
+     * also raises a risk that two XML files with the same format wont
+     * nescesarily yield the same table model if some optional attributes or
+     * tags are omitted in one of the files.
+     * 
+     * @param inputSource
+     *            an input source feeding XML content
+     * @param schemaName
+     *            the name to be used for the main schema
+     * @param autoFlattenTables
+     *            a boolean indicating if MetaModel should flatten very simple
+     *            table structures (where tables only contain a single
+     *            data-carrying column) for greater usability of the generated
+     *            table-based model
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createXmlDataContext(InputSource inputSource, String schemaName, boolean autoFlattenTables) {
+        XmlDomDataContext dc = new XmlDomDataContext(inputSource, schemaName, autoFlattenTables);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on XML-content from a File.
+     * 
+     * Tables are created by examining the data in the XML file, NOT by reading
+     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
+     * also raises a risk that two XML files with the same format wont
+     * nescesarily yield the same table model if some optional attributes or
+     * tags are omitted in one of the files.
+     * 
+     * @param file
+     *            the File to use for feeding XML content
+     * @param autoFlattenTables
+     *            a boolean indicating if MetaModel should flatten very simple
+     *            table structures (where tables only contain a single
+     *            data-carrying column) for greater usability of the generated
+     *            table-based model
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createXmlDataContext(File file, boolean autoFlattenTables) {
+        XmlDomDataContext dc = new XmlDomDataContext(file, autoFlattenTables);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on XML-content from a URL.
+     * 
+     * Tables are created by examining the data in the XML file, NOT by reading
+     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
+     * also raises a risk that two XML files with the same format wont
+     * nescesarily yield the same table model if some optional attributes or
+     * tags are omitted in one of the files.
+     * 
+     * @param url
+     *            the URL to use for feeding XML content
+     * @param autoFlattenTables
+     *            a boolean indicating if MetaModel should flatten very simple
+     *            table structures (where tables only contain a single
+     *            data-carrying column) for greater usability of the generated
+     *            table-based model
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createXmlDataContext(URL url, boolean autoFlattenTables) {
+        XmlDomDataContext dc = new XmlDomDataContext(url, autoFlattenTables);
+        return dc;
+    }
+
+    /**
+     * Creates a DataContext based on an OpenOffice.org database file.
+     * 
+     * @param file
+     *            an OpenOffice.org database file
+     * @return a DataContext object that matches the request
+     */
+    public static DataContext createOpenOfficeDataContext(File file) {
+        return new OpenOfficeDataContext(file);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC connection
+     * 
+     * @param connection
+     *            a JDBC connection
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(Connection connection) {
+        return new JdbcDataContext(connection);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC datasource
+     * 
+     * @param ds
+     *            a JDBC datasource
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(DataSource ds) {
+        return new JdbcDataContext(ds);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC connection
+     * 
+     * @param connection
+     *            a JDBC connection
+     * @param catalogName
+     *            a catalog name to use
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName) {
+        return new JdbcDataContext(connection, TableType.DEFAULT_TABLE_TYPES, catalogName);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC connection
+     * 
+     * @param connection
+     *            a JDBC connection
+     * @param tableTypes
+     *            the types of tables to include in the generated schemas
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(Connection connection, TableType... tableTypes) {
+        return new JdbcDataContext(connection, tableTypes, null);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC connection
+     * 
+     * @param connection
+     *            a JDBC connection
+     * @param catalogName
+     *            a catalog name to use
+     * @param tableTypes
+     *            the types of tables to include in the generated schemas
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName, TableType[] tableTypes) {
+        return new JdbcDataContext(connection, tableTypes, catalogName);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC datasource
+     * 
+     * @param ds
+     *            a JDBC datasource
+     * @param tableTypes
+     *            the types of tables to include in the generated schemas
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(DataSource ds, TableType... tableTypes) {
+        return new JdbcDataContext(ds, tableTypes, null);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC datasource
+     * 
+     * @param ds
+     *            a JDBC datasource
+     * @param catalogName
+     *            a catalog name to use
+     * @param tableTypes
+     *            the types of tables to include in the generated schemas
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName, TableType[] tableTypes) {
+        return new JdbcDataContext(ds, tableTypes, catalogName);
+    }
+
+    /**
+     * Creates a DataContext based on a JDBC datasource
+     * 
+     * @param ds
+     *            a JDBC datasource
+     * @param catalogName
+     *            a catalog name to use
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName) {
+        return new JdbcDataContext(ds, TableType.DEFAULT_TABLE_TYPES, catalogName);
+    }
+
+    /**
+     * Creates a new MongoDB datacontext.
+     * 
+     * @param hostname
+     *            The hostname of the MongoDB instance
+     * @param port
+     *            the port of the MongoDB instance, or null if the default port
+     *            should be used.
+     * @param databaseName
+     *            the name of the database
+     * @param username
+     *            the username, or null if unauthenticated access should be used
+     * @param password
+     *            the password, or null if unathenticated access should be used
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createMongoDbDataContext(String hostname, Integer port, String databaseName,
+            String username, char[] password) {
+        try {
+            DB mongoDb;
+            if (port == null) {
+                mongoDb = new Mongo(hostname).getDB(databaseName);
+            } else {
+                mongoDb = new Mongo(hostname, port).getDB(databaseName);
+            }
+            if (username != null) {
+                mongoDb.authenticate(username, password);
+            }
+            return new MongoDbDataContext(mongoDb);
+        } catch (Exception e) {
+            if (e instanceof RuntimeException) {
+                throw (RuntimeException) e;
+            }
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Creates a new CouchDB datacontext.
+     * 
+     * @param hostname
+     *            The hostname of the CouchDB instance
+     * @param port
+     *            the port of the CouchDB instance, or null if the default port
+     *            should be used.
+     * @param username
+     *            the username, or null if unauthenticated access should be used
+     * @param password
+     *            the password, or null if unathenticated access should be used
+     * @return a DataContext object that matches the request
+     */
+    public static UpdateableDataContext createCouchDbDataContext(String hostname, Integer port, String username, String password) {
+
+        Builder httpClientBuilder = new Builder();
+        httpClientBuilder.host(hostname);
+        if (port != null) {
+            httpClientBuilder.port(port);
+        }
+        if (username != null) {
+            httpClientBuilder.username(username);
+        }
+        if (password != null) {
+            httpClientBuilder.password(password);
+        }
+
+        // increased timeouts (20 sec) - metamodel typically does quite some
+        // batching so it might take a bit of time to provide a connection.
+        httpClientBuilder.connectionTimeout(20000);
+        httpClientBuilder.socketTimeout(20000);
+
+        return new CouchDbDataContext(httpClientBuilder);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/full/src/main/java/org/eobjects/metamodel/DataContextFactory.java
----------------------------------------------------------------------
diff --git a/full/src/main/java/org/eobjects/metamodel/DataContextFactory.java b/full/src/main/java/org/eobjects/metamodel/DataContextFactory.java
deleted file mode 100644
index 5b5598b..0000000
--- a/full/src/main/java/org/eobjects/metamodel/DataContextFactory.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.eobjects.metamodel;
-
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.sql.Connection;
-import java.util.Collection;
-
-import javax.sql.DataSource;
-
-import org.ektorp.http.StdHttpClient.Builder;
-import org.eobjects.metamodel.access.AccessDataContext;
-import org.eobjects.metamodel.couchdb.CouchDbDataContext;
-import org.eobjects.metamodel.csv.CsvConfiguration;
-import org.eobjects.metamodel.csv.CsvDataContext;
-import org.eobjects.metamodel.excel.ExcelConfiguration;
-import org.eobjects.metamodel.excel.ExcelDataContext;
-import org.eobjects.metamodel.fixedwidth.FixedWidthConfiguration;
-import org.eobjects.metamodel.fixedwidth.FixedWidthDataContext;
-import org.eobjects.metamodel.jdbc.JdbcDataContext;
-import org.eobjects.metamodel.mongodb.MongoDbDataContext;
-import org.eobjects.metamodel.openoffice.OpenOfficeDataContext;
-import org.eobjects.metamodel.salesforce.SalesforceDataContext;
-import org.eobjects.metamodel.schema.TableType;
-import org.eobjects.metamodel.sugarcrm.SugarCrmDataContext;
-import org.eobjects.metamodel.util.FileHelper;
-import org.eobjects.metamodel.xml.XmlDomDataContext;
-import org.xml.sax.InputSource;
-
-import com.mongodb.DB;
-import com.mongodb.Mongo;
-
-/**
- * A factory for DataContext objects. This class substantially easens the task
- * of creating and initializing DataContext objects and/or their strategies for
- * reading datastores.
- * 
- * @see DataContext
- */
-public class DataContextFactory {
-
-    public static final char DEFAULT_CSV_SEPARATOR_CHAR = CsvConfiguration.DEFAULT_SEPARATOR_CHAR;
-    public static final char DEFAULT_CSV_QUOTE_CHAR = CsvConfiguration.DEFAULT_QUOTE_CHAR;
-
-    private DataContextFactory() {
-        // Prevent instantiation
-    }
-
-    /**
-     * Creates a composite DataContext based on a set of delegate DataContexts.
-     * 
-     * Composite DataContexts enables cross-DataContext querying and unified
-     * schema exploration
-     * 
-     * @param delegates
-     *            an array/var-args of delegate DataContexts
-     * @return a DataContext that matches the request
-     */
-    public static DataContext createCompositeDataContext(DataContext... delegates) {
-        return new CompositeDataContext(delegates);
-    }
-
-    /**
-     * Creates a composite DataContext based on a set of delegate DataContexts.
-     * 
-     * Composite DataContexts enables cross-DataContext querying and unified
-     * schema exploration
-     * 
-     * @param delegates
-     *            a collection of delegate DataContexts
-     * @return a DataContext that matches the request
-     */
-    public static DataContext createCompositeDataContext(Collection<DataContext> delegates) {
-        return new CompositeDataContext(delegates);
-    }
-
-    /**
-     * Creates a DataContext based on a MS Access (.mdb) file
-     * 
-     * @param filename
-     *            the path to a MS Access (.mdb) file
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createAccessDataContext(String filename) {
-        return new AccessDataContext(filename);
-    }
-
-    /**
-     * Creates a DataContext based on a MS Access (.mdb) file
-     * 
-     * @param file
-     *            a MS Access (.mdb) file
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createAccessDataContext(File file) {
-        return new AccessDataContext(file);
-    }
-
-    /**
-     * Creates a DataContext that connects to a Salesforce.com instance.
-     * 
-     * @param username
-     *            the Salesforce username
-     * @param password
-     *            the Salesforce password
-     * @param securityToken
-     *            the Salesforce security token
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createSalesforceDataContext(String username, String password, String securityToken) {
-        return new SalesforceDataContext(username, password, securityToken);
-    }
-
-    /**
-     * Create a DataContext that connects to a SugarCRM system.
-     * 
-     * @param baseUrl
-     *            the base URL of the system, e.g. http://localhost/sugarcrm
-     * @param username
-     *            the SugarCRM username
-     * @param password
-     *            the SugarCRM password
-     * @param applicationName
-     *            the name of the application you are connecting with
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createSugarCrmDataContext(String baseUrl, String username, String password, String applicationName) {
-        return new SugarCrmDataContext(baseUrl, username, password, applicationName);
-    }
-
-    /**
-     * Creates a DataContext based on a CSV file
-     * 
-     * @param file
-     *            a CSV file
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createCsvDataContext(File file) {
-        return createCsvDataContext(file, DEFAULT_CSV_SEPARATOR_CHAR, DEFAULT_CSV_QUOTE_CHAR);
-    }
-
-    /**
-     * Creates a DataContext based on a CSV file
-     * 
-     * @param file
-     *            a CSV file
-     * @param separatorChar
-     *            the char to use for separating values
-     * @param quoteChar
-     *            the char used for quoting values (typically if they include
-     *            the separator char)
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar) {
-        return createCsvDataContext(file, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
-    }
-
-    /**
-     * Creates a DataContext based on a CSV file
-     * 
-     * @param file
-     *            a CSV file
-     * @param separatorChar
-     *            the char to use for separating values
-     * @param quoteChar
-     *            the char used for quoting values (typically if they include
-     *            the separator char)
-     * @param encoding
-     *            the character encoding of the file
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createCsvDataContext(File file, char separatorChar, char quoteChar, String encoding) {
-        CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
-                quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR);
-        CsvDataContext dc = new CsvDataContext(file, configuration);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on a CSV file
-     * 
-     * @param file
-     *            a CSV file
-     * @param configuration
-     *            the CSV configuration to use
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createCsvDataContext(File file, CsvConfiguration configuration) {
-        CsvDataContext dc = new CsvDataContext(file, configuration);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on CSV-content through an input stream
-     * 
-     * @param inputStream
-     *            the input stream to read from
-     * @param separatorChar
-     *            the char to use for separating values
-     * @param quoteChar
-     *            the char used for quoting values (typically if they include
-     *            the separator char)
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar) {
-        return createCsvDataContext(inputStream, separatorChar, quoteChar, FileHelper.DEFAULT_ENCODING);
-    }
-
-    /**
-     * Creates a DataContext based on CSV-content through an input stream
-     * 
-     * @param inputStream
-     *            the input stream to read from
-     * @param separatorChar
-     *            the char to use for separating values
-     * @param quoteChar
-     *            the char used for quoting values (typically if they include
-     *            the separator char)
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createCsvDataContext(InputStream inputStream, char separatorChar, char quoteChar, String encoding) {
-        CsvConfiguration configuration = new CsvConfiguration(CsvConfiguration.DEFAULT_COLUMN_NAME_LINE, encoding, separatorChar,
-                quoteChar, CsvConfiguration.DEFAULT_ESCAPE_CHAR);
-        CsvDataContext dc = new CsvDataContext(inputStream, configuration);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on CSV-content through an input stream
-     * 
-     * @param inputStream
-     *            the input stream to read from
-     * @param configuration
-     *            the CSV configuration to use
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createCsvDataContext(InputStream inputStream, CsvConfiguration configuration) {
-        CsvDataContext dc = new CsvDataContext(inputStream, configuration);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on a fixed width file.
-     * 
-     * @param file
-     *            the file to read from.
-     * @param fileEncoding
-     *            the character encoding of the file.
-     * @param fixedValueWidth
-     *            the (fixed) width of values in the file.
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth) {
-        return createFixedWidthDataContext(file, new FixedWidthConfiguration(FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE,
-                fileEncoding, fixedValueWidth));
-    }
-
-    /**
-     * Creates a DataContext based on a fixed width file.
-     * 
-     * @param file
-     *            the file to read from.
-     * @param configuration
-     *            the fixed width configuration to use
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createFixedWidthDataContext(File file, FixedWidthConfiguration configuration) {
-        FixedWidthDataContext dc = new FixedWidthDataContext(file, configuration);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on a fixed width file.
-     * 
-     * @param file
-     *            the file to read from.
-     * @param fileEncoding
-     *            the character encoding of the file.
-     * @param fixedValueWidth
-     *            the (fixed) width of values in the file.
-     * @param headerLineNumber
-     *            the line number of the column headers.
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createFixedWidthDataContext(File file, String fileEncoding, int fixedValueWidth,
-            int headerLineNumber) {
-        return createFixedWidthDataContext(file, new FixedWidthConfiguration(FixedWidthConfiguration.DEFAULT_COLUMN_NAME_LINE,
-                fileEncoding, fixedValueWidth));
-    }
-
-    /**
-     * Creates a DataContet based on an Excel spreadsheet file
-     * 
-     * @param file
-     *            an excel spreadsheet file
-     * @param configuration
-     *            the configuration with metadata for reading the spreadsheet
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createExcelDataContext(File file, ExcelConfiguration configuration) {
-        return new ExcelDataContext(file, configuration);
-    }
-
-    /**
-     * Creates a DataContext based on an Excel spreadsheet file
-     * 
-     * @param file
-     *            an Excel spreadsheet file
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createExcelDataContext(File file) {
-        return createExcelDataContext(file, new ExcelConfiguration());
-    }
-
-    /**
-     * Creates a DataContext based on XML-content from an input source.
-     * 
-     * Tables are created by examining the data in the XML file, NOT by reading
-     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
-     * also raises a risk that two XML files with the same format wont
-     * nescesarily yield the same table model if some optional attributes or
-     * tags are omitted in one of the files.
-     * 
-     * @param inputSource
-     *            an input source feeding XML content
-     * @param schemaName
-     *            the name to be used for the main schema
-     * @param autoFlattenTables
-     *            a boolean indicating if MetaModel should flatten very simple
-     *            table structures (where tables only contain a single
-     *            data-carrying column) for greater usability of the generated
-     *            table-based model
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createXmlDataContext(InputSource inputSource, String schemaName, boolean autoFlattenTables) {
-        XmlDomDataContext dc = new XmlDomDataContext(inputSource, schemaName, autoFlattenTables);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on XML-content from a File.
-     * 
-     * Tables are created by examining the data in the XML file, NOT by reading
-     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
-     * also raises a risk that two XML files with the same format wont
-     * nescesarily yield the same table model if some optional attributes or
-     * tags are omitted in one of the files.
-     * 
-     * @param file
-     *            the File to use for feeding XML content
-     * @param autoFlattenTables
-     *            a boolean indicating if MetaModel should flatten very simple
-     *            table structures (where tables only contain a single
-     *            data-carrying column) for greater usability of the generated
-     *            table-based model
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createXmlDataContext(File file, boolean autoFlattenTables) {
-        XmlDomDataContext dc = new XmlDomDataContext(file, autoFlattenTables);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on XML-content from a URL.
-     * 
-     * Tables are created by examining the data in the XML file, NOT by reading
-     * XML Schemas (xsd/dtd's). This enables compliancy with ALL xml formats but
-     * also raises a risk that two XML files with the same format wont
-     * nescesarily yield the same table model if some optional attributes or
-     * tags are omitted in one of the files.
-     * 
-     * @param url
-     *            the URL to use for feeding XML content
-     * @param autoFlattenTables
-     *            a boolean indicating if MetaModel should flatten very simple
-     *            table structures (where tables only contain a single
-     *            data-carrying column) for greater usability of the generated
-     *            table-based model
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createXmlDataContext(URL url, boolean autoFlattenTables) {
-        XmlDomDataContext dc = new XmlDomDataContext(url, autoFlattenTables);
-        return dc;
-    }
-
-    /**
-     * Creates a DataContext based on an OpenOffice.org database file.
-     * 
-     * @param file
-     *            an OpenOffice.org database file
-     * @return a DataContext object that matches the request
-     */
-    public static DataContext createOpenOfficeDataContext(File file) {
-        return new OpenOfficeDataContext(file);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC connection
-     * 
-     * @param connection
-     *            a JDBC connection
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(Connection connection) {
-        return new JdbcDataContext(connection);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC datasource
-     * 
-     * @param ds
-     *            a JDBC datasource
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(DataSource ds) {
-        return new JdbcDataContext(ds);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC connection
-     * 
-     * @param connection
-     *            a JDBC connection
-     * @param catalogName
-     *            a catalog name to use
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName) {
-        return new JdbcDataContext(connection, TableType.DEFAULT_TABLE_TYPES, catalogName);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC connection
-     * 
-     * @param connection
-     *            a JDBC connection
-     * @param tableTypes
-     *            the types of tables to include in the generated schemas
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(Connection connection, TableType... tableTypes) {
-        return new JdbcDataContext(connection, tableTypes, null);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC connection
-     * 
-     * @param connection
-     *            a JDBC connection
-     * @param catalogName
-     *            a catalog name to use
-     * @param tableTypes
-     *            the types of tables to include in the generated schemas
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(Connection connection, String catalogName, TableType[] tableTypes) {
-        return new JdbcDataContext(connection, tableTypes, catalogName);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC datasource
-     * 
-     * @param ds
-     *            a JDBC datasource
-     * @param tableTypes
-     *            the types of tables to include in the generated schemas
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(DataSource ds, TableType... tableTypes) {
-        return new JdbcDataContext(ds, tableTypes, null);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC datasource
-     * 
-     * @param ds
-     *            a JDBC datasource
-     * @param catalogName
-     *            a catalog name to use
-     * @param tableTypes
-     *            the types of tables to include in the generated schemas
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName, TableType[] tableTypes) {
-        return new JdbcDataContext(ds, tableTypes, catalogName);
-    }
-
-    /**
-     * Creates a DataContext based on a JDBC datasource
-     * 
-     * @param ds
-     *            a JDBC datasource
-     * @param catalogName
-     *            a catalog name to use
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createJdbcDataContext(DataSource ds, String catalogName) {
-        return new JdbcDataContext(ds, TableType.DEFAULT_TABLE_TYPES, catalogName);
-    }
-
-    /**
-     * Creates a new MongoDB datacontext.
-     * 
-     * @param hostname
-     *            The hostname of the MongoDB instance
-     * @param port
-     *            the port of the MongoDB instance, or null if the default port
-     *            should be used.
-     * @param databaseName
-     *            the name of the database
-     * @param username
-     *            the username, or null if unauthenticated access should be used
-     * @param password
-     *            the password, or null if unathenticated access should be used
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createMongoDbDataContext(String hostname, Integer port, String databaseName,
-            String username, char[] password) {
-        try {
-            DB mongoDb;
-            if (port == null) {
-                mongoDb = new Mongo(hostname).getDB(databaseName);
-            } else {
-                mongoDb = new Mongo(hostname, port).getDB(databaseName);
-            }
-            if (username != null) {
-                mongoDb.authenticate(username, password);
-            }
-            return new MongoDbDataContext(mongoDb);
-        } catch (Exception e) {
-            if (e instanceof RuntimeException) {
-                throw (RuntimeException) e;
-            }
-            throw new IllegalStateException(e);
-        }
-    }
-
-    /**
-     * Creates a new CouchDB datacontext.
-     * 
-     * @param hostname
-     *            The hostname of the CouchDB instance
-     * @param port
-     *            the port of the CouchDB instance, or null if the default port
-     *            should be used.
-     * @param username
-     *            the username, or null if unauthenticated access should be used
-     * @param password
-     *            the password, or null if unathenticated access should be used
-     * @return a DataContext object that matches the request
-     */
-    public static UpdateableDataContext createCouchDbDataContext(String hostname, Integer port, String username, String password) {
-
-        Builder httpClientBuilder = new Builder();
-        httpClientBuilder.host(hostname);
-        if (port != null) {
-            httpClientBuilder.port(port);
-        }
-        if (username != null) {
-            httpClientBuilder.username(username);
-        }
-        if (password != null) {
-            httpClientBuilder.password(password);
-        }
-
-        // increased timeouts (20 sec) - metamodel typically does quite some
-        // batching so it might take a bit of time to provide a connection.
-        httpClientBuilder.connectionTimeout(20000);
-        httpClientBuilder.socketTimeout(20000);
-
-        return new CouchDbDataContext(httpClientBuilder);
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/full/src/test/java/org/apache/metamodel/DataContextFactoryTest.java
----------------------------------------------------------------------
diff --git a/full/src/test/java/org/apache/metamodel/DataContextFactoryTest.java b/full/src/test/java/org/apache/metamodel/DataContextFactoryTest.java
new file mode 100644
index 0000000..5bf24e1
--- /dev/null
+++ b/full/src/test/java/org/apache/metamodel/DataContextFactoryTest.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel;
+
+import java.io.File;
+
+import org.eobjects.metamodel.excel.ExcelConfiguration;
+import org.eobjects.metamodel.excel.ExcelDataContext;
+
+import junit.framework.TestCase;
+
+public class DataContextFactoryTest extends TestCase {
+
+    public void testCreateExcelDataContext() throws Exception {
+        File file = new File("../excel/src/test/resources/xls_people.xls");
+        assertTrue(file.exists());
+
+        UpdateableDataContext dc;
+
+        dc = DataContextFactory.createExcelDataContext(file);
+        assertNotNull(dc);
+        assertTrue(dc instanceof ExcelDataContext);
+
+        dc = DataContextFactory.createExcelDataContext(file,
+                new ExcelConfiguration());
+        assertNotNull(dc);
+        assertTrue(dc instanceof ExcelDataContext);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/full/src/test/java/org/eobjects/metamodel/DataContextFactoryTest.java
----------------------------------------------------------------------
diff --git a/full/src/test/java/org/eobjects/metamodel/DataContextFactoryTest.java b/full/src/test/java/org/eobjects/metamodel/DataContextFactoryTest.java
deleted file mode 100644
index 374c1b7..0000000
--- a/full/src/test/java/org/eobjects/metamodel/DataContextFactoryTest.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.eobjects.metamodel;
-
-import java.io.File;
-
-import org.eobjects.metamodel.excel.ExcelConfiguration;
-import org.eobjects.metamodel.excel.ExcelDataContext;
-
-import junit.framework.TestCase;
-
-public class DataContextFactoryTest extends TestCase {
-
-    public void testCreateExcelDataContext() throws Exception {
-        File file = new File("../excel/src/test/resources/xls_people.xls");
-        assertTrue(file.exists());
-
-        UpdateableDataContext dc;
-
-        dc = DataContextFactory.createExcelDataContext(file);
-        assertNotNull(dc);
-        assertTrue(dc instanceof ExcelDataContext);
-
-        dc = DataContextFactory.createExcelDataContext(file,
-                new ExcelConfiguration());
-        assertNotNull(dc);
-        assertTrue(dc instanceof ExcelDataContext);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/FetchSizeCalculator.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/FetchSizeCalculator.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/FetchSizeCalculator.java
new file mode 100644
index 0000000..155adf9
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/FetchSizeCalculator.java
@@ -0,0 +1,264 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.util.List;
+
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class used to calculate an appropriate fetch size of a JDBC query.
+ * 
+ * The approach used in this class is largely based on the documentation of
+ * Oracle's caching size, see <a href=
+ * "http://www.oracle.com/technetwork/database/enterprise-edition/memory.pdf"
+ * >JDBC Memory Management</a>, section "Where does it all go?".
+ * 
+ * @author Kasper Sørensen
+ */
+final class FetchSizeCalculator {
+
+	/**
+	 * 22 bytes is a reasonable approximation for remaining row types, we add a
+	 * few bytes to be on the safe side.
+	 */
+	private static final int DEFAULT_COLUMN_SIZE = 30;
+
+	/**
+	 * A kilobyte (kb)
+	 */
+	private static final int KB = 1024;
+
+	private static final Logger logger = LoggerFactory
+			.getLogger(FetchSizeCalculator.class);
+
+	private static final int MIN_FETCH_SIZE = 1;
+	private static final int MAX_FETCH_SIZE = 25000;
+	private final int _bytesInMemory;
+
+	public FetchSizeCalculator(int bytesInMemory) {
+		_bytesInMemory = bytesInMemory;
+	}
+
+	/**
+	 * Gets the fetch size of a query
+	 * 
+	 * @param query
+	 *            the query to execute
+	 * @return an integer representing how many rows to eagerly fetch for the
+	 *         query
+	 */
+	public int getFetchSize(Query query) {
+		if (isSingleRowQuery(query)) {
+			return 1;
+		}
+		int bytesPerRow = getRowSize(query);
+		int result = getFetchSize(bytesPerRow);
+		final Integer maxRows = query.getMaxRows();
+		if (maxRows != null && result > maxRows) {
+			logger.debug("Result ({}) was below max rows ({}), adjusting.",
+					result, maxRows);
+			result = maxRows;
+		}
+		return result;
+	}
+
+	/**
+	 * Gets whether a query is guaranteed to only yield a single row. Such
+	 * queries are queries that only consist of aggregation functions and no
+	 * group by clause.
+	 * 
+	 * @param query
+	 * @return
+	 */
+	private boolean isSingleRowQuery(Query query) {
+		if (!query.getGroupByClause().isEmpty()) {
+			return false;
+		}
+
+		List<SelectItem> items = query.getSelectClause().getItems();
+		for (SelectItem item : items) {
+			if (item.getFunction() == null) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * Gets the fetch size of a query based on the columns to query.
+	 * 
+	 * @param columns
+	 *            the columns to query
+	 * @return an integer representing how many rows to eagerly fetch for the
+	 *         query
+	 */
+	public int getFetchSize(Column... columns) {
+		int bytesPerRow = getRowSize(columns);
+		return getFetchSize(bytesPerRow);
+	}
+
+	/**
+	 * Gets the size of a row (in bytes).
+	 * 
+	 * @param query
+	 *            the query that will yield the rows
+	 * @return an integer representing the size of a row from the given query
+	 *         (in bytes).
+	 */
+	protected int getRowSize(Query query) {
+		List<SelectItem> items = query.getSelectClause().getItems();
+		int bytesPerRow = 0;
+		for (SelectItem selectItem : items) {
+			bytesPerRow += getValueSize(selectItem);
+		}
+		return bytesPerRow;
+	}
+
+	/**
+	 * Gets the size of a row (in bytes).
+	 * 
+	 * @param columns
+	 *            the columns in the row
+	 * @return an integer representing the size of a row with the given columns
+	 *         (in bytes).
+	 */
+	protected int getRowSize(Column... columns) {
+		int bytesPerRow = 0;
+		for (Column column : columns) {
+			bytesPerRow += getValueSize(column);
+		}
+		return bytesPerRow;
+	}
+
+	/**
+	 * Gets the principal fetch size for a query where a row has the given size.
+	 * 
+	 * @param bytesPerRow
+	 *            the size (in bytes) of a single row in the result set.
+	 * @return an appropriate fetch size.
+	 */
+	protected int getFetchSize(int bytesPerRow) {
+		if (bytesPerRow == 0) {
+			// prevent divide by zero
+			return MAX_FETCH_SIZE;
+		}
+		int result = _bytesInMemory / bytesPerRow;
+		if (result < MIN_FETCH_SIZE) {
+			logger.debug(
+					"Result ({}) was below minimum fetch size ({}), adjusting.",
+					result, MIN_FETCH_SIZE);
+			result = MIN_FETCH_SIZE;
+		} else if (result > MAX_FETCH_SIZE) {
+			logger.debug(
+					"Result ({}) was above maximum fetch size ({}), adjusting.",
+					result, MAX_FETCH_SIZE);
+			result = MAX_FETCH_SIZE;
+		}
+		return result;
+	}
+
+	/**
+	 * Gets the size (in bytes) of a single {@link SelectItem}
+	 */
+	protected int getValueSize(SelectItem selectItem) {
+		Column column = selectItem.getColumn();
+		if (column == null) {
+			return DEFAULT_COLUMN_SIZE;
+		} else {
+			return getValueSize(column);
+		}
+	}
+
+	/**
+	 * Gets the size (in bytes) of a single {@link Column}
+	 */
+	protected int getValueSize(Column column) {
+		ColumnType type = column.getType();
+		if (type == null) {
+			return DEFAULT_COLUMN_SIZE;
+		} else {
+			Integer columnSize = column.getColumnSize();
+			if (columnSize == null) {
+				// if column size is missing, then use
+				// size-indifferent approach
+				return getSize(type);
+			} else if (columnSize > 10000 && !type.isLargeObject()) {
+				// if column size is unrealistically high, then use
+				// size-indifferent approach
+				return getSize(type);
+			} else {
+				return getSize(type, columnSize);
+			}
+		}
+	}
+
+	/**
+	 * Gets the size (in bytes) of a column with a specific {@link ColumnType}
+	 * and size
+	 */
+	private int getSize(ColumnType type, int columnSize) {
+		final int baseSize;
+		if (type.isBinary()) {
+			baseSize = 1;
+		} else if (type.isBoolean()) {
+			baseSize = 1;
+		} else if (type.isLiteral()) {
+			baseSize = 2;
+		} else if (type.isNumber()) {
+			baseSize = 16;
+		} else {
+			baseSize = DEFAULT_COLUMN_SIZE;
+		}
+
+		int result = baseSize * columnSize;
+
+		if (type.isLargeObject()) {
+			// assign at least 4KB for LOBs.
+			result = Math.max(result, 4 * KB);
+		}
+
+		return result;
+	}
+
+	/**
+	 * Gets the (approximate) size (in bytes) of a column with a specific
+	 * {@link ColumnType}.
+	 */
+	private int getSize(ColumnType type) {
+		if (type.isBinary()) {
+			return 4 * KB;
+		} else if (type.isBoolean()) {
+			return 2;
+		} else if (type.isLargeObject()) {
+			return 4 * KB;
+		} else if (type.isLiteral()) {
+			return KB;
+		} else if (type.isNumber()) {
+			return 16;
+		} else {
+			return DEFAULT_COLUMN_SIZE;
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
new file mode 100644
index 0000000..50e38a4
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcBatchUpdateCallback.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.eobjects.metamodel.UpdateCallback;
+import org.eobjects.metamodel.util.FileHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Jdbc {@link UpdateCallback} for databases that support the JDBC Batch
+ * features.
+ * 
+ * @author Kasper Sørensen
+ */
+final class JdbcBatchUpdateCallback extends JdbcUpdateCallback {
+
+    private static final Logger logger = LoggerFactory.getLogger(JdbcBatchUpdateCallback.class);
+
+    public JdbcBatchUpdateCallback(JdbcDataContext dataContext) {
+        super(dataContext);
+    }
+
+    @Override
+    protected void closePreparedStatement(PreparedStatement preparedStatement) {
+        try {
+            int[] results = preparedStatement.executeBatch();
+            if (logger.isDebugEnabled()) {
+                for (int i = 0; i < results.length; i++) {
+                    int result = results[i];
+                    final String resultString;
+                    switch (result) {
+                    case Statement.SUCCESS_NO_INFO:
+                        resultString = "SUCCESS_NO_INFO";
+                        break;
+                    case Statement.EXECUTE_FAILED:
+                        resultString = "EXECUTE_FAILED";
+                        break;
+                    default:
+                        resultString = result + " rows updated";
+                    }
+                    logger.debug("batch execute result[" + i + "]:" + resultString);
+                }
+            }
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "execute batch: " + preparedStatement);
+        } finally {
+            FileHelper.safeClose(preparedStatement);
+        }
+    }
+
+    @Override
+    protected void executePreparedStatement(PreparedStatement st) throws SQLException {
+        st.addBatch();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcColumn.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcColumn.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcColumn.java
new file mode 100644
index 0000000..de09ce7
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcColumn.java
@@ -0,0 +1,55 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.Table;
+
+/**
+ * Column implementation for JDBC data contexts.
+ * 
+ * @author Kasper Sørensen
+ */
+final class JdbcColumn extends MutableColumn {
+
+	private static final long serialVersionUID = 389872697452157919L;
+
+	public JdbcColumn(String columnName, ColumnType columnType, JdbcTable table, int columnNumber, Boolean nullable) {
+		super(columnName, columnType, table, columnNumber, nullable);
+	}
+
+	@Override
+	public boolean isIndexed() {
+		Table table = getTable();
+		if (table instanceof JdbcTable) {
+			((JdbcTable) table).loadIndexes();
+		}
+		return super.isIndexed();
+	}
+
+	@Override
+	public boolean isPrimaryKey() {
+		Table table = getTable();
+		if (table instanceof JdbcTable) {
+			((JdbcTable) table).loadPrimaryKeys();
+		}
+		return super.isPrimaryKey();
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQuery.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQuery.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQuery.java
new file mode 100644
index 0000000..ddadf1f
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQuery.java
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.List;
+
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.query.CompiledQuery;
+import org.eobjects.metamodel.query.DefaultCompiledQuery;
+import org.eobjects.metamodel.query.Query;
+import org.eobjects.metamodel.query.SelectItem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of {@link CompiledQuery} for JDBC which uses a
+ * {@link PreparedStatement} behind the scenes.
+ */
+final class JdbcCompiledQuery extends DefaultCompiledQuery implements CompiledQuery {
+
+	private static final Logger logger = LoggerFactory.getLogger(JdbcCompiledQuery.class);
+
+	private final JdbcDataContext _dataContext;
+	private final Connection _connection;
+	private final String _sql;
+	private final Query _query;
+	private final GenericObjectPool<JdbcCompiledQueryLease> _pool;
+	private boolean _closed;
+
+	public JdbcCompiledQuery(JdbcDataContext dc, Query query) {
+		super(query);
+		_dataContext = dc;
+		_connection = dc.getConnection();
+		_query = query;
+		_sql = dc.getQueryRewriter().rewriteQuery(query);
+		_pool = new GenericObjectPool<JdbcCompiledQueryLease>(new JdbcCompiledQueryLeaseFactory(dc, _connection, _sql));
+		_closed = false;
+
+		logger.debug("Created compiled JDBC query: {}", _sql);
+	}
+
+	public JdbcCompiledQueryLease borrowLease() {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Borrowing lease. Leases (before): Active={}, Idle={}", getActiveLeases(), getIdleLeases());
+		}
+		try {
+			return _pool.borrowObject();
+		} catch (Exception e) {
+			throw handleError(e, "borrow lease");
+		}
+	}
+
+	public void returnLease(JdbcCompiledQueryLease lease) {
+		if (logger.isDebugEnabled()) {
+			logger.debug("Returning lease. Leases (before): Active={}, Idle={}", getActiveLeases(), getIdleLeases());
+		}
+		try {
+			_pool.returnObject(lease);
+		} catch (Exception e) {
+			throw handleError(e, "return lease");
+		}
+	}
+
+	private RuntimeException handleError(Exception e, String message) {
+		if (logger.isWarnEnabled()) {
+			logger.warn("Unexpected error occurred in compiled JDBC query: " + message, e);
+		}
+		
+		if (e instanceof SQLException) {
+			return JdbcUtils.wrapException((SQLException) e, message);
+		} else if (e instanceof RuntimeException) {
+			return (RuntimeException) e;
+		} else {
+			return new MetaModelException(message, e);
+		}
+	}
+
+	protected int getActiveLeases() {
+		return _pool.getNumActive();
+	}
+
+	protected int getIdleLeases() {
+		return _pool.getNumIdle();
+	}
+
+	protected Query getQuery() {
+		return _query;
+	}
+
+	@Override
+	public String toSql() {
+		return _sql;
+	}
+
+	@Override
+	public void close() {
+		logger.debug("Closing compiled JDBC query: {}", _sql);
+		try {
+			_pool.close();
+		} catch (Exception e) {
+			throw handleError(e, "close pool of leases");
+		} finally {
+			_dataContext.close(_connection, null, null);
+			_closed = true;
+		}
+	}
+
+	protected List<SelectItem> getSelectItems() {
+		return _query.getSelectClause().getItems();
+	}
+
+	@Override
+	protected void finalize() throws Throwable {
+		super.finalize();
+		if (!_closed) {
+			logger.warn("finalize() invoked, but DataSet is not closed. Invoking close() on {}", this);
+			close();
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLease.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLease.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLease.java
new file mode 100644
index 0000000..65bf7b5
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLease.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+/**
+ * Represents a "lease" of a JdbcCompiledQuery. A lease holds the
+ * {@link Connection} and {@link PreparedStatement} object associated with
+ * executing a compiled query. Since these are not thread-safe, but expensive to
+ * create, they are pooled to allow proper isolation when executing compiled
+ * queries.
+ */
+final class JdbcCompiledQueryLease {
+
+    private final Connection _connection;
+    private final PreparedStatement _statement;
+
+    public JdbcCompiledQueryLease(Connection connection, PreparedStatement statement) {
+        _connection = connection;
+        _statement = statement;
+    }
+    
+    public Connection getConnection() {
+        return _connection;
+    }
+    
+    public PreparedStatement getStatement() {
+        return _statement;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLeaseFactory.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLeaseFactory.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLeaseFactory.java
new file mode 100644
index 0000000..e3712ed
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCompiledQueryLeaseFactory.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import org.apache.commons.pool.PoolableObjectFactory;
+
+/**
+ * Factory for the object pool of {@link JdbcCompiledQueryLease}s.
+ */
+final class JdbcCompiledQueryLeaseFactory implements PoolableObjectFactory<JdbcCompiledQueryLease> {
+
+	private final JdbcDataContext _dataContext;
+    private final Connection _connection;
+    private final String _sql;
+
+    public JdbcCompiledQueryLeaseFactory(JdbcDataContext dataContext, Connection connection, String sql) {
+    	_dataContext = dataContext;
+        _connection = connection;
+        _sql = sql;
+    }
+    
+
+    @Override
+    public JdbcCompiledQueryLease makeObject() throws Exception {
+        try {
+            final PreparedStatement statement = _connection.prepareStatement(_sql);
+            final JdbcCompiledQueryLease lease = new JdbcCompiledQueryLease(_connection, statement);
+            return lease;
+        } catch (SQLException e) {
+            throw JdbcUtils.wrapException(e, "preparing statement");
+        }
+    }
+
+    @Override
+    public void destroyObject(JdbcCompiledQueryLease lease) throws Exception {
+        _dataContext.close(null, null, lease.getStatement());
+    }
+
+    @Override
+    public boolean validateObject(JdbcCompiledQueryLease lease) {
+        return true;
+    }
+
+    @Override
+    public void activateObject(JdbcCompiledQueryLease obj) throws Exception {
+    }
+
+    @Override
+    public void passivateObject(JdbcCompiledQueryLease obj) throws Exception {
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCreateTableBuilder.java
----------------------------------------------------------------------
diff --git a/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCreateTableBuilder.java b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCreateTableBuilder.java
new file mode 100644
index 0000000..a1afc6c
--- /dev/null
+++ b/jdbc/src/main/java/org/apache/metamodel/jdbc/JdbcCreateTableBuilder.java
@@ -0,0 +1,127 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.eobjects.metamodel.jdbc;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
+import org.eobjects.metamodel.jdbc.dialects.IQueryRewriter;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.util.FileHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link CreateTableBuilder} implementation that issues a SQL CREATE TABLE
+ * statement.
+ * 
+ * @author Kasper Sørensen
+ */
+final class JdbcCreateTableBuilder extends AbstractTableCreationBuilder<JdbcUpdateCallback> {
+
+	private static final Logger logger = LoggerFactory.getLogger(JdbcCreateTableBuilder.class);
+
+	public JdbcCreateTableBuilder(JdbcUpdateCallback updateCallback, Schema schema, String name) {
+		super(updateCallback, schema, name);
+		if (!(schema instanceof JdbcSchema)) {
+			throw new IllegalArgumentException("Not a valid JDBC schema: " + schema);
+		}
+	}
+
+	@Override
+	public Table execute() {
+		final String sql = createSqlStatement();
+		logger.info("Create table statement created: {}", sql);
+
+		Connection connection = getUpdateCallback().getConnection();
+		Statement st = null;
+		try {
+			st = connection.createStatement();
+			int rowsAffected = st.executeUpdate(sql);
+			logger.debug("Create table statement executed, {} rows affected", rowsAffected);
+		} catch (SQLException e) {
+			throw JdbcUtils.wrapException(e, "execute create table statement: " + sql);
+		} finally {
+			FileHelper.safeClose(st);
+		}
+
+		JdbcSchema schema = (JdbcSchema) getSchema();
+		schema.refreshTables();
+		return schema.getTableByName(getTable().getName());
+	}
+
+	protected String createSqlStatement() {
+		return createSqlStatement(getTable());
+	}
+
+	private String createSqlStatement(Table table) {
+		final IQueryRewriter queryRewriter = getUpdateCallback().getDataContext().getQueryRewriter();
+		final StringBuilder sb = new StringBuilder();
+		sb.append("CREATE TABLE ");
+		final Schema schema = getSchema();
+		if (schema != null && schema.getName() != null) {
+			sb.append(schema.getQualifiedLabel());
+			sb.append(".");
+		}
+		sb.append(getUpdateCallback().quoteIfNescesary(table.getName()));
+		sb.append(" (");
+		final Column[] columns = table.getColumns();
+		for (int i = 0; i < columns.length; i++) {
+			final Column column = columns[i];
+			if (i != 0) {
+				sb.append(", ");
+			}
+			sb.append(getUpdateCallback().quoteIfNescesary(column.getName()));
+			sb.append(' ');
+			final String nativeType = column.getNativeType();
+			if (nativeType == null) {
+				ColumnType columnType = column.getType();
+				if (columnType == null) {
+					columnType = ColumnType.VARCHAR;
+				}
+
+				final String columnTypeString = queryRewriter.rewriteColumnType(columnType);
+
+				sb.append(columnTypeString);
+			} else {
+				sb.append(nativeType);
+			}
+			final Integer columnSize = column.getColumnSize();
+			if (columnSize != null) {
+				sb.append('(');
+				sb.append(columnSize.intValue());
+				sb.append(')');
+			}
+			if (column.isNullable() != null && !column.isNullable().booleanValue()) {
+				sb.append(" NOT NULL");
+			}
+			if (column.isPrimaryKey()) {
+				sb.append(" PRIMARY KEY");
+			}
+		}
+		sb.append(")");
+		return sb.toString();
+	}
+
+}