From 752aaea9f05148ab76f942f675319a5fe05bb5d7 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sat, 18 Apr 2015 00:25:10 +0530 Subject: [PATCH 1/7] Solr connector added --- solr/.classpath | 24 + solr/.project | 20 + solr/.settings/org.eclipse.jdt.core.prefs | 9 + solr/pom.xml | 89 ++++ .../metamodel/solr/SolrDataContext.java | 429 ++++++++++++++++++ .../apache/metamodel/solr/SolrDataSet.java | 174 +++++++ .../metamodel/solr/SolrDataContextTest1.java | 199 ++++++++ 7 files changed, 944 insertions(+) create mode 100644 solr/.classpath create mode 100644 solr/.project create mode 100644 solr/.settings/org.eclipse.jdt.core.prefs create mode 100644 solr/pom.xml create mode 100644 solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java create mode 100644 solr/src/main/java/org/apache/metamodel/solr/SolrDataSet.java create mode 100644 solr/src/test/java/org/apache/metamodel/solr/SolrDataContextTest1.java diff --git a/solr/.classpath b/solr/.classpath new file mode 100644 index 000000000..73d91c6ba --- /dev/null +++ b/solr/.classpath @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/solr/.project b/solr/.project new file mode 100644 index 000000000..570783e44 --- /dev/null +++ b/solr/.project @@ -0,0 +1,20 @@ + + + MetaModel-solr + MetaModel is a library that encapsulates the differences and enhances + the capabilities of different datastores. Rich querying abilities are + offered to datastores that do not otherwise support advanced querying + and a unified view of the datastore structure is offered through a + single model of the schemas, tables, columns and relationships. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + MetaModel-core + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/solr/.settings/org.eclipse.jdt.core.prefs b/solr/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..28ddb0a96 --- /dev/null +++ b/solr/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +#Fri Jan 30 22:32:19 IST 2015 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +eclipse.preferences.version=1 +encoding/src/main/java=utf-8 +org.eclipse.jdt.core.compiler.source=1.6 +encoding/src/test/resources=utf-8 +encoding/src/main/resources=utf-8 +encoding/src/test/java=utf-8 +org.eclipse.jdt.core.compiler.compliance=1.6 diff --git a/solr/pom.xml b/solr/pom.xml new file mode 100644 index 000000000..efe6593d1 --- /dev/null +++ b/solr/pom.xml @@ -0,0 +1,89 @@ + + + + + MetaModel + org.apache.metamodel + 4.3.4-SNAPSHOT + + 4.0.0 + MetaModel-solr + MetaModel module for Solr analytics engine + + + 4.10.3 + 4.7.2 + + + + + org.apache.metamodel + MetaModel-core + ${project.version} + + + commons-io + commons-io + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + + org.slf4j + slf4j-log4j12 + test + + + junit + junit + test + + + + + + latest + + !1.6 + + + + + org.apache.solr + solr-solrj + ${solr.latest.version} + + + + + + jdk6 + + 1.6 + + + + + org.apache.solr + solr-solrj + ${solr.jdk6.version} + + + + + diff --git a/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java b/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java new file mode 100644 index 000000000..95b537c07 --- /dev/null +++ b/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java @@ -0,0 +1,429 @@ +/** + * 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.solr; + +import java.io.InputStreamReader; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.metamodel.DataContext; +import org.apache.metamodel.MetaModelException; +import org.apache.metamodel.query.Query; +import org.apache.metamodel.QueryPostprocessDataContext; +import org.apache.metamodel.data.DataSet; +import org.apache.metamodel.data.DataSetHeader; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.data.SimpleDataSetHeader; +import org.apache.metamodel.query.FilterClause; +import org.apache.metamodel.query.FilterItem; +import org.apache.metamodel.query.GroupByItem; +import org.apache.metamodel.query.OrderByItem; +import org.apache.metamodel.query.SelectItem; +import org.apache.metamodel.query.LogicalOperator; +import org.apache.metamodel.query.OperatorType; +import org.apache.metamodel.query.FunctionType; +import org.apache.metamodel.schema.Column; +import org.apache.metamodel.schema.ColumnType; +import org.apache.metamodel.schema.MutableColumn; +import org.apache.metamodel.schema.MutableSchema; +import org.apache.metamodel.schema.MutableTable; +import org.apache.metamodel.schema.Schema; +import org.apache.metamodel.schema.Table; +import org.apache.metamodel.util.SimpleTableDef; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.SolrQuery.ORDER; +import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.client.solrj.response.QueryResponse; +import org.apache.solr.client.solrj.response.FacetField; +import org.apache.solr.common.SolrDocumentList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; + +/** + * DataContext implementation for ElasticSearch analytics engine. + * + * ElasticSearch has a data storage structure hierarchy that briefly goes like + * this: + * + * + * When instantiating this DataContext, an index name is provided. Within this + * index, each document type is represented as a table. + * + * This implementation supports either automatic discovery of a schema or manual + * specification of a schema, through the {@link SimpleTableDef} class. + */ + +public class SolrDataContext extends QueryPostprocessDataContext implements + DataContext { + + private static final Logger logger = LoggerFactory + .getLogger(SolrDataContext.class); + + public static final String FIELD_ID = "_id"; + + private final SimpleTableDef tableDef; + private final String indexName; + private final String url; + + private SolrQuery query = new SolrQuery(); + + private static enum queryTypes { + ROW, FACET + }; + + private static final int MAX_RETRIES = 0; + private static final int SOCK_TIMEOUT = 1000; + private static final int CONN_TIMEOUT = 5000; + private static final int DEFAULT_LIMIT = 1000; + + public SolrDataContext(String url, String indexName) { + this.url = url; + this.indexName = indexName; + this.tableDef = detectSchema(url, indexName); + } + + private SimpleTableDef detectSchema(String url, String indexName) { + SimpleTableDef tableDef = null; + + url += "/schema"; + + try { + HttpClient httpclient = new DefaultHttpClient(); + HttpGet request = new HttpGet(url); + HttpResponse response = httpclient.execute(request); + + InputStreamReader inputStream = new InputStreamReader(response + .getEntity().getContent()); + + ObjectReader reader = new ObjectMapper().reader(HashMap.class); + Map outerMap = reader.readValue(inputStream); + + Map schemaMap = (Map) outerMap.get("schema"); + + if (outerMap != null) { + List> fieldMapList = (List) schemaMap + .get("fields"); + List columnNames = new ArrayList(); + List columnTypes = new ArrayList(); + + for (int i = 0; i < fieldMapList.size(); i++) { + Map fieldMap = fieldMapList.get(i); + + columnNames.add(fieldMap.get("name")); + columnTypes.add(ColumnType.VARCHAR); + } + + String[] columnNamesArr = new String[columnNames.size()]; + columnNamesArr = columnNames.toArray(columnNamesArr); + + ColumnType[] columnTypesArr = new ColumnType[columnTypes.size()]; + columnTypesArr = columnTypes.toArray(columnTypesArr); + + tableDef = new SimpleTableDef(indexName, columnNamesArr, + columnTypesArr); + } + } catch (IOException e) { + logger.error("Failed to parse schema", "", e); + } + + return tableDef; + } + + @Override + protected Schema getMainSchema() throws MetaModelException { + try { + final MutableSchema theSchema = new MutableSchema( + getMainSchemaName()); + + final MutableTable table = tableDef.toTable().setSchema(theSchema); + final Column idColumn = table.getColumnByName(FIELD_ID); + if (idColumn != null && idColumn instanceof MutableColumn) { + final MutableColumn mutableColumn = (MutableColumn) idColumn; + mutableColumn.setPrimaryKey(true); + } + theSchema.addTable(table); + + return theSchema; + } catch (Exception e) { + throw new MetaModelException("Schema retrieval failed " + e); + } + } + + @Override + protected Number executeCountQuery(Table table, + List whereItems, boolean functionApproximationAllowed) { + String queryStr = "*:*"; + + if (whereItems != null) { + for (int i = 0; i < whereItems.size(); i++) { + FilterItem whereItem = whereItems.get(i); + queryStr = whereItem.toString(); + } + } + + QueryResponse response = selectRows(table, null, queryStr, 0, 0); + return response.getResults().getNumFound(); + } + + private String processSingleFilterItem(FilterItem filterItem) { + String clause = ""; + + if (filterItem != null) { + SelectItem item = filterItem.getSelectItem(); + OperatorType operator = filterItem.getOperator(); + Object operand = filterItem.getOperand(); + + if (item == null || operator == null || operand == null) { + clause = " " + filterItem.getExpression(); + } else { + String columnName = item.getColumn().getName(); + clause = " " + columnName + operator.toSql() + operand; + } + } + + return clause; + } + + private String createSearchClause(FilterItem filterItem, String clause) { + FilterItem[] filterItems = filterItem.getChildItems(); + + if (filterItems != null && filterItems.length > 0) { + for (FilterItem filterItemInner : filterItems) { + if (filterItemInner != null) { + clause += " " + processSingleFilterItem(filterItemInner); + } + + return createSearchClause(filterItemInner, clause); + } + } + + if (filterItem != null) { + clause += " " + processSingleFilterItem(filterItem); + } + + return clause; + } + + @Override + public DataSet executeQuery(Query q) throws MetaModelException { + String queryStr = ""; + QueryResponse response = null; + + Schema schema = getMainSchema(); + Table table = schema.getTable(0); + Column[] columns = table.getColumns(); + + boolean selectAll = true; + List selectItems = q.getSelectClause().getItems(); + + for (SelectItem selectItem : selectItems) { + if (selectItem.getFunction() != null + || selectItem.getColumn() == null) { + selectAll = false; + break; + } + } + + if (selectItems.size() == 1 && selectAll == false) { + return super.executeQuery(q); + } + + FilterClause clause = q.getWhereClause(); + + String searchClause = ""; + + if (clause != null) { + List filterItemList = clause.getItems(); + + for (FilterItem filterItem : filterItemList) { + searchClause += " " + + createSearchClause(filterItem, searchClause); + } + + queryStr = searchClause; + } + + if (queryStr.isEmpty()) { + queryStr = "*:*"; + } + + Integer limitObject = q.getMaxRows(); + int limit = DEFAULT_LIMIT; + + if (limitObject != null) { + limit = (int) limitObject; + } + + final List groupByItems = q.getGroupByClause().getItems(); + + if (groupByItems.size() > 0) { + query.clear(); + query.setQuery(queryStr); + query.setFacet(true); + + for (int i = 0; i < groupByItems.size(); i++) { + String facetField = groupByItems.get(i).getSelectItem() + .getColumn().getName(); + query.addFacetField(facetField); + } + + setOrder(q, query, queryTypes.FACET); + + query.setFacetLimit(limit); + + try { + HttpSolrServer server = initSolrServer(); + response = server.query(query); + } catch (SolrServerException e) { + logger.error("Server initialization failed", "", e); + throw new MetaModelException("Server initialization failed " + + e); + } + + List facetFieldsList = response.getFacetFields(); + + String facetFieldName = facetFieldsList.get(0).getName(); + + Column[] facetColumns = { new MutableColumn("count"), + new MutableColumn(facetFieldName) }; + + return new SolrDataSet(facetFieldsList, facetColumns); + } else if (selectAll) { + response = selectRows(table, q, queryStr, 0, limit); + SolrDocumentList results = response.getResults(); + + return new SolrDataSet(results, columns); + } + + return super.executeQuery(q); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, + int maxRows) { + QueryResponse response = selectRows(table, null, "*:*", 0, maxRows); + return new SolrDataSet(response.getResults(), columns); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, + int offset, int num) { + QueryResponse response = selectRows(table, null, "*:*", offset, num); + return new SolrDataSet(response.getResults(), columns); + } + + private void setOrder(Query q, SolrQuery query, queryTypes qtype) { + List orderByList = q.getOrderByClause().getItems(); + + for (OrderByItem orderItem : orderByList) { + SelectItem orderFieldOrFunc = orderItem.getSelectItem(); + Column orderColumn = orderFieldOrFunc.getColumn(); + FunctionType orderFunc = orderFieldOrFunc.getFunction(); + + String orderField = null; + String direction = orderItem.getDirection().toString(); + + if (orderColumn != null) { + orderField = orderColumn.getName(); + + if (direction == null || direction.equalsIgnoreCase("ASC")) { + query.addSort(orderField, SolrQuery.ORDER.asc); + } else { + query.addSort(orderField, SolrQuery.ORDER.desc); + } + } + + if (qtype == queryTypes.FACET) { + if (orderColumn == null) { + if (direction.equalsIgnoreCase("ASC")) { + throw new UnsupportedOperationException( + "Ascending sort on count unsupported"); + } + query.setFacetSort("count"); + } else { + if (direction.equalsIgnoreCase("DESC")) { + throw new UnsupportedOperationException( + "Descending sort on facet unsupported"); + } + query.setFacetSort("index"); + } + } + } + } + + private HttpSolrServer initSolrServer() { + HttpSolrServer server = new HttpSolrServer(url); + server.setMaxRetries(MAX_RETRIES); + server.setSoTimeout(SOCK_TIMEOUT); + server.setConnectionTimeout(CONN_TIMEOUT); + server.setFollowRedirects(false); + + return server; + } + + private QueryResponse selectRows(Table table, Query q, String queryStr, + int offset, int num) { + HttpSolrServer server = initSolrServer(); + + query.clear(); + query.setQuery(queryStr); + query.setStart(offset); + query.setRows(num); + + if (q != null) { + setOrder(q, query, queryTypes.ROW); + } + + QueryResponse response = null; + + try { + response = server.query(query); + } catch (SolrServerException e) { + logger.error("Search query for documents failed", "", e); + throw new MetaModelException("Query failed " + e); + } + + return response; + } + + @Override + protected String getMainSchemaName() throws MetaModelException { + return indexName; + } +} \ No newline at end of file diff --git a/solr/src/main/java/org/apache/metamodel/solr/SolrDataSet.java b/solr/src/main/java/org/apache/metamodel/solr/SolrDataSet.java new file mode 100644 index 000000000..9bdcf6ba2 --- /dev/null +++ b/solr/src/main/java/org/apache/metamodel/solr/SolrDataSet.java @@ -0,0 +1,174 @@ +/** + * 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.solr; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.List; +import java.util.Set; +import java.util.IdentityHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.metamodel.data.AbstractDataSet; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.data.DataSetHeader; +import org.apache.metamodel.data.DefaultRow; +import org.apache.metamodel.schema.Column; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.solr.client.solrj.response.FacetField; +import org.apache.solr.client.solrj.response.FacetField.Count; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrDocumentList; + +/** + * {@link DataSet} implementation for ElasticSearch + */ +final class SolrDataSet extends AbstractDataSet { + + private static final Logger logger = LoggerFactory + .getLogger(SolrDataSet.class); + + private final AtomicBoolean _closed; + private final SolrDocumentList _docs; + private final Map> _facetMap; + + private Column[] _columns; + private int _numColumns = 0; + private int _hitIndex = 0; + private int _docListSize = 0; + private int _facetFieldListSize = 0; + + public SolrDataSet(SolrDocumentList _docs, Column[] columns) { + super(columns); + _numColumns = columns.length; + _columns = columns; + this._docs = _docs; + + _facetMap = null; + _docListSize = _docs.size(); + _closed = new AtomicBoolean(false); + } + + public SolrDataSet(List facetFieldsList, Column[] columns) { + super(columns); + _numColumns = columns.length; + _columns = columns; + + Map> facetMap = new IdentityHashMap>(); + + for (FacetField facetField : facetFieldsList) { + String facetName = facetField.getName(); + List facetPairs = facetField.getValues(); + facetMap.put(facetName, facetPairs); + _facetFieldListSize = facetPairs.size(); + } + + _facetMap = facetMap; + _docs = null; + _closed = new AtomicBoolean(false); + } + + @Override + public void close() { + super.close(); + boolean closeNow = _closed.compareAndSet(true, false); + if (closeNow) { + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (!_closed.get()) { + logger.warn( + "finalize() invoked, but DataSet is not closed. Invoking close() on {}", + this); + close(); + } + } + + @Override + public boolean next() { + if (_docListSize != 0 && _docListSize == _hitIndex) + return false; + + if (_facetFieldListSize != 0 && _facetFieldListSize == _hitIndex) + return false; + + if (_docListSize == 0 && _facetFieldListSize == 0) + return false; + + return true; + } + + private Object[] getRow(SolrDocumentList _docs) { + Object[] values = new Object[_numColumns]; + SolrDocument doc = _docs.get(_hitIndex); + + Map docValues = doc.getFieldValueMap(); + + for (int i = 0; i < _columns.length; i++) { + String key = _columns[i].getName(); + values[i] = docValues.get(key); + } + + _hitIndex++; + + return values; + } + + private Object[] getRow(Map> facetMap) { + Set keys = facetMap.keySet(); + Object[] values = new Object[2]; + + for (String key : keys) { + List facetPairs = facetMap.get(key); + FacetField.Count facetPair = facetPairs.get(_hitIndex); + + long facetCount = facetPair.getCount(); + String nameValue = facetPair.getName(); + + values[0] = (Object) facetCount; + values[1] = (Object) nameValue; + } + + _hitIndex++; + + return values; + } + + @Override + public Row getRow() { + DataSetHeader dataSetHeader = super.getHeader(); + + Object[] values; + + if (_docListSize > 0) { + values = getRow(_docs); + } else { + values = getRow(_facetMap); + } + + final Row row = new DefaultRow(dataSetHeader, values); + return row; + } +} \ No newline at end of file diff --git a/solr/src/test/java/org/apache/metamodel/solr/SolrDataContextTest1.java b/solr/src/test/java/org/apache/metamodel/solr/SolrDataContextTest1.java new file mode 100644 index 000000000..5bcf57bdf --- /dev/null +++ b/solr/src/test/java/org/apache/metamodel/solr/SolrDataContextTest1.java @@ -0,0 +1,199 @@ +/** + * 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.solr; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.swing.table.TableModel; + +import org.apache.metamodel.DataContext; +import org.apache.metamodel.data.DataSet; +import org.apache.metamodel.data.DataSetTableModel; +import org.apache.metamodel.data.FilteredDataSet; +import org.apache.metamodel.data.InMemoryDataSet; +import org.apache.metamodel.data.Row; +import org.apache.metamodel.query.FunctionType; +import org.apache.metamodel.query.Query; +import org.apache.metamodel.query.SelectItem; +import org.apache.metamodel.schema.Column; +import org.apache.metamodel.schema.ColumnType; +import org.apache.metamodel.schema.Table; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class SolrDataContextTest1 { + private static final String url = "http://localhost:8983/solr/collection1"; + private static final String index = "collection1"; + + private static DataContext dataContext; + + @BeforeClass + public static void beforeTests() throws Exception { + DataContext dataContext = new SolrDataContext(url, index); + + } + + @AfterClass + public static void afterTests() { + System.out.println("Solr server shut down!"); + } + + @Test + public void testWhereWithLimit() throws Exception { + DataSet dataSet = dataContext + .executeQuery("SELECT * FROM collection1 WHERE (manu='maxtor' or manu='samsung') LIMIT 1"); + try { + assertTrue(dataSet.next()); + + Row row = dataSet.getRow(); + Object val = row.getValue(1); + + assertEquals("1491367446686203904", val.toString()); + } finally { + dataSet.close(); + } + } + + @Test + public void testGroupByQueryWithAlphaOrder() throws Exception { + List output = new ArrayList(); + + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) AS X, manu FROM collection1 WHERE (manu='maxtor' OR manu='samsung') GROUP BY manu ORDER BY manu LIMIT 3"); + + while (dataSet.next()) { + Row row = dataSet.getRow(); + output.add(row.toString()); + } + + assertEquals( + "[Row[values=[0, a]], Row[values=[0, america]], Row[values=[0, apache]]]", + output.toString()); + } + + @Test + public void testGroupByQueryWithMeasureOrder() throws Exception { + List output = new ArrayList(); + + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) AS X, manu FROM collection1 WHERE (manu='maxtor' OR manu='samsung') GROUP BY manu ORDER BY X DESC LIMIT 3"); + + while (dataSet.next()) { + Row row = dataSet.getRow(); + output.add(row.toString()); + } + + assertEquals( + "[Row[values=[1, corp]], Row[values=[1, maxtor]], Row[values=[0, a]]]", + output.toString()); + } + + @Test + public void testCountQuery() throws Exception { + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) FROM collection1"); + + try { + assertTrue(dataSet.next()); + assertEquals("Row[values=[32]]", dataSet.getRow().toString()); + } finally { + dataSet.close(); + } + } + + @Test + public void testCountWithWhereQuery() throws Exception { + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) FROM collection1 WHERE (manu='samsung' or manu='maxtor')"); + + try { + assertTrue(dataSet.next()); + assertEquals("Row[values=[3]]", dataSet.getRow().toString()); + } finally { + dataSet.close(); + } + } + + @Test + public void testGroupByQueryWithWrongMeasureOrder() throws Exception { + boolean isThrown = false; + + try { + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) AS X, manu FROM collection1 WHERE (manu='maxtor' OR manu='samsung') GROUP BY manu ORDER BY X LIMIT 3"); + List output = new ArrayList(); + + while (dataSet.next()) { + Row row = dataSet.getRow(); + } + } catch (Exception e) { + isThrown = true; + } finally { + + } + + assertTrue(isThrown); + } + + @Test + public void testGroupByQueryWithWrongAlphaOrder() throws Exception { + boolean isThrown = false; + + try { + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) AS X, manu FROM collection1 WHERE (manu='maxtor' OR manu='samsung') GROUP BY manu ORDER BY manu DESC LIMIT 3"); + List output = new ArrayList(); + + while (dataSet.next()) { + Row row = dataSet.getRow(); + } + } catch (Exception e) { + isThrown = true; + } finally { + + } + + assertTrue(isThrown); + } + + @Test + public void testQueryForANonExistingIndex() throws Exception { + boolean isThrown = false; + + try { + DataSet dataSet = dataContext + .executeQuery("SELECT COUNT(*) FROM foo"); + } catch (Exception e) { + isThrown = true; + } finally { + + } + + assertTrue(isThrown); + } +} \ No newline at end of file From 77cd4f2ab5eb1452bcc52d08f5768681c8b021f8 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sat, 18 Apr 2015 00:25:50 +0530 Subject: [PATCH 2/7] Additions for Solr connector --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 6c50c98bd..2a339a7dd 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,7 @@ under the License. xml jdbc elasticsearch + solr hbase cassandra mongodb From a25b5fc7352fd0829dfd45814f3803bfbc418d22 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sat, 18 Apr 2015 00:26:06 +0530 Subject: [PATCH 3/7] Dependency added for Solr connector --- full/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/full/pom.xml b/full/pom.xml index 1659364f8..8e940aa11 100644 --- a/full/pom.xml +++ b/full/pom.xml @@ -150,6 +150,11 @@ under the License. MetaModel-elasticsearch ${project.version} + + org.apache.metamodel + MetaModel-solr + ${project.version} + org.apache.metamodel MetaModel-cassandra From 85fe92faf6b95ac9a94566939f63afb4ddcd50fc Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sat, 18 Apr 2015 00:26:46 +0530 Subject: [PATCH 4/7] Lines added for Solr connector --- .../org/apache/metamodel/DataContextFactory.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/full/src/main/java/org/apache/metamodel/DataContextFactory.java b/full/src/main/java/org/apache/metamodel/DataContextFactory.java index c7f740996..48d7f4b44 100644 --- a/full/src/main/java/org/apache/metamodel/DataContextFactory.java +++ b/full/src/main/java/org/apache/metamodel/DataContextFactory.java @@ -28,6 +28,7 @@ import org.apache.metamodel.cassandra.CassandraDataContext; import org.apache.metamodel.elasticsearch.ElasticSearchDataContext; +import org.apache.metamodel.solr.SolrDataContext; import org.ektorp.http.StdHttpClient.Builder; import org.apache.metamodel.couchdb.CouchDbDataContext; import org.apache.metamodel.csv.CsvConfiguration; @@ -652,6 +653,18 @@ public static UpdateableDataContext createElasticSearchDataContext(Client client return new ElasticSearchDataContext(client, indexName); } + /** + * Creates a new Solr datacontext + * @param url + The Solr url + * @param indexName + The Solr index name + * @return a DataContext object that matches the request + */ + public static DataContext createSolrDataContext(String url, String indexName) { + return new SolrDataContext(url,indexName); + } + /** * Creates a new Cassandra datacontext. * @param cluster @@ -663,4 +676,4 @@ public static UpdateableDataContext createElasticSearchDataContext(Client client public static DataContext createCassandraDataContext(Cluster cluster, String keySpaceName) { return new CassandraDataContext(cluster, keySpaceName); } -} \ No newline at end of file +} From 02b62d42966fe373b3c9ac26bef8baa7bad2b630 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Tue, 21 Apr 2015 00:14:04 +0530 Subject: [PATCH 5/7] Formatting changes and fixes based on PR comments --- solr/.classpath | 24 ----------------------- solr/.project | 20 ------------------- solr/.settings/org.eclipse.jdt.core.prefs | 9 --------- 3 files changed, 53 deletions(-) delete mode 100644 solr/.classpath delete mode 100644 solr/.project delete mode 100644 solr/.settings/org.eclipse.jdt.core.prefs diff --git a/solr/.classpath b/solr/.classpath deleted file mode 100644 index 73d91c6ba..000000000 --- a/solr/.classpath +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/solr/.project b/solr/.project deleted file mode 100644 index 570783e44..000000000 --- a/solr/.project +++ /dev/null @@ -1,20 +0,0 @@ - - - MetaModel-solr - MetaModel is a library that encapsulates the differences and enhances - the capabilities of different datastores. Rich querying abilities are - offered to datastores that do not otherwise support advanced querying - and a unified view of the datastore structure is offered through a - single model of the schemas, tables, columns and relationships. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. - - MetaModel-core - - - - org.eclipse.jdt.core.javabuilder - - - - org.eclipse.jdt.core.javanature - - \ No newline at end of file diff --git a/solr/.settings/org.eclipse.jdt.core.prefs b/solr/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 28ddb0a96..000000000 --- a/solr/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -#Fri Jan 30 22:32:19 IST 2015 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -eclipse.preferences.version=1 -encoding/src/main/java=utf-8 -org.eclipse.jdt.core.compiler.source=1.6 -encoding/src/test/resources=utf-8 -encoding/src/main/resources=utf-8 -encoding/src/test/java=utf-8 -org.eclipse.jdt.core.compiler.compliance=1.6 From 0ac41ae258cf33d4a7a937238b0fa157eaf64640 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sun, 26 Apr 2015 22:15:46 +0530 Subject: [PATCH 6/7] Simplified code for filter handling --- .../metamodel/solr/SolrDataContext.java | 640 +++++++++--------- 1 file changed, 307 insertions(+), 333 deletions(-) diff --git a/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java b/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java index 95b537c07..54329ee52 100644 --- a/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java +++ b/solr/src/main/java/org/apache/metamodel/solr/SolrDataContext.java @@ -90,340 +90,314 @@ */ public class SolrDataContext extends QueryPostprocessDataContext implements - DataContext { + DataContext { - private static final Logger logger = LoggerFactory - .getLogger(SolrDataContext.class); - - public static final String FIELD_ID = "_id"; + private static final Logger logger = LoggerFactory + .getLogger(SolrDataContext.class); - private final SimpleTableDef tableDef; - private final String indexName; - private final String url; + public static final String FIELD_ID = "id"; - private SolrQuery query = new SolrQuery(); - - private static enum queryTypes { - ROW, FACET - }; - - private static final int MAX_RETRIES = 0; - private static final int SOCK_TIMEOUT = 1000; - private static final int CONN_TIMEOUT = 5000; - private static final int DEFAULT_LIMIT = 1000; - - public SolrDataContext(String url, String indexName) { - this.url = url; - this.indexName = indexName; - this.tableDef = detectSchema(url, indexName); - } - - private SimpleTableDef detectSchema(String url, String indexName) { - SimpleTableDef tableDef = null; - - url += "/schema"; - - try { - HttpClient httpclient = new DefaultHttpClient(); - HttpGet request = new HttpGet(url); - HttpResponse response = httpclient.execute(request); - - InputStreamReader inputStream = new InputStreamReader(response - .getEntity().getContent()); - - ObjectReader reader = new ObjectMapper().reader(HashMap.class); - Map outerMap = reader.readValue(inputStream); - - Map schemaMap = (Map) outerMap.get("schema"); - - if (outerMap != null) { - List> fieldMapList = (List) schemaMap - .get("fields"); - List columnNames = new ArrayList(); - List columnTypes = new ArrayList(); - - for (int i = 0; i < fieldMapList.size(); i++) { - Map fieldMap = fieldMapList.get(i); - - columnNames.add(fieldMap.get("name")); - columnTypes.add(ColumnType.VARCHAR); - } - - String[] columnNamesArr = new String[columnNames.size()]; - columnNamesArr = columnNames.toArray(columnNamesArr); - - ColumnType[] columnTypesArr = new ColumnType[columnTypes.size()]; - columnTypesArr = columnTypes.toArray(columnTypesArr); - - tableDef = new SimpleTableDef(indexName, columnNamesArr, - columnTypesArr); - } - } catch (IOException e) { - logger.error("Failed to parse schema", "", e); - } - - return tableDef; - } - - @Override - protected Schema getMainSchema() throws MetaModelException { - try { - final MutableSchema theSchema = new MutableSchema( - getMainSchemaName()); - - final MutableTable table = tableDef.toTable().setSchema(theSchema); - final Column idColumn = table.getColumnByName(FIELD_ID); - if (idColumn != null && idColumn instanceof MutableColumn) { - final MutableColumn mutableColumn = (MutableColumn) idColumn; - mutableColumn.setPrimaryKey(true); - } - theSchema.addTable(table); - - return theSchema; - } catch (Exception e) { - throw new MetaModelException("Schema retrieval failed " + e); - } - } - - @Override - protected Number executeCountQuery(Table table, - List whereItems, boolean functionApproximationAllowed) { - String queryStr = "*:*"; - - if (whereItems != null) { - for (int i = 0; i < whereItems.size(); i++) { - FilterItem whereItem = whereItems.get(i); - queryStr = whereItem.toString(); - } - } - - QueryResponse response = selectRows(table, null, queryStr, 0, 0); - return response.getResults().getNumFound(); - } - - private String processSingleFilterItem(FilterItem filterItem) { - String clause = ""; - - if (filterItem != null) { - SelectItem item = filterItem.getSelectItem(); - OperatorType operator = filterItem.getOperator(); - Object operand = filterItem.getOperand(); - - if (item == null || operator == null || operand == null) { - clause = " " + filterItem.getExpression(); - } else { - String columnName = item.getColumn().getName(); - clause = " " + columnName + operator.toSql() + operand; - } - } - - return clause; - } - - private String createSearchClause(FilterItem filterItem, String clause) { - FilterItem[] filterItems = filterItem.getChildItems(); - - if (filterItems != null && filterItems.length > 0) { - for (FilterItem filterItemInner : filterItems) { - if (filterItemInner != null) { - clause += " " + processSingleFilterItem(filterItemInner); - } - - return createSearchClause(filterItemInner, clause); - } - } - - if (filterItem != null) { - clause += " " + processSingleFilterItem(filterItem); - } - - return clause; - } - - @Override - public DataSet executeQuery(Query q) throws MetaModelException { - String queryStr = ""; - QueryResponse response = null; - - Schema schema = getMainSchema(); - Table table = schema.getTable(0); - Column[] columns = table.getColumns(); - - boolean selectAll = true; - List selectItems = q.getSelectClause().getItems(); - - for (SelectItem selectItem : selectItems) { - if (selectItem.getFunction() != null - || selectItem.getColumn() == null) { - selectAll = false; - break; - } - } - - if (selectItems.size() == 1 && selectAll == false) { - return super.executeQuery(q); - } - - FilterClause clause = q.getWhereClause(); - - String searchClause = ""; - - if (clause != null) { - List filterItemList = clause.getItems(); - - for (FilterItem filterItem : filterItemList) { - searchClause += " " - + createSearchClause(filterItem, searchClause); - } - - queryStr = searchClause; - } - - if (queryStr.isEmpty()) { - queryStr = "*:*"; - } - - Integer limitObject = q.getMaxRows(); - int limit = DEFAULT_LIMIT; - - if (limitObject != null) { - limit = (int) limitObject; - } - - final List groupByItems = q.getGroupByClause().getItems(); - - if (groupByItems.size() > 0) { - query.clear(); - query.setQuery(queryStr); - query.setFacet(true); - - for (int i = 0; i < groupByItems.size(); i++) { - String facetField = groupByItems.get(i).getSelectItem() - .getColumn().getName(); - query.addFacetField(facetField); - } - - setOrder(q, query, queryTypes.FACET); - - query.setFacetLimit(limit); - - try { - HttpSolrServer server = initSolrServer(); - response = server.query(query); - } catch (SolrServerException e) { - logger.error("Server initialization failed", "", e); - throw new MetaModelException("Server initialization failed " - + e); - } - - List facetFieldsList = response.getFacetFields(); - - String facetFieldName = facetFieldsList.get(0).getName(); - - Column[] facetColumns = { new MutableColumn("count"), - new MutableColumn(facetFieldName) }; - - return new SolrDataSet(facetFieldsList, facetColumns); - } else if (selectAll) { - response = selectRows(table, q, queryStr, 0, limit); - SolrDocumentList results = response.getResults(); - - return new SolrDataSet(results, columns); - } - - return super.executeQuery(q); - } - - @Override - protected DataSet materializeMainSchemaTable(Table table, Column[] columns, - int maxRows) { - QueryResponse response = selectRows(table, null, "*:*", 0, maxRows); - return new SolrDataSet(response.getResults(), columns); - } - - @Override - protected DataSet materializeMainSchemaTable(Table table, Column[] columns, - int offset, int num) { - QueryResponse response = selectRows(table, null, "*:*", offset, num); - return new SolrDataSet(response.getResults(), columns); - } - - private void setOrder(Query q, SolrQuery query, queryTypes qtype) { - List orderByList = q.getOrderByClause().getItems(); - - for (OrderByItem orderItem : orderByList) { - SelectItem orderFieldOrFunc = orderItem.getSelectItem(); - Column orderColumn = orderFieldOrFunc.getColumn(); - FunctionType orderFunc = orderFieldOrFunc.getFunction(); - - String orderField = null; - String direction = orderItem.getDirection().toString(); - - if (orderColumn != null) { - orderField = orderColumn.getName(); - - if (direction == null || direction.equalsIgnoreCase("ASC")) { - query.addSort(orderField, SolrQuery.ORDER.asc); - } else { - query.addSort(orderField, SolrQuery.ORDER.desc); - } - } - - if (qtype == queryTypes.FACET) { - if (orderColumn == null) { - if (direction.equalsIgnoreCase("ASC")) { - throw new UnsupportedOperationException( - "Ascending sort on count unsupported"); - } - query.setFacetSort("count"); - } else { - if (direction.equalsIgnoreCase("DESC")) { - throw new UnsupportedOperationException( - "Descending sort on facet unsupported"); - } - query.setFacetSort("index"); - } - } - } - } - - private HttpSolrServer initSolrServer() { - HttpSolrServer server = new HttpSolrServer(url); - server.setMaxRetries(MAX_RETRIES); - server.setSoTimeout(SOCK_TIMEOUT); - server.setConnectionTimeout(CONN_TIMEOUT); - server.setFollowRedirects(false); - - return server; - } - - private QueryResponse selectRows(Table table, Query q, String queryStr, - int offset, int num) { - HttpSolrServer server = initSolrServer(); - - query.clear(); - query.setQuery(queryStr); - query.setStart(offset); - query.setRows(num); - - if (q != null) { - setOrder(q, query, queryTypes.ROW); - } - - QueryResponse response = null; - - try { - response = server.query(query); - } catch (SolrServerException e) { - logger.error("Search query for documents failed", "", e); - throw new MetaModelException("Query failed " + e); - } - - return response; - } - - @Override - protected String getMainSchemaName() throws MetaModelException { - return indexName; - } + private final SimpleTableDef tableDef; + private final String indexName; + private final String url; + + private SolrQuery query = new SolrQuery(); + + private static enum queryTypes { + ROW, FACET + }; + + private static final int MAX_RETRIES = 0; + private static final int SOCK_TIMEOUT = 1000; + private static final int CONN_TIMEOUT = 5000; + private static final int DEFAULT_LIMIT = 1000; + + public SolrDataContext(String url, String indexName) { + this.url = url; + this.indexName = indexName; + this.tableDef = detectSchema(url, indexName); + } + + private SimpleTableDef detectSchema(String url, String indexName) { + SimpleTableDef tableDef = null; + + url += "/schema"; + + try { + HttpClient httpclient = new DefaultHttpClient(); + HttpGet request = new HttpGet(url); + HttpResponse response = httpclient.execute(request); + + InputStreamReader inputStream = new InputStreamReader(response + .getEntity().getContent()); + + ObjectReader reader = new ObjectMapper().reader(HashMap.class); + Map outerMap = reader.readValue(inputStream); + + Map schemaMap = null; + + if (outerMap != null) { + schemaMap = (Map) outerMap.get("schema"); + } + + if (schemaMap != null) { + List> fieldMapList = (List) schemaMap + .get("fields"); + List columnNames = new ArrayList(); + List columnTypes = new ArrayList(); + + for (int i = 0; i < fieldMapList.size(); i++) { + Map fieldMap = fieldMapList.get(i); + + columnNames.add(fieldMap.get("name")); + columnTypes.add(ColumnType.STRING); + } + + String[] columnNamesArr = new String[columnNames.size()]; + columnNamesArr = columnNames.toArray(columnNamesArr); + + ColumnType[] columnTypesArr = new ColumnType[columnTypes.size()]; + columnTypesArr = columnTypes.toArray(columnTypesArr); + + tableDef = new SimpleTableDef(indexName, columnNamesArr, + columnTypesArr); + } + } catch (IOException e) { + logger.error("Failed to parse schema", "", e); + } + + return tableDef; + } + + @Override + protected Schema getMainSchema() throws MetaModelException { + try { + final MutableSchema theSchema = new MutableSchema( + getMainSchemaName()); + + final MutableTable table = tableDef.toTable().setSchema(theSchema); + final Column idColumn = table.getColumnByName(FIELD_ID); + if (idColumn != null && idColumn instanceof MutableColumn) { + final MutableColumn mutableColumn = (MutableColumn) idColumn; + mutableColumn.setPrimaryKey(true); + } + theSchema.addTable(table); + + return theSchema; + } catch (Exception e) { + throw new MetaModelException("Schema retrieval failed " + e); + } + } + + @Override + protected Number executeCountQuery(Table table, + List whereItems, boolean functionApproximationAllowed) { + String queryStr = "*:*"; + + if (whereItems != null) { + for (int i = 0; i < whereItems.size(); i++) { + FilterItem whereItem = whereItems.get(i); + queryStr = whereItem.toString(); + } + } + + QueryResponse response = selectRows(table, null, queryStr, 0, 0); + return response.getResults().getNumFound(); + } + + @Override + public DataSet executeQuery(Query q) throws MetaModelException { + String queryStr = ""; + QueryResponse response = null; + + Schema schema = getMainSchema(); + Table table = schema.getTable(0); + Column[] columns = table.getColumns(); + + boolean selectAll = true; + List selectItems = q.getSelectClause().getItems(); + + for (SelectItem selectItem : selectItems) { + if (selectItem.getFunction() != null + || selectItem.getColumn() == null) { + selectAll = false; + break; + } + } + + if (selectItems.size() == 1 && selectAll == false) { + return super.executeQuery(q); + } + + FilterClause clause = q.getWhereClause(); + + if (clause != null) { + List filterItemList = clause.getItems(); + + boolean isFirst = true; + + for (FilterItem filterItem : filterItemList) { + String expr = filterItem.getExpression(); + + if (expr == null){ + expr = filterItem.toString(); + expr = expr.replaceAll("[a-z_0-9]+\\.",""); + } + + expr = expr.replace(" or ", " OR ").replace(" and ", " AND ").replaceAll("=",":"); + + String joiner = (isFirst == true) ? " " : " AND "; + queryStr += joiner + expr; + + isFirst = false; + } + } + + if (queryStr.isEmpty()) { + queryStr = "*:*"; + } + + Integer limitObject = q.getMaxRows(); + int limit = DEFAULT_LIMIT; + + if (limitObject != null) { + limit = (int) limitObject; + } + + final List groupByItems = q.getGroupByClause().getItems(); + + if (groupByItems.size() > 0) { + query.clear(); + query.setQuery(queryStr); + query.setFacet(true); + + for (int i = 0; i < groupByItems.size(); i++) { + String facetField = groupByItems.get(i).getSelectItem() + .getColumn().getName(); + query.addFacetField(facetField); + } + + setOrder(q, query, queryTypes.FACET); + + query.setFacetLimit(limit); + + try { + HttpSolrServer server = initSolrServer(); + response = server.query(query); + } catch (SolrServerException e) { + logger.error("Server initialization failed", "", e); + throw new MetaModelException("Server initialization failed " + + e); + } + + List facetFieldsList = response.getFacetFields(); + + String facetFieldName = facetFieldsList.get(0).getName(); + + Column[] facetColumns = { new MutableColumn("count"), + new MutableColumn(facetFieldName) }; + + return new SolrDataSet(facetFieldsList, facetColumns); + } else if (selectAll) { + response = selectRows(table, q, queryStr, 0, limit); + SolrDocumentList results = response.getResults(); + + return new SolrDataSet(results, columns); + } + + return super.executeQuery(q); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, + int maxRows) { + QueryResponse response = selectRows(table, null, "*:*", 0, maxRows); + return new SolrDataSet(response.getResults(), columns); + } + + @Override + protected DataSet materializeMainSchemaTable(Table table, Column[] columns, + int offset, int num) { + QueryResponse response = selectRows(table, null, "*:*", offset, num); + return new SolrDataSet(response.getResults(), columns); + } + + private void setOrder(Query q, SolrQuery query, queryTypes qtype) { + List orderByList = q.getOrderByClause().getItems(); + + for (OrderByItem orderItem : orderByList) { + SelectItem orderFieldOrFunc = orderItem.getSelectItem(); + Column orderColumn = orderFieldOrFunc.getColumn(); + FunctionType orderFunc = orderFieldOrFunc.getFunction(); + + String orderField = null; + String direction = orderItem.getDirection().toString(); + + if (orderColumn != null) { + orderField = orderColumn.getName(); + + if (direction == null || direction.equalsIgnoreCase("ASC")) { + query.addSort(orderField, SolrQuery.ORDER.asc); + } else { + query.addSort(orderField, SolrQuery.ORDER.desc); + } + } + + if (qtype == queryTypes.FACET) { + if (orderColumn == null) { + if (direction.equalsIgnoreCase("ASC")) { + throw new UnsupportedOperationException( + "Ascending sort on count unsupported"); + } + query.setFacetSort("count"); + } else { + if (direction.equalsIgnoreCase("DESC")) { + throw new UnsupportedOperationException( + "Descending sort on facet unsupported"); + } + query.setFacetSort("index"); + } + } + } + } + + private HttpSolrServer initSolrServer() { + HttpSolrServer server = new HttpSolrServer(url); + server.setMaxRetries(MAX_RETRIES); + server.setSoTimeout(SOCK_TIMEOUT); + server.setConnectionTimeout(CONN_TIMEOUT); + server.setFollowRedirects(false); + + return server; + } + + private QueryResponse selectRows(Table table, Query q, String queryStr, + int offset, int num) { + HttpSolrServer server = initSolrServer(); + + query.clear(); + query.setQuery(queryStr); + query.setStart(offset); + query.setRows(num); + + if (q != null) { + setOrder(q, query, queryTypes.ROW); + } + + QueryResponse response = null; + + try { + response = server.query(query); + } catch (SolrServerException e) { + logger.error("Search query for documents failed", "", e); + throw new MetaModelException("Query failed " + e); + } + + return response; + } + + @Override + protected String getMainSchemaName() throws MetaModelException { + return indexName; + } } \ No newline at end of file From 024087dc6189335be385a9578b2b0e8b29a8cd92 Mon Sep 17 00:00:00 2001 From: Ashish Mukherjee Date: Sun, 26 Apr 2015 22:17:52 +0530 Subject: [PATCH 7/7] Indentation fixes --- full/pom.xml | 8 ++++---- .../java/org/apache/metamodel/DataContextFactory.java | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/full/pom.xml b/full/pom.xml index 8e940aa11..44de7d7c7 100644 --- a/full/pom.xml +++ b/full/pom.xml @@ -151,10 +151,10 @@ under the License. ${project.version} - org.apache.metamodel - MetaModel-solr - ${project.version} - + org.apache.metamodel + MetaModel-solr + ${project.version} + org.apache.metamodel MetaModel-cassandra diff --git a/full/src/main/java/org/apache/metamodel/DataContextFactory.java b/full/src/main/java/org/apache/metamodel/DataContextFactory.java index 48d7f4b44..d6f9e6c16 100644 --- a/full/src/main/java/org/apache/metamodel/DataContextFactory.java +++ b/full/src/main/java/org/apache/metamodel/DataContextFactory.java @@ -653,8 +653,8 @@ public static UpdateableDataContext createElasticSearchDataContext(Client client return new ElasticSearchDataContext(client, indexName); } - /** - * Creates a new Solr datacontext + /** + * Creates a new ElasticSearch datacontext. * @param url The Solr url * @param indexName