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/19 11:33:01 UTC

[18/61] [partial] Hard rename of all 'org/eobjects' folders to 'org/apache'.

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataSet.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataSet.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataSet.java
new file mode 100644
index 0000000..6f3db01
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbDataSet.java
@@ -0,0 +1,123 @@
+/**
+ * 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.couchdb;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.ektorp.StreamingViewResult;
+import org.eobjects.metamodel.data.AbstractDataSet;
+import org.eobjects.metamodel.data.DefaultRow;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.query.SelectItem;
+
+/**
+ * DataSet implementation for couch db.
+ */
+final class CouchDbDataSet extends AbstractDataSet {
+
+    private final Iterator<org.ektorp.ViewResult.Row> _iterator;
+    private final StreamingViewResult _streamingViewResult;
+    private DefaultRow _row;
+
+    public CouchDbDataSet(SelectItem[] selectItems, StreamingViewResult streamingViewResult) {
+        super(selectItems);
+        _streamingViewResult = streamingViewResult;
+
+        _iterator = _streamingViewResult.iterator();
+    }
+
+    @Override
+    public boolean next() {
+        if (_iterator == null || !_iterator.hasNext()) {
+            return false;
+        }
+
+        final org.ektorp.ViewResult.Row row = _iterator.next();
+        final JsonNode node = row.getDocAsNode();
+        final int size = getHeader().size();
+        final Object[] values = new Object[size];
+        for (int i = 0; i < size; i++) {
+            final String key = getHeader().getSelectItem(i).getColumn().getName();
+            final JsonNode valueNode = node.get(key);
+            final Object value;
+            if (valueNode == null || valueNode.isNull()) {
+                value = null;
+            } else if (valueNode.isTextual()) {
+                value = valueNode.asText();
+            } else if (valueNode.isArray()) {
+                value = toList(valueNode);
+            } else if (valueNode.isObject()) {
+                value = toMap(valueNode);
+            } else if (valueNode.isBoolean()) {
+                value = valueNode.asBoolean();
+            } else if (valueNode.isInt()) {
+                value = valueNode.asInt();
+            } else if (valueNode.isLong()) {
+                value = valueNode.asLong();
+            } else if (valueNode.isDouble()) {
+                value = valueNode.asDouble();
+            } else {
+                value = valueNode;
+            }
+            values[i] = value;
+        }
+
+        _row = new DefaultRow(getHeader(), values);
+
+        return true;
+    }
+
+    private Map<String, Object> toMap(JsonNode valueNode) {
+        if (valueNode == null) {
+            return null;
+        }
+        try {
+            return new ObjectMapper().reader(Map.class).readValue(valueNode);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    private Object toList(JsonNode valueNode) {
+        if (valueNode == null) {
+            return null;
+        }
+        try {
+            return new ObjectMapper().reader(List.class).readValue(valueNode);
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public Row getRow() {
+        return _row;
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        _streamingViewResult.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbInsertionBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbInsertionBuilder.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbInsertionBuilder.java
new file mode 100644
index 0000000..7fe2ae6
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbInsertionBuilder.java
@@ -0,0 +1,54 @@
+/**
+ * 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.couchdb;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ektorp.CouchDbConnector;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.insert.AbstractRowInsertionBuilder;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+
+final class CouchDbInsertionBuilder extends AbstractRowInsertionBuilder<CouchDbUpdateCallback> {
+
+    public CouchDbInsertionBuilder(CouchDbUpdateCallback updateCallback, Table table) {
+        super(updateCallback, table);
+    }
+
+    @Override
+    public void execute() throws MetaModelException {
+        Table table = getTable();
+        String name = table.getName();
+
+        Object[] values = getValues();
+        Column[] columns = getColumns();
+        Map<String, Object> map = new HashMap<String, Object>();
+        for (int i = 0; i < columns.length; i++) {
+            Column column = columns[i];
+            if (isSet(column)) {
+                map.put(column.getName(), values[i]);
+            }
+        }
+
+        CouchDbConnector connector = getUpdateCallback().getConnector(name);
+        connector.addToBulkBuffer(map);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowDeletionBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowDeletionBuilder.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowDeletionBuilder.java
new file mode 100644
index 0000000..fe0fc66
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowDeletionBuilder.java
@@ -0,0 +1,62 @@
+/**
+ * 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.couchdb;
+
+import java.util.List;
+
+import org.ektorp.CouchDbConnector;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.delete.AbstractRowDeletionBuilder;
+import org.eobjects.metamodel.query.FilterItem;
+import org.eobjects.metamodel.schema.Table;
+
+final class CouchDbRowDeletionBuilder extends AbstractRowDeletionBuilder {
+
+    private final CouchDbUpdateCallback _updateCallback;
+
+    public CouchDbRowDeletionBuilder(CouchDbUpdateCallback updateCallback, Table table) {
+        super(table);
+        _updateCallback = updateCallback;
+    }
+
+    @Override
+    public void execute() throws MetaModelException {
+        Table table = getTable();
+        List<FilterItem> whereItems = getWhereItems();
+
+        CouchDbConnector connector = _updateCallback.getConnector(table.getName());
+        CouchDbDataContext dataContext = _updateCallback.getDataContext();
+
+        DataSet dataSet = dataContext.query().from(table)
+                .select(CouchDbDataContext.FIELD_ID, CouchDbDataContext.FIELD_REV).where(whereItems).execute();
+        try {
+            while (dataSet.next()) {
+                Row row = dataSet.getRow();
+                String id = (String) row.getValue(0);
+                String revision = (String) row.getValue(1);
+                connector.delete(id, revision);
+            }
+        } finally {
+            dataSet.close();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowUpdationBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowUpdationBuilder.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowUpdationBuilder.java
new file mode 100644
index 0000000..15a4298
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbRowUpdationBuilder.java
@@ -0,0 +1,79 @@
+/**
+ * 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.couchdb;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ektorp.CouchDbConnector;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.schema.Column;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.update.AbstractRowUpdationBuilder;
+
+final class CouchDbRowUpdationBuilder extends AbstractRowUpdationBuilder {
+
+	private final CouchDbUpdateCallback _updateCallback;
+
+	public CouchDbRowUpdationBuilder(CouchDbUpdateCallback updateCallback, Table table) {
+		super(table);
+		_updateCallback = updateCallback;
+	}
+
+	@Override
+	public void execute() throws MetaModelException {
+		final Table table = getTable();
+		final CouchDbConnector connector = _updateCallback.getConnector(table.getName());
+
+		// create a map which will act as a prototype for updated objects
+		final Map<String, Object> prototype = new HashMap<String, Object>();
+		final Column[] columns = getColumns();
+		final Object[] values = getValues();
+		for (int i = 0; i < columns.length; i++) {
+			final Column column = columns[i];
+			if (isSet(column)) {
+				final String columnName = column.getName();
+				final Object value = values[i];
+				prototype.put(columnName, value);
+			}
+		}
+
+		final CouchDbDataContext dc = _updateCallback.getDataContext();
+		final DataSet dataSet = dc.query().from(table).select(table.getColumns()).where(getWhereItems()).execute();
+		try {
+			while (dataSet.next()) {
+				final Map<String, Object> map = new HashMap<String, Object>(prototype);
+				final Row row = dataSet.getRow();
+				for (Column column : table.getColumns()) {
+					if (!map.containsKey(column.getName())) {
+						map.put(column.getName(), row.getValue(column));
+					}
+				}
+
+				// copy the prototype and set the not-updated values
+				connector.update(map);
+			}
+		} finally {
+			dataSet.close();
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableCreationBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableCreationBuilder.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableCreationBuilder.java
new file mode 100644
index 0000000..df00880
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableCreationBuilder.java
@@ -0,0 +1,75 @@
+/**
+ * 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.couchdb;
+
+import org.ektorp.CouchDbInstance;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
+import org.eobjects.metamodel.schema.ColumnType;
+import org.eobjects.metamodel.schema.MutableColumn;
+import org.eobjects.metamodel.schema.MutableSchema;
+import org.eobjects.metamodel.schema.MutableTable;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+
+final class CouchDbTableCreationBuilder extends AbstractTableCreationBuilder<CouchDbUpdateCallback> {
+
+    public CouchDbTableCreationBuilder(CouchDbUpdateCallback updateCallback, Schema schema, String name) {
+        super(updateCallback, schema, name);
+    }
+
+    @Override
+    public Table execute() throws MetaModelException {
+        MutableTable table = getTable();
+
+        String name = table.getName();
+
+        CouchDbInstance instance = getUpdateCallback().getDataContext().getCouchDbInstance();
+        instance.createDatabase(name);
+
+        addMandatoryColumns(table);
+
+        MutableSchema schema = (MutableSchema) table.getSchema();
+        schema.addTable(table);
+
+        return table;
+    }
+
+    /**
+     * Verifies, and adds if nescesary, the two mandatory columns: _id and _rev.
+     * 
+     * @param table
+     */
+    public static void addMandatoryColumns(MutableTable table) {
+        // add or correct ID column
+        {
+            MutableColumn idColumn = (MutableColumn) table.getColumnByName(CouchDbDataContext.FIELD_ID);
+            if (idColumn == null) {
+                idColumn = new MutableColumn(CouchDbDataContext.FIELD_ID, ColumnType.VARCHAR, table, 0, false);
+                table.addColumn(0, idColumn);
+            }
+            idColumn.setPrimaryKey(true);
+        }
+
+        if (table.getColumnByName(CouchDbDataContext.FIELD_REV) == null) {
+            table.addColumn(1, new MutableColumn(CouchDbDataContext.FIELD_REV, ColumnType.VARCHAR, table, 1, false));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableDropBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableDropBuilder.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableDropBuilder.java
new file mode 100644
index 0000000..91297aa
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbTableDropBuilder.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.couchdb;
+
+import org.ektorp.CouchDbInstance;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.drop.AbstractTableDropBuilder;
+import org.eobjects.metamodel.schema.MutableSchema;
+import org.eobjects.metamodel.schema.Table;
+
+final class CouchDbTableDropBuilder extends AbstractTableDropBuilder {
+
+	private final CouchDbUpdateCallback _updateCallback;
+
+	public CouchDbTableDropBuilder(CouchDbUpdateCallback updateCallback, Table table) {
+		super(table);
+		_updateCallback = updateCallback;
+	}
+
+	@Override
+	public void execute() throws MetaModelException {
+		CouchDbInstance instance = _updateCallback.getDataContext().getCouchDbInstance();
+		Table table = getTable();
+		MutableSchema schema = (MutableSchema) table.getSchema();
+		schema.removeTable(table);
+		
+		instance.deleteDatabase(table.getName());
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbUpdateCallback.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbUpdateCallback.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbUpdateCallback.java
new file mode 100644
index 0000000..8207c0d
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/CouchDbUpdateCallback.java
@@ -0,0 +1,143 @@
+/**
+ * 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.couchdb;
+
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.ektorp.CouchDbConnector;
+import org.ektorp.CouchDbInstance;
+import org.ektorp.DocumentOperationResult;
+import org.eobjects.metamodel.AbstractUpdateCallback;
+import org.eobjects.metamodel.MetaModelException;
+import org.eobjects.metamodel.create.TableCreationBuilder;
+import org.eobjects.metamodel.delete.RowDeletionBuilder;
+import org.eobjects.metamodel.drop.TableDropBuilder;
+import org.eobjects.metamodel.insert.RowInsertionBuilder;
+import org.eobjects.metamodel.schema.Schema;
+import org.eobjects.metamodel.schema.Table;
+import org.eobjects.metamodel.update.RowUpdationBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class CouchDbUpdateCallback extends AbstractUpdateCallback implements Closeable {
+
+	private static final Logger logger = LoggerFactory.getLogger(CouchDbUpdateCallback.class);
+	private final Map<String, CouchDbConnector> _connectors;
+
+	public CouchDbUpdateCallback(CouchDbDataContext couchDbDataContext) {
+		super(couchDbDataContext);
+		_connectors = new HashMap<String, CouchDbConnector>();
+	}
+
+	@Override
+	public CouchDbDataContext getDataContext() {
+		return (CouchDbDataContext) super.getDataContext();
+	}
+
+	@Override
+	public boolean isUpdateSupported() {
+		return true;
+	}
+
+	@Override
+	public RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException,
+			UnsupportedOperationException {
+		return new CouchDbRowUpdationBuilder(this, table);
+	}
+
+	@Override
+	public boolean isCreateTableSupported() {
+		return true;
+	}
+
+	@Override
+	public TableCreationBuilder createTable(Schema schema, String name) throws IllegalArgumentException,
+			IllegalStateException {
+		return new CouchDbTableCreationBuilder(this, schema, name);
+	}
+
+	@Override
+	public boolean isDropTableSupported() {
+		return true;
+	}
+
+	@Override
+	public TableDropBuilder dropTable(Table table) throws IllegalArgumentException, IllegalStateException,
+			UnsupportedOperationException {
+		return new CouchDbTableDropBuilder(this, table);
+	}
+
+	@Override
+	public RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException,
+			UnsupportedOperationException {
+		return new CouchDbInsertionBuilder(this, table);
+	}
+
+	@Override
+	public boolean isDeleteSupported() {
+		return true;
+	}
+
+	@Override
+	public RowDeletionBuilder deleteFrom(Table table) throws IllegalArgumentException, IllegalStateException,
+			UnsupportedOperationException {
+		return new CouchDbRowDeletionBuilder(this, table);
+	}
+
+	@Override
+	public void close() {
+		Collection<CouchDbConnector> connectorSet = _connectors.values();
+		for (CouchDbConnector connector : connectorSet) {
+			List<String> errornousResultsDescriptions = new ArrayList<String>();
+			List<DocumentOperationResult> results = connector.flushBulkBuffer();
+			for (DocumentOperationResult result : results) {
+				if (result.isErroneous()) {
+					String id = result.getId();
+					String error = result.getError();
+					String reason = result.getReason();
+					String revision = result.getRevision();
+					logger.error("Error occurred while flushing bulk buffer: {}, id: {}, revision: {}, reason: {}",
+							new Object[] { error, id, revision, reason });
+					errornousResultsDescriptions.add(error);
+				}
+			}
+
+			if (!errornousResultsDescriptions.isEmpty()) {
+				throw new MetaModelException(errornousResultsDescriptions.size() + " out of " + results.size()
+						+ " operations in bulk was errornous: " + errornousResultsDescriptions);
+			}
+		}
+	}
+
+	public CouchDbConnector getConnector(String name) {
+		CouchDbConnector connector = _connectors.get(name);
+		if (connector == null) {
+			CouchDbInstance instance = getDataContext().getCouchDbInstance();
+			connector = instance.createConnector(name, false);
+			_connectors.put(name, connector);
+		}
+		return connector;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/apache/metamodel/couchdb/package-info.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/apache/metamodel/couchdb/package-info.java b/couchdb/src/main/java/org/apache/metamodel/couchdb/package-info.java
new file mode 100644
index 0000000..340fd98
--- /dev/null
+++ b/couchdb/src/main/java/org/apache/metamodel/couchdb/package-info.java
@@ -0,0 +1,23 @@
+/**
+ * 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.
+ */
+/**
+ * Module package for CouchDB support
+ */
+package org.eobjects.metamodel.couchdb;
+

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataContext.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataContext.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataContext.java
deleted file mode 100644
index ac626e6..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataContext.java
+++ /dev/null
@@ -1,254 +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.couchdb;
-
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.codehaus.jackson.JsonNode;
-import org.ektorp.CouchDbConnector;
-import org.ektorp.CouchDbInstance;
-import org.ektorp.StreamingViewResult;
-import org.ektorp.ViewQuery;
-import org.ektorp.ViewResult.Row;
-import org.ektorp.http.HttpClient;
-import org.ektorp.http.StdHttpClient;
-import org.ektorp.impl.StdCouchDbInstance;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.MetaModelHelper;
-import org.eobjects.metamodel.QueryPostprocessDataContext;
-import org.eobjects.metamodel.UpdateScript;
-import org.eobjects.metamodel.UpdateableDataContext;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.query.FilterItem;
-import org.eobjects.metamodel.query.SelectItem;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.ColumnType;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.MutableTable;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.util.SimpleTableDef;
-
-/**
- * DataContext implementation for CouchDB
- */
-public class CouchDbDataContext extends QueryPostprocessDataContext implements UpdateableDataContext {
-
-    public static final int DEFAULT_PORT = 5984;
-
-    public static final String FIELD_ID = "_id";
-    public static final String FIELD_REV = "_rev";
-
-    private static final String SCHEMA_NAME = "CouchDB";
-
-    private final CouchDbInstance _couchDbInstance;
-    private final SimpleTableDef[] _tableDefs;
-
-    public CouchDbDataContext(StdHttpClient.Builder httpClientBuilder, SimpleTableDef... tableDefs) {
-        this(httpClientBuilder.build(), tableDefs);
-    }
-
-    public CouchDbDataContext(StdHttpClient.Builder httpClientBuilder) {
-        this(httpClientBuilder.build());
-    }
-
-    public CouchDbDataContext(HttpClient httpClient, SimpleTableDef... tableDefs) {
-        this(new StdCouchDbInstance(httpClient), tableDefs);
-    }
-
-    public CouchDbDataContext(HttpClient httpClient) {
-        this(new StdCouchDbInstance(httpClient));
-    }
-
-    public CouchDbDataContext(CouchDbInstance couchDbInstance) {
-        this(couchDbInstance, detectSchema(couchDbInstance));
-    }
-
-    public CouchDbDataContext(CouchDbInstance couchDbInstance, SimpleTableDef... tableDefs) {
-        // the instance represents a handle to the whole couchdb cluster
-        _couchDbInstance = couchDbInstance;
-        _tableDefs = tableDefs;
-    }
-
-    public static SimpleTableDef[] detectSchema(CouchDbInstance couchDbInstance) {
-        final List<SimpleTableDef> tableDefs = new ArrayList<SimpleTableDef>();
-        final List<String> databaseNames = couchDbInstance.getAllDatabases();
-        for (final String databaseName : databaseNames) {
-
-            if (databaseName.startsWith("_")) {
-                // don't add system tables
-                continue;
-            }
-
-            CouchDbConnector connector = couchDbInstance.createConnector(databaseName, false);
-
-            SimpleTableDef tableDef = detectTable(connector);
-            tableDefs.add(tableDef);
-        }
-        return tableDefs.toArray(new SimpleTableDef[tableDefs.size()]);
-    }
-
-    public static SimpleTableDef detectTable(CouchDbConnector connector) {
-        final SortedMap<String, Set<ColumnType>> columnsAndTypes = new TreeMap<String, Set<ColumnType>>();
-
-        final StreamingViewResult streamingView = connector.queryForStreamingView(new ViewQuery().allDocs().includeDocs(true)
-                .limit(1000));
-        try {
-            final Iterator<Row> rowIterator = streamingView.iterator();
-            while (rowIterator.hasNext()) {
-                Row row = rowIterator.next();
-                JsonNode doc = row.getDocAsNode();
-
-                final Iterator<Entry<String, JsonNode>> fieldIterator = doc.getFields();
-                while (fieldIterator.hasNext()) {
-                    Entry<String, JsonNode> entry = fieldIterator.next();
-                    String key = entry.getKey();
-
-                    Set<ColumnType> types = columnsAndTypes.get(key);
-
-                    if (types == null) {
-                        types = EnumSet.noneOf(ColumnType.class);
-                        columnsAndTypes.put(key, types);
-                    }
-
-                    JsonNode value = entry.getValue();
-                    if (value == null || value.isNull()) {
-                        // do nothing
-                    } else if (value.isTextual()) {
-                        types.add(ColumnType.VARCHAR);
-                    } else if (value.isArray()) {
-                        types.add(ColumnType.LIST);
-                    } else if (value.isObject()) {
-                        types.add(ColumnType.MAP);
-                    } else if (value.isBoolean()) {
-                        types.add(ColumnType.BOOLEAN);
-                    } else if (value.isInt()) {
-                        types.add(ColumnType.INTEGER);
-                    } else if (value.isLong()) {
-                        types.add(ColumnType.BIGINT);
-                    } else if (value.isDouble()) {
-                        types.add(ColumnType.DOUBLE);
-                    }
-                }
-
-            }
-        } finally {
-            streamingView.close();
-        }
-
-        final String[] columnNames = new String[columnsAndTypes.size()];
-        final ColumnType[] columnTypes = new ColumnType[columnsAndTypes.size()];
-
-        int i = 0;
-        for (Entry<String, Set<ColumnType>> columnAndTypes : columnsAndTypes.entrySet()) {
-            final String columnName = columnAndTypes.getKey();
-            final Set<ColumnType> columnTypeSet = columnAndTypes.getValue();
-            final ColumnType columnType;
-            if (columnTypeSet.isEmpty()) {
-                columnType = ColumnType.OTHER;
-            } else if (columnTypeSet.size() == 1) {
-                columnType = columnTypeSet.iterator().next();
-            } else {
-                // TODO: Select best type?
-                columnType = ColumnType.OTHER;
-            }
-            columnNames[i] = columnName;
-            columnTypes[i] = columnType;
-            i++;
-        }
-
-        final SimpleTableDef tableDef = new SimpleTableDef(connector.getDatabaseName(), columnNames, columnTypes);
-        return tableDef;
-    }
-
-    public CouchDbInstance getCouchDbInstance() {
-        return _couchDbInstance;
-    }
-
-    @Override
-    protected Schema getMainSchema() throws MetaModelException {
-        final MutableSchema schema = new MutableSchema(SCHEMA_NAME);
-        for (final SimpleTableDef tableDef : _tableDefs) {
-            final MutableTable table = tableDef.toTable().setSchema(schema);
-            CouchDbTableCreationBuilder.addMandatoryColumns(table);
-            schema.addTable(table);
-        }
-        return schema;
-    }
-
-    @Override
-    protected String getMainSchemaName() throws MetaModelException {
-        return SCHEMA_NAME;
-    }
-
-    @Override
-    protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int firstRow, int maxRows) {
-        // the connector represents a handle to the the couchdb "database".
-        final String databaseName = table.getName();
-        final CouchDbConnector connector = _couchDbInstance.createConnector(databaseName, false);
-
-        ViewQuery query = new ViewQuery().allDocs().includeDocs(true);
-
-        if (maxRows > 0) {
-            query = query.limit(maxRows);
-        }
-        if (firstRow > 1) {
-            final int skip = firstRow - 1;
-            query = query.skip(skip);
-        }
-
-        final StreamingViewResult streamingView = connector.queryForStreamingView(query);
-
-        final SelectItem[] selectItems = MetaModelHelper.createSelectItems(columns);
-        return new CouchDbDataSet(selectItems, streamingView);
-    }
-
-    @Override
-    protected DataSet materializeMainSchemaTable(Table table, Column[] columns, int maxRows) {
-        return materializeMainSchemaTable(table, columns, 1, maxRows);
-    }
-
-    @Override
-    protected Number executeCountQuery(Table table, List<FilterItem> whereItems, boolean functionApproximationAllowed) {
-        if (whereItems.isEmpty()) {
-            String databaseName = table.getName();
-            CouchDbConnector connector = _couchDbInstance.createConnector(databaseName, false);
-            long docCount = connector.getDbInfo().getDocCount();
-            return docCount;
-        }
-        return null;
-    }
-
-    @Override
-    public void executeUpdate(UpdateScript script) {
-        CouchDbUpdateCallback callback = new CouchDbUpdateCallback(this);
-        try {
-            script.run(callback);
-        } finally {
-            callback.close();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataSet.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataSet.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataSet.java
deleted file mode 100644
index 6f3db01..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbDataSet.java
+++ /dev/null
@@ -1,123 +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.couchdb;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.ektorp.StreamingViewResult;
-import org.eobjects.metamodel.data.AbstractDataSet;
-import org.eobjects.metamodel.data.DefaultRow;
-import org.eobjects.metamodel.data.Row;
-import org.eobjects.metamodel.query.SelectItem;
-
-/**
- * DataSet implementation for couch db.
- */
-final class CouchDbDataSet extends AbstractDataSet {
-
-    private final Iterator<org.ektorp.ViewResult.Row> _iterator;
-    private final StreamingViewResult _streamingViewResult;
-    private DefaultRow _row;
-
-    public CouchDbDataSet(SelectItem[] selectItems, StreamingViewResult streamingViewResult) {
-        super(selectItems);
-        _streamingViewResult = streamingViewResult;
-
-        _iterator = _streamingViewResult.iterator();
-    }
-
-    @Override
-    public boolean next() {
-        if (_iterator == null || !_iterator.hasNext()) {
-            return false;
-        }
-
-        final org.ektorp.ViewResult.Row row = _iterator.next();
-        final JsonNode node = row.getDocAsNode();
-        final int size = getHeader().size();
-        final Object[] values = new Object[size];
-        for (int i = 0; i < size; i++) {
-            final String key = getHeader().getSelectItem(i).getColumn().getName();
-            final JsonNode valueNode = node.get(key);
-            final Object value;
-            if (valueNode == null || valueNode.isNull()) {
-                value = null;
-            } else if (valueNode.isTextual()) {
-                value = valueNode.asText();
-            } else if (valueNode.isArray()) {
-                value = toList(valueNode);
-            } else if (valueNode.isObject()) {
-                value = toMap(valueNode);
-            } else if (valueNode.isBoolean()) {
-                value = valueNode.asBoolean();
-            } else if (valueNode.isInt()) {
-                value = valueNode.asInt();
-            } else if (valueNode.isLong()) {
-                value = valueNode.asLong();
-            } else if (valueNode.isDouble()) {
-                value = valueNode.asDouble();
-            } else {
-                value = valueNode;
-            }
-            values[i] = value;
-        }
-
-        _row = new DefaultRow(getHeader(), values);
-
-        return true;
-    }
-
-    private Map<String, Object> toMap(JsonNode valueNode) {
-        if (valueNode == null) {
-            return null;
-        }
-        try {
-            return new ObjectMapper().reader(Map.class).readValue(valueNode);
-        } catch (Exception e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    private Object toList(JsonNode valueNode) {
-        if (valueNode == null) {
-            return null;
-        }
-        try {
-            return new ObjectMapper().reader(List.class).readValue(valueNode);
-        } catch (Exception e) {
-            throw new IllegalStateException(e);
-        }
-    }
-
-    @Override
-    public Row getRow() {
-        return _row;
-    }
-
-    @Override
-    public void close() {
-        super.close();
-        _streamingViewResult.close();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbInsertionBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbInsertionBuilder.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbInsertionBuilder.java
deleted file mode 100644
index 7b5f298..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbInsertionBuilder.java
+++ /dev/null
@@ -1,54 +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.couchdb;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.ektorp.CouchDbConnector;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.insert.AbstractRowInsertionBuilder;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.Table;
-
-final class CouchDbInsertionBuilder extends AbstractRowInsertionBuilder<CouchDbUpdateCallback> {
-
-    public CouchDbInsertionBuilder(CouchDbUpdateCallback updateCallback, Table table) {
-        super(updateCallback, table);
-    }
-
-    @Override
-    public void execute() throws MetaModelException {
-        Table table = getTable();
-        String name = table.getName();
-
-        Object[] values = getValues();
-        Column[] columns = getColumns();
-        Map<String, Object> map = new HashMap<String, Object>();
-        for (int i = 0; i < columns.length; i++) {
-            Column column = columns[i];
-            if (isSet(column)) {
-                map.put(column.getName(), values[i]);
-            }
-        }
-
-        CouchDbConnector connector = getUpdateCallback().getConnector(name);
-        connector.addToBulkBuffer(map);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowDeletionBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowDeletionBuilder.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowDeletionBuilder.java
deleted file mode 100644
index fe0fc66..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowDeletionBuilder.java
+++ /dev/null
@@ -1,62 +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.couchdb;
-
-import java.util.List;
-
-import org.ektorp.CouchDbConnector;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.data.Row;
-import org.eobjects.metamodel.delete.AbstractRowDeletionBuilder;
-import org.eobjects.metamodel.query.FilterItem;
-import org.eobjects.metamodel.schema.Table;
-
-final class CouchDbRowDeletionBuilder extends AbstractRowDeletionBuilder {
-
-    private final CouchDbUpdateCallback _updateCallback;
-
-    public CouchDbRowDeletionBuilder(CouchDbUpdateCallback updateCallback, Table table) {
-        super(table);
-        _updateCallback = updateCallback;
-    }
-
-    @Override
-    public void execute() throws MetaModelException {
-        Table table = getTable();
-        List<FilterItem> whereItems = getWhereItems();
-
-        CouchDbConnector connector = _updateCallback.getConnector(table.getName());
-        CouchDbDataContext dataContext = _updateCallback.getDataContext();
-
-        DataSet dataSet = dataContext.query().from(table)
-                .select(CouchDbDataContext.FIELD_ID, CouchDbDataContext.FIELD_REV).where(whereItems).execute();
-        try {
-            while (dataSet.next()) {
-                Row row = dataSet.getRow();
-                String id = (String) row.getValue(0);
-                String revision = (String) row.getValue(1);
-                connector.delete(id, revision);
-            }
-        } finally {
-            dataSet.close();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowUpdationBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowUpdationBuilder.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowUpdationBuilder.java
deleted file mode 100644
index 15a4298..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbRowUpdationBuilder.java
+++ /dev/null
@@ -1,79 +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.couchdb;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.ektorp.CouchDbConnector;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.data.DataSet;
-import org.eobjects.metamodel.data.Row;
-import org.eobjects.metamodel.schema.Column;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.update.AbstractRowUpdationBuilder;
-
-final class CouchDbRowUpdationBuilder extends AbstractRowUpdationBuilder {
-
-	private final CouchDbUpdateCallback _updateCallback;
-
-	public CouchDbRowUpdationBuilder(CouchDbUpdateCallback updateCallback, Table table) {
-		super(table);
-		_updateCallback = updateCallback;
-	}
-
-	@Override
-	public void execute() throws MetaModelException {
-		final Table table = getTable();
-		final CouchDbConnector connector = _updateCallback.getConnector(table.getName());
-
-		// create a map which will act as a prototype for updated objects
-		final Map<String, Object> prototype = new HashMap<String, Object>();
-		final Column[] columns = getColumns();
-		final Object[] values = getValues();
-		for (int i = 0; i < columns.length; i++) {
-			final Column column = columns[i];
-			if (isSet(column)) {
-				final String columnName = column.getName();
-				final Object value = values[i];
-				prototype.put(columnName, value);
-			}
-		}
-
-		final CouchDbDataContext dc = _updateCallback.getDataContext();
-		final DataSet dataSet = dc.query().from(table).select(table.getColumns()).where(getWhereItems()).execute();
-		try {
-			while (dataSet.next()) {
-				final Map<String, Object> map = new HashMap<String, Object>(prototype);
-				final Row row = dataSet.getRow();
-				for (Column column : table.getColumns()) {
-					if (!map.containsKey(column.getName())) {
-						map.put(column.getName(), row.getValue(column));
-					}
-				}
-
-				// copy the prototype and set the not-updated values
-				connector.update(map);
-			}
-		} finally {
-			dataSet.close();
-		}
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableCreationBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableCreationBuilder.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableCreationBuilder.java
deleted file mode 100644
index df00880..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableCreationBuilder.java
+++ /dev/null
@@ -1,75 +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.couchdb;
-
-import org.ektorp.CouchDbInstance;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.create.AbstractTableCreationBuilder;
-import org.eobjects.metamodel.schema.ColumnType;
-import org.eobjects.metamodel.schema.MutableColumn;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.MutableTable;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-
-final class CouchDbTableCreationBuilder extends AbstractTableCreationBuilder<CouchDbUpdateCallback> {
-
-    public CouchDbTableCreationBuilder(CouchDbUpdateCallback updateCallback, Schema schema, String name) {
-        super(updateCallback, schema, name);
-    }
-
-    @Override
-    public Table execute() throws MetaModelException {
-        MutableTable table = getTable();
-
-        String name = table.getName();
-
-        CouchDbInstance instance = getUpdateCallback().getDataContext().getCouchDbInstance();
-        instance.createDatabase(name);
-
-        addMandatoryColumns(table);
-
-        MutableSchema schema = (MutableSchema) table.getSchema();
-        schema.addTable(table);
-
-        return table;
-    }
-
-    /**
-     * Verifies, and adds if nescesary, the two mandatory columns: _id and _rev.
-     * 
-     * @param table
-     */
-    public static void addMandatoryColumns(MutableTable table) {
-        // add or correct ID column
-        {
-            MutableColumn idColumn = (MutableColumn) table.getColumnByName(CouchDbDataContext.FIELD_ID);
-            if (idColumn == null) {
-                idColumn = new MutableColumn(CouchDbDataContext.FIELD_ID, ColumnType.VARCHAR, table, 0, false);
-                table.addColumn(0, idColumn);
-            }
-            idColumn.setPrimaryKey(true);
-        }
-
-        if (table.getColumnByName(CouchDbDataContext.FIELD_REV) == null) {
-            table.addColumn(1, new MutableColumn(CouchDbDataContext.FIELD_REV, ColumnType.VARCHAR, table, 1, false));
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableDropBuilder.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableDropBuilder.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableDropBuilder.java
deleted file mode 100644
index 91297aa..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbTableDropBuilder.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.couchdb;
-
-import org.ektorp.CouchDbInstance;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.drop.AbstractTableDropBuilder;
-import org.eobjects.metamodel.schema.MutableSchema;
-import org.eobjects.metamodel.schema.Table;
-
-final class CouchDbTableDropBuilder extends AbstractTableDropBuilder {
-
-	private final CouchDbUpdateCallback _updateCallback;
-
-	public CouchDbTableDropBuilder(CouchDbUpdateCallback updateCallback, Table table) {
-		super(table);
-		_updateCallback = updateCallback;
-	}
-
-	@Override
-	public void execute() throws MetaModelException {
-		CouchDbInstance instance = _updateCallback.getDataContext().getCouchDbInstance();
-		Table table = getTable();
-		MutableSchema schema = (MutableSchema) table.getSchema();
-		schema.removeTable(table);
-		
-		instance.deleteDatabase(table.getName());
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbUpdateCallback.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbUpdateCallback.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbUpdateCallback.java
deleted file mode 100644
index e96b7bc..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/CouchDbUpdateCallback.java
+++ /dev/null
@@ -1,143 +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.couchdb;
-
-import java.io.Closeable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.ektorp.CouchDbConnector;
-import org.ektorp.CouchDbInstance;
-import org.ektorp.DocumentOperationResult;
-import org.eobjects.metamodel.AbstractUpdateCallback;
-import org.eobjects.metamodel.MetaModelException;
-import org.eobjects.metamodel.create.TableCreationBuilder;
-import org.eobjects.metamodel.delete.RowDeletionBuilder;
-import org.eobjects.metamodel.drop.TableDropBuilder;
-import org.eobjects.metamodel.insert.RowInsertionBuilder;
-import org.eobjects.metamodel.schema.Schema;
-import org.eobjects.metamodel.schema.Table;
-import org.eobjects.metamodel.update.RowUpdationBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-final class CouchDbUpdateCallback extends AbstractUpdateCallback implements Closeable {
-
-	private static final Logger logger = LoggerFactory.getLogger(CouchDbUpdateCallback.class);
-	private final Map<String, CouchDbConnector> _connectors;
-
-	public CouchDbUpdateCallback(CouchDbDataContext couchDbDataContext) {
-		super(couchDbDataContext);
-		_connectors = new HashMap<String, CouchDbConnector>();
-	}
-
-	@Override
-	public CouchDbDataContext getDataContext() {
-		return (CouchDbDataContext) super.getDataContext();
-	}
-
-	@Override
-	public boolean isUpdateSupported() {
-		return true;
-	}
-
-	@Override
-	public RowUpdationBuilder update(Table table) throws IllegalArgumentException, IllegalStateException,
-			UnsupportedOperationException {
-		return new CouchDbRowUpdationBuilder(this, table);
-	}
-
-	@Override
-	public boolean isCreateTableSupported() {
-		return true;
-	}
-
-	@Override
-	public TableCreationBuilder createTable(Schema schema, String name) throws IllegalArgumentException,
-			IllegalStateException {
-		return new CouchDbTableCreationBuilder(this, schema, name);
-	}
-
-	@Override
-	public boolean isDropTableSupported() {
-		return true;
-	}
-
-	@Override
-	public TableDropBuilder dropTable(Table table) throws IllegalArgumentException, IllegalStateException,
-			UnsupportedOperationException {
-		return new CouchDbTableDropBuilder(this, table);
-	}
-
-	@Override
-	public RowInsertionBuilder insertInto(Table table) throws IllegalArgumentException, IllegalStateException,
-			UnsupportedOperationException {
-		return new CouchDbInsertionBuilder(this, table);
-	}
-
-	@Override
-	public boolean isDeleteSupported() {
-		return true;
-	}
-
-	@Override
-	public RowDeletionBuilder deleteFrom(Table table) throws IllegalArgumentException, IllegalStateException,
-			UnsupportedOperationException {
-		return new CouchDbRowDeletionBuilder(this, table);
-	}
-
-	@Override
-	public void close() {
-		Collection<CouchDbConnector> connectorSet = _connectors.values();
-		for (CouchDbConnector connector : connectorSet) {
-			List<String> errornousResultsDescriptions = new ArrayList<String>();
-			List<DocumentOperationResult> results = connector.flushBulkBuffer();
-			for (DocumentOperationResult result : results) {
-				if (result.isErroneous()) {
-					String id = result.getId();
-					String error = result.getError();
-					String reason = result.getReason();
-					String revision = result.getRevision();
-					logger.error("Error occurred while flushing bulk buffer: {}, id: {}, revision: {}, reason: {}",
-							new Object[] { error, id, revision, reason });
-					errornousResultsDescriptions.add(error);
-				}
-			}
-
-			if (!errornousResultsDescriptions.isEmpty()) {
-				throw new MetaModelException(errornousResultsDescriptions.size() + " out of " + results.size()
-						+ " operations in bulk was errornous: " + errornousResultsDescriptions);
-			}
-		}
-	}
-
-	public CouchDbConnector getConnector(String name) {
-		CouchDbConnector connector = _connectors.get(name);
-		if (connector == null) {
-			CouchDbInstance instance = getDataContext().getCouchDbInstance();
-			connector = instance.createConnector(name, false);
-			_connectors.put(name, connector);
-		}
-		return connector;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/package-info.java
----------------------------------------------------------------------
diff --git a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/package-info.java b/couchdb/src/main/java/org/eobjects/metamodel/couchdb/package-info.java
deleted file mode 100644
index 340fd98..0000000
--- a/couchdb/src/main/java/org/eobjects/metamodel/couchdb/package-info.java
+++ /dev/null
@@ -1,23 +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.
- */
-/**
- * Module package for CouchDB support
- */
-package org.eobjects.metamodel.couchdb;
-

http://git-wip-us.apache.org/repos/asf/incubator-metamodel/blob/e2e2b37a/couchdb/src/test/java/org/apache/metamodel/couchdb/CouchDbDataContextTest.java
----------------------------------------------------------------------
diff --git a/couchdb/src/test/java/org/apache/metamodel/couchdb/CouchDbDataContextTest.java b/couchdb/src/test/java/org/apache/metamodel/couchdb/CouchDbDataContextTest.java
new file mode 100644
index 0000000..403a64c
--- /dev/null
+++ b/couchdb/src/test/java/org/apache/metamodel/couchdb/CouchDbDataContextTest.java
@@ -0,0 +1,354 @@
+/**
+ * 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.couchdb;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+import org.ektorp.CouchDbConnector;
+import org.ektorp.DbAccessException;
+import org.ektorp.http.HttpClient;
+import org.ektorp.http.StdHttpClient;
+import org.ektorp.impl.StdCouchDbInstance;
+import org.eobjects.metamodel.UpdateCallback;
+import org.eobjects.metamodel.UpdateScript;
+import org.eobjects.metamodel.data.DataSet;
+import org.eobjects.metamodel.data.Row;
+import org.eobjects.metamodel.drop.DropTable;
+import org.eobjects.metamodel.insert.InsertInto;
+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.SimpleTableDef;
+
+public class CouchDbDataContextTest extends TestCase {
+
+    private static final String TEST_DATABASE_NAME = "eobjects_metamodel_test";
+
+    private boolean serverAvailable;
+
+    private HttpClient httpClient;
+    private StdCouchDbInstance couchDbInstance;
+    private CouchDbConnector connector;
+    private SimpleTableDef predefinedTableDef;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        httpClient = new StdHttpClient.Builder().host("localhost").build();
+
+        // set up a simple database
+        couchDbInstance = new StdCouchDbInstance(httpClient);
+
+        try {
+            if (couchDbInstance.getAllDatabases().contains(TEST_DATABASE_NAME)) {
+                throw new IllegalStateException("Couch DB instance already has a database called " + TEST_DATABASE_NAME);
+            }
+            connector = couchDbInstance.createConnector(TEST_DATABASE_NAME, true);
+            System.out.println("Running CouchDB integration tests");
+            serverAvailable = true;
+        } catch (DbAccessException e) {
+            System.out.println("!!! WARNING: Skipping CouchDB tests because local server is not available");
+            e.printStackTrace();
+            serverAvailable = false;
+        }
+
+        final String[] columnNames = new String[] { "name", "gender", "age" };
+        final ColumnType[] columnTypes = new ColumnType[] { ColumnType.VARCHAR, ColumnType.CHAR, ColumnType.INTEGER };
+        predefinedTableDef = new SimpleTableDef(TEST_DATABASE_NAME, columnNames, columnTypes);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+
+        connector = null;
+
+        if (serverAvailable) {
+            couchDbInstance.deleteDatabase(TEST_DATABASE_NAME);
+        }
+
+        httpClient.shutdown();
+    }
+
+    public void testWorkingWithMapsAndLists() throws Exception {
+        if (!serverAvailable) {
+            return;
+        }
+
+        connector = couchDbInstance.createConnector("test_table_map_and_list", true);
+
+        final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, new SimpleTableDef("test_table_map_and_list",
+                new String[] { "id", "foo", "bar" }, new ColumnType[] { ColumnType.INTEGER, ColumnType.MAP, ColumnType.LIST }));
+        Table table = null;
+        try {
+            table = dc.getTableByQualifiedLabel("test_table_map_and_list");
+            Map<String, Object> exampleMap = new LinkedHashMap<String, Object>();
+            exampleMap.put("hello", Arrays.asList("world", "welt", "verden"));
+            exampleMap.put("foo", "bar");
+
+            List<Map<String, Object>> exampleList = new ArrayList<Map<String, Object>>();
+            exampleList.add(new LinkedHashMap<String, Object>());
+            Map<String, Object> exampleMap2 = new LinkedHashMap<String, Object>();
+            exampleMap2.put("meta", "model");
+            exampleMap2.put("couch", "db");
+            exampleList.add(exampleMap2);
+
+            dc.executeUpdate(new InsertInto(table).value("id", 1).value("foo", exampleMap).value("bar", exampleList));
+
+            DataSet ds = dc.query().from(table).select("id","foo","bar").execute();
+            assertTrue(ds.next());
+            Row row = ds.getRow();
+            assertFalse(ds.next());
+            ds.close();
+
+            assertEquals(
+                    "Row[values=[1, {hello=[world, welt, verden], foo=bar}, [{}, {meta=model, couch=db}]]]",
+                    row.toString());
+            assertTrue(row.getValue(0) instanceof Integer);
+            assertTrue(row.getValue(1) instanceof Map);
+            assertTrue(row.getValue(2) instanceof List);
+
+        } finally {
+            dc.executeUpdate(new DropTable(table));
+        }
+
+    }
+
+    public void testCreateUpdateDeleteScenario() throws Exception {
+        if (!serverAvailable) {
+            return;
+        }
+
+        final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance);
+
+        // first delete the manually created database!
+        dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback callback) {
+                callback.dropTable(TEST_DATABASE_NAME).execute();
+            }
+        });
+
+        assertNull(dc.getDefaultSchema().getTableByName(TEST_DATABASE_NAME));
+
+        dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback callback) {
+                Table table = callback.createTable(dc.getDefaultSchema(), TEST_DATABASE_NAME).withColumn("foo")
+                        .ofType(ColumnType.VARCHAR).withColumn("greeting").ofType(ColumnType.VARCHAR).execute();
+                assertEquals("[_id, _rev, foo, greeting]", Arrays.toString(table.getColumnNames()));
+            }
+        });
+
+        dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback callback) {
+                callback.insertInto(TEST_DATABASE_NAME).value("foo", "bar").value("greeting", "hello").execute();
+                callback.insertInto(TEST_DATABASE_NAME).value("foo", "baz").value("greeting", "hi").execute();
+            }
+        });
+
+        DataSet ds = dc.query().from(TEST_DATABASE_NAME).select("_id", "foo", "greeting").execute();
+        assertTrue(ds.next());
+        assertNotNull(ds.getRow().getValue(0));
+        assertEquals("bar", ds.getRow().getValue(1));
+        assertEquals("hello", ds.getRow().getValue(2));
+        assertTrue(ds.next());
+        assertNotNull(ds.getRow().getValue(0));
+        assertEquals("baz", ds.getRow().getValue(1));
+        assertEquals("hi", ds.getRow().getValue(2));
+        assertFalse(ds.next());
+        ds.close();
+
+        dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback callback) {
+                callback.update(TEST_DATABASE_NAME).value("greeting", "howdy").where("foo").isEquals("baz").execute();
+
+                callback.update(TEST_DATABASE_NAME).value("foo", "foo").where("foo").isEquals("bar").execute();
+            }
+        });
+
+        ds = dc.query().from(TEST_DATABASE_NAME).select("_id", "foo", "greeting").execute();
+        assertTrue(ds.next());
+        assertNotNull(ds.getRow().getValue(0));
+        assertEquals("foo", ds.getRow().getValue(1));
+        assertEquals("hello", ds.getRow().getValue(2));
+        assertTrue(ds.next());
+        assertNotNull(ds.getRow().getValue(0));
+        assertEquals("baz", ds.getRow().getValue(1));
+        assertEquals("howdy", ds.getRow().getValue(2));
+        assertFalse(ds.next());
+        ds.close();
+    }
+
+    public void testBasicQuery() throws Exception {
+        if (!serverAvailable) {
+            return;
+        }
+
+        // insert a few records
+        {
+            HashMap<String, Object> map;
+
+            map = new HashMap<String, Object>();
+            map.put("name", "John Doe");
+            map.put("age", 30);
+            connector.create(map);
+
+            map = new HashMap<String, Object>();
+            map.put("name", "Jane Doe");
+            map.put("gender", 'F');
+            connector.create(map);
+        }
+
+        // create datacontext using detected schema
+        SimpleTableDef tableDef = CouchDbDataContext.detectTable(connector);
+        CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, tableDef);
+
+        // verify schema and execute query
+        Schema schema = dc.getMainSchema();
+        assertEquals("[eobjects_metamodel_test]", Arrays.toString(schema.getTableNames()));
+
+        assertEquals("[_id, _rev, age, gender, name]",
+                Arrays.toString(schema.getTableByName(TEST_DATABASE_NAME).getColumnNames()));
+        Column idColumn = schema.getTableByName(TEST_DATABASE_NAME).getColumnByName("_id");
+        assertEquals("Column[name=_id,columnNumber=0,type=VARCHAR,nullable=true,nativeType=null,columnSize=null]",
+                idColumn.toString());
+        assertTrue(idColumn.isPrimaryKey());
+
+        assertEquals("Column[name=_rev,columnNumber=1,type=VARCHAR,nullable=true,nativeType=null,columnSize=null]", schema
+                .getTableByName(TEST_DATABASE_NAME).getColumnByName("_rev").toString());
+
+        DataSet ds;
+
+        ds = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").execute();
+        assertTrue(ds.next());
+        assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString());
+        assertTrue(ds.next());
+        assertEquals("Row[values=[Jane Doe, null]]", ds.getRow().toString());
+        assertFalse(ds.next());
+        ds.close();
+
+        ds = dc.query().from(TEST_DATABASE_NAME).select("name").and("gender").where("age").isNull().execute();
+        assertTrue(ds.next());
+        assertEquals("Row[values=[Jane Doe, F]]", ds.getRow().toString());
+        assertFalse(ds.next());
+        ds.close();
+    }
+
+    public void testFirstRowAndLastRow() throws Exception {
+        if (!serverAvailable) {
+            return;
+        }
+
+        // insert a few records
+        {
+            HashMap<String, Object> map;
+
+            map = new HashMap<String, Object>();
+            map.put("name", "John Doe");
+            map.put("age", 30);
+            connector.create(map);
+
+            map = new HashMap<String, Object>();
+            map.put("name", "Jane Doe");
+            map.put("gender", 'F');
+            connector.create(map);
+        }
+
+        // create datacontext using detected schema
+        SimpleTableDef tableDef = CouchDbDataContext.detectTable(connector);
+        CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, tableDef);
+
+        DataSet ds1 = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").firstRow(2).execute();
+        DataSet ds2 = dc.query().from(TEST_DATABASE_NAME).select("name").and("age").maxRows(1).execute();
+
+        assertTrue("Class: " + ds1.getClass().getName(), ds1 instanceof CouchDbDataSet);
+        assertTrue("Class: " + ds2.getClass().getName(), ds2 instanceof CouchDbDataSet);
+
+        assertTrue(ds1.next());
+        assertTrue(ds2.next());
+
+        final Row row1 = ds1.getRow();
+        final Row row2 = ds2.getRow();
+
+        assertFalse(ds1.next());
+        assertFalse(ds2.next());
+
+        assertEquals("Row[values=[Jane Doe, null]]", row1.toString());
+        assertEquals("Row[values=[John Doe, 30]]", row2.toString());
+
+        ds1.close();
+        ds2.close();
+    }
+
+    public void testInsert() throws Exception {
+        if (!serverAvailable) {
+            return;
+        }
+
+        // create datacontext using predefined table def
+        CouchDbDataContext dc = new CouchDbDataContext(httpClient, predefinedTableDef);
+        Table table = dc.getTableByQualifiedLabel(TEST_DATABASE_NAME);
+        assertNotNull(table);
+
+        assertEquals("[_id, _rev, name, gender, age]", Arrays.toString(table.getColumnNames()));
+
+        DataSet ds;
+
+        // assert not rows in DB
+        ds = dc.query().from(TEST_DATABASE_NAME).selectCount().execute();
+        assertTrue(ds.next());
+        assertEquals(0, ((Number) ds.getRow().getValue(0)).intValue());
+        assertFalse(ds.next());
+        ds.close();
+
+        dc.executeUpdate(new UpdateScript() {
+            @Override
+            public void run(UpdateCallback callback) {
+                callback.insertInto(TEST_DATABASE_NAME).value("name", "foo").value("gender", 'M').execute();
+                callback.insertInto(TEST_DATABASE_NAME).value("name", "bar").value("age", 32).execute();
+            }
+        });
+
+        // now count should be 2
+        ds = dc.query().from(TEST_DATABASE_NAME).selectCount().execute();
+        assertTrue(ds.next());
+        assertEquals(2, ((Number) ds.getRow().getValue(0)).intValue());
+        assertFalse(ds.next());
+        ds.close();
+
+        ds = dc.query().from(TEST_DATABASE_NAME).select("name", "gender", "age").execute();
+        assertTrue(ds.next());
+        assertEquals("Row[values=[foo, M, null]]", ds.getRow().toString());
+        assertTrue(ds.next());
+        assertEquals("Row[values=[bar, null, 32]]", ds.getRow().toString());
+        assertFalse(ds.next());
+        ds.close();
+    }
+}