| /** |
| * 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.apache.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 org.apache.metamodel.UpdateCallback; |
| import org.apache.metamodel.UpdateScript; |
| import org.apache.metamodel.data.DataSet; |
| import org.apache.metamodel.data.Row; |
| import org.apache.metamodel.drop.DropTable; |
| import org.apache.metamodel.insert.InsertInto; |
| import org.apache.metamodel.schema.Column; |
| import org.apache.metamodel.schema.ColumnType; |
| import org.apache.metamodel.schema.Schema; |
| import org.apache.metamodel.schema.Table; |
| import org.apache.metamodel.util.SimpleTableDef; |
| import org.ektorp.CouchDbConnector; |
| import org.ektorp.http.HttpClient; |
| import org.ektorp.http.StdHttpClient; |
| import org.ektorp.impl.StdCouchDbInstance; |
| |
| public class CouchDbDataContextTest extends CouchDbTestCase { |
| |
| private HttpClient httpClient; |
| private StdCouchDbInstance couchDbInstance; |
| private CouchDbConnector connector; |
| private SimpleTableDef predefinedTableDef; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| |
| if (isConfigured()) { |
| httpClient = new StdHttpClient.Builder().host(getHostname()).build(); |
| |
| // set up a simple database |
| couchDbInstance = new StdCouchDbInstance(httpClient); |
| |
| final String databaseName = getDatabaseName(); |
| if (couchDbInstance.getAllDatabases().contains(databaseName)) { |
| throw new IllegalStateException("Couch DB instance already has a database called " + databaseName); |
| } |
| connector = couchDbInstance.createConnector(databaseName, true); |
| |
| final String[] columnNames = new String[] { "name", "gender", "age" }; |
| final ColumnType[] columnTypes = new ColumnType[] { ColumnType.STRING, ColumnType.CHAR, ColumnType.INTEGER }; |
| predefinedTableDef = new SimpleTableDef(databaseName, columnNames, columnTypes); |
| } |
| |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| super.tearDown(); |
| |
| connector = null; |
| |
| if (isConfigured()) { |
| couchDbInstance.deleteDatabase(getDatabaseName()); |
| |
| httpClient.shutdown(); |
| } |
| } |
| |
| public void testWorkingWithMapsAndLists() throws Exception { |
| if (!isConfigured()) { |
| System.err.println(getInvalidConfigurationMessage()); |
| 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); |
| |
| CouchDbDataContext dc2 = new CouchDbDataContext(couchDbInstance, new SimpleTableDef("test_table_map_and_list", |
| new String[] { "foo.hello[0]", "bar[1].couch" })); |
| ds = dc2.query().from("test_table_map_and_list").select("foo.hello[0]", "bar[1].couch").execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[world, db]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| } finally { |
| dc.executeUpdate(new DropTable(table)); |
| } |
| |
| } |
| |
| public void testCreateUpdateDeleteScenario() throws Exception { |
| if (!isConfigured()) { |
| System.err.println(getInvalidConfigurationMessage()); |
| return; |
| } |
| |
| final String databaseName = getDatabaseName(); |
| |
| { |
| // insert a document to provide data to do inferential schema |
| // detection |
| final CouchDbConnector connector = couchDbInstance.createConnector(databaseName, false); |
| final Map<String, Object> map = new HashMap<String, Object>(); |
| map.put("foo", "bar"); |
| map.put("bar", "baz"); |
| map.put("baz", 1234); |
| connector.addToBulkBuffer(map); |
| connector.flushBulkBuffer(); |
| } |
| |
| final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance); |
| Table table = dc.getDefaultSchema().getTableByName(databaseName); |
| assertNotNull(table); |
| assertEquals("[Column[name=_id,columnNumber=0,type=STRING,nullable=false,nativeType=null,columnSize=null], " |
| + "Column[name=_rev,columnNumber=1,type=STRING,nullable=false,nativeType=null,columnSize=null], " |
| + "Column[name=bar,columnNumber=2,type=STRING,nullable=null,nativeType=null,columnSize=null], " |
| + "Column[name=baz,columnNumber=3,type=INTEGER,nullable=null,nativeType=null,columnSize=null], " |
| + "Column[name=foo,columnNumber=4,type=STRING,nullable=null,nativeType=null,columnSize=null]]", |
| Arrays.toString(table.getColumns())); |
| |
| // first delete the manually created database! |
| dc.executeUpdate(new UpdateScript() { |
| @Override |
| public void run(UpdateCallback callback) { |
| callback.dropTable(databaseName).execute(); |
| } |
| }); |
| |
| table = dc.getDefaultSchema().getTableByName(databaseName); |
| assertNull(table); |
| |
| dc.executeUpdate(new UpdateScript() { |
| @Override |
| public void run(UpdateCallback callback) { |
| Table table = callback.createTable(dc.getDefaultSchema(), databaseName).withColumn("foo") |
| .ofType(ColumnType.STRING).withColumn("greeting").ofType(ColumnType.STRING).execute(); |
| assertEquals("[_id, _rev, foo, greeting]", Arrays.toString(table.getColumnNames())); |
| } |
| }); |
| |
| dc.executeUpdate(new UpdateScript() { |
| @Override |
| public void run(UpdateCallback callback) { |
| callback.insertInto(databaseName).value("foo", "bar").value("greeting", "hello").execute(); |
| callback.insertInto(databaseName).value("foo", "baz").value("greeting", "hi").execute(); |
| } |
| }); |
| |
| DataSet ds = dc.query().from(databaseName).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(databaseName).value("greeting", "howdy").where("foo").isEquals("baz").execute(); |
| |
| callback.update(databaseName).value("foo", "foo").where("foo").isEquals("bar").execute(); |
| } |
| }); |
| |
| ds = dc.query().from(databaseName).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 (!isConfigured()) { |
| System.err.println(getInvalidConfigurationMessage()); |
| 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 |
| CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, getDatabaseName()); |
| |
| // verify schema and execute query |
| Schema schema = dc.getMainSchema(); |
| assertEquals("[" + getDatabaseName() + "]", Arrays.toString(schema.getTableNames())); |
| |
| assertEquals("[_id, _rev, age, gender, name]", |
| Arrays.toString(schema.getTableByName(getDatabaseName()).getColumnNames())); |
| Column idColumn = schema.getTableByName(getDatabaseName()).getColumnByName("_id"); |
| assertEquals("Column[name=_id,columnNumber=0,type=STRING,nullable=false,nativeType=null,columnSize=null]", |
| idColumn.toString()); |
| assertTrue(idColumn.isPrimaryKey()); |
| |
| assertEquals("Column[name=_rev,columnNumber=1,type=STRING,nullable=false,nativeType=null,columnSize=null]", |
| schema.getTableByName(getDatabaseName()).getColumnByName("_rev").toString()); |
| |
| DataSet ds; |
| |
| ds = dc.query().from(getDatabaseName()).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(getDatabaseName()).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(); |
| |
| ds = dc.query().from(getDatabaseName()).select("_id").where("name").eq("Jane Doe").execute(); |
| assertTrue(ds.next()); |
| Object pkValue = ds.getRow().getValue(0); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| // Test greater than or equals |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").greaterThanOrEquals(29) |
| .execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").greaterThanOrEquals(30) |
| .execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").greaterThanOrEquals(31) |
| .execute(); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| // Test less than or equals |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").lessThanOrEquals(31).execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").lessThanOrEquals(30).execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[John Doe, 30]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| ds = dc.query().from(getDatabaseName()).select("name").and("age").where("age").lessThanOrEquals(29).execute(); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| // test primary key lookup query |
| ds = dc.query().from(getDatabaseName()).select("name").and("gender").where("_id").eq(pkValue).execute(); |
| assertTrue(ds.next()); |
| assertEquals("Row[values=[Jane Doe, F]]", ds.getRow().toString()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| // test primary key null |
| ds = dc.query().from(getDatabaseName()).select("name").and("gender").where("_id").isNull().execute(); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| // test primary key not found |
| ds = dc.query().from(getDatabaseName()).select("name").and("gender").where("_id").eq("this id does not exist") |
| .execute(); |
| assertFalse(ds.next()); |
| ds.close(); |
| } |
| |
| public void testFirstRowAndLastRow() throws Exception { |
| if (!isConfigured()) { |
| System.err.println(getInvalidConfigurationMessage()); |
| 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 |
| final String databaseName = getDatabaseName(); |
| final CouchDbDataContext dc = new CouchDbDataContext(couchDbInstance, databaseName); |
| |
| final DataSet ds1 = dc.query().from(databaseName).select("name").and("age").firstRow(2).execute(); |
| final DataSet ds2 = dc.query().from(databaseName).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 (!isConfigured()) { |
| System.err.println(getInvalidConfigurationMessage()); |
| return; |
| } |
| |
| // create datacontext using predefined table def |
| CouchDbDataContext dc = new CouchDbDataContext(httpClient, predefinedTableDef); |
| Table table = dc.getTableByQualifiedLabel(getDatabaseName()); |
| assertNotNull(table); |
| |
| assertEquals("[_id, _rev, name, gender, age]", Arrays.toString(table.getColumnNames())); |
| |
| DataSet ds; |
| |
| // assert not rows in DB |
| ds = dc.query().from(getDatabaseName()).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(getDatabaseName()).value("name", "foo").value("gender", 'M').execute(); |
| callback.insertInto(getDatabaseName()).value("name", "bar").value("age", 32).execute(); |
| } |
| }); |
| |
| // now count should be 2 |
| ds = dc.query().from(getDatabaseName()).selectCount().execute(); |
| assertTrue(ds.next()); |
| assertEquals(2, ((Number) ds.getRow().getValue(0)).intValue()); |
| assertFalse(ds.next()); |
| ds.close(); |
| |
| ds = dc.query().from(getDatabaseName()).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(); |
| } |
| } |