METAMODEL-1165: Fixed - added default_table alias table
[metamodel.git] / couchdb / src / main / java / org / apache / metamodel / couchdb / CouchDbDataContext.java
1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19 package org.apache.metamodel.couchdb;
20
21 import java.util.List;
22 import java.util.stream.Collectors;
23
24 import org.apache.metamodel.MetaModelException;
25 import org.apache.metamodel.QueryPostprocessDataContext;
26 import org.apache.metamodel.UpdateScript;
27 import org.apache.metamodel.UpdateSummary;
28 import org.apache.metamodel.UpdateableDataContext;
29 import org.apache.metamodel.data.DataSet;
30 import org.apache.metamodel.data.DocumentSource;
31 import org.apache.metamodel.data.SimpleDataSetHeader;
32 import org.apache.metamodel.query.FilterItem;
33 import org.apache.metamodel.query.SelectItem;
34 import org.apache.metamodel.schema.Column;
35 import org.apache.metamodel.schema.Schema;
36 import org.apache.metamodel.schema.Table;
37 import org.apache.metamodel.schema.builder.DocumentSourceProvider;
38 import org.apache.metamodel.schema.builder.SchemaBuilder;
39 import org.apache.metamodel.util.SimpleTableDef;
40 import org.ektorp.CouchDbConnector;
41 import org.ektorp.CouchDbInstance;
42 import org.ektorp.StreamingViewResult;
43 import org.ektorp.ViewQuery;
44 import org.ektorp.http.HttpClient;
45 import org.ektorp.http.StdHttpClient;
46 import org.ektorp.impl.StdCouchDbInstance;
47
48 import com.fasterxml.jackson.databind.JsonNode;
49
50 /**
51 * DataContext implementation for CouchDB
52 */
53 public class CouchDbDataContext extends QueryPostprocessDataContext implements UpdateableDataContext,
54 DocumentSourceProvider {
55
56 public static final String SCHEMA_NAME = "CouchDB";
57
58 public static final int DEFAULT_PORT = 5984;
59
60 public static final String FIELD_ID = "_id";
61 public static final String FIELD_REV = "_rev";
62
63 // the instance represents a handle to the whole couchdb cluster
64 private final CouchDbInstance _couchDbInstance;
65 private final SchemaBuilder _schemaBuilder;
66
67 public CouchDbDataContext(StdHttpClient.Builder httpClientBuilder, SimpleTableDef... tableDefs) {
68 this(httpClientBuilder.build(), tableDefs);
69 }
70
71 public CouchDbDataContext(StdHttpClient.Builder httpClientBuilder) {
72 this(httpClientBuilder.build());
73 }
74
75 public CouchDbDataContext(HttpClient httpClient, SimpleTableDef... tableDefs) {
76 this(new StdCouchDbInstance(httpClient), tableDefs);
77 }
78
79 public CouchDbDataContext(HttpClient httpClient) {
80 this(new StdCouchDbInstance(httpClient));
81 }
82
83 public CouchDbDataContext(CouchDbInstance couchDbInstance) {
84 super(false);
85 _couchDbInstance = couchDbInstance;
86 _schemaBuilder = new CouchDbInferentialSchemaBuilder();
87 }
88
89 public CouchDbDataContext(CouchDbInstance couchDbInstance, String... databaseNames) {
90 super(false);
91 _couchDbInstance = couchDbInstance;
92 _schemaBuilder = new CouchDbInferentialSchemaBuilder(databaseNames);
93 }
94
95 public CouchDbDataContext(CouchDbInstance couchDbInstance, SimpleTableDef... tableDefs) {
96 super(false);
97 _couchDbInstance = couchDbInstance;
98 _schemaBuilder = new CouchDbSimpleTableDefSchemaBuilder(tableDefs);
99 }
100
101 public CouchDbInstance getCouchDbInstance() {
102 return _couchDbInstance;
103 }
104
105 @Override
106 protected Schema getMainSchema() throws MetaModelException {
107 _schemaBuilder.offerSources(this);
108 return _schemaBuilder.build();
109 }
110
111 @Override
112 protected String getMainSchemaName() throws MetaModelException {
113 return _schemaBuilder.getSchemaName();
114 }
115
116 @Override
117 protected DataSet materializeMainSchemaTable(Table table, List<Column> columns, int firstRow, int maxRows) {
118 // the connector represents a handle to the the couchdb "database".
119 final String databaseName = table.getName();
120 final CouchDbConnector connector = _couchDbInstance.createConnector(databaseName, false);
121
122 ViewQuery query = new ViewQuery().allDocs().includeDocs(true);
123
124 if (maxRows > 0) {
125 query = query.limit(maxRows);
126 }
127 if (firstRow > 1) {
128 final int skip = firstRow - 1;
129 query = query.skip(skip);
130 }
131
132 final StreamingViewResult streamingView = connector.queryForStreamingView(query);
133
134 final List<SelectItem> selectItems = columns.stream().map(SelectItem::new).collect(Collectors.toList());
135 return new CouchDbDataSet(selectItems, streamingView);
136 }
137
138 @Override
139 protected DataSet materializeMainSchemaTable(Table table, List<Column> columns, int maxRows) {
140 return materializeMainSchemaTable(table, columns, 1, maxRows);
141 }
142
143 @Override
144 protected org.apache.metamodel.data.Row executePrimaryKeyLookupQuery(Table table, List<SelectItem> selectItems,
145 Column primaryKeyColumn, Object keyValue) {
146 if (keyValue == null) {
147 return null;
148 }
149
150 final String databaseName = table.getName();
151 final CouchDbConnector connector = _couchDbInstance.createConnector(databaseName, false);
152
153 final String keyString = keyValue.toString();
154 final JsonNode node = connector.find(JsonNode.class, keyString);
155 if (node == null) {
156 return null;
157 }
158
159 return CouchDbUtils.jsonNodeToMetaModelRow(node, new SimpleDataSetHeader(selectItems));
160 }
161
162 @Override
163 protected Number executeCountQuery(Table table, List<FilterItem> whereItems, boolean functionApproximationAllowed) {
164 if (whereItems.isEmpty()) {
165 String databaseName = table.getName();
166 CouchDbConnector connector = _couchDbInstance.createConnector(databaseName, false);
167 long docCount = connector.getDbInfo().getDocCount();
168 return docCount;
169 }
170 return null;
171 }
172
173 @Override
174 public UpdateSummary executeUpdate(UpdateScript script) {
175 final CouchDbUpdateCallback callback = new CouchDbUpdateCallback(this);
176 try {
177 script.run(callback);
178 } finally {
179 callback.close();
180 }
181 return callback.getUpdateSummary();
182 }
183
184 @Override
185 public DocumentSource getMixedDocumentSourceForSampling() {
186 return new CouchDbSamplingDocumentSource(_couchDbInstance);
187 }
188
189 @Override
190 public DocumentSource getDocumentSourceForTable(String sourceCollectionName) {
191 return new CouchDbDatabaseDocumentSource(_couchDbInstance, sourceCollectionName, -1);
192 }
193 }