Github user kaspersorensen commented on a diff in the pull request:

    https://github.com/apache/incubator-metamodel/pull/2#discussion_r18351203
  
    --- Diff: 
cassandra/src/main/java/org/apache/metamodel/cassandra/CassandraDataContext.java
 ---
    @@ -0,0 +1,205 @@
    +/**
    + * 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.cassandra;
    +
    +import com.datastax.driver.core.*;
    +import com.datastax.driver.core.querybuilder.QueryBuilder;
    +import com.datastax.driver.core.querybuilder.Select;
    +
    +import org.apache.metamodel.DataContext;
    +import org.apache.metamodel.MetaModelException;
    +import org.apache.metamodel.QueryPostprocessDataContext;
    +import org.apache.metamodel.data.DataSet;
    +import org.apache.metamodel.query.FilterItem;
    +import org.apache.metamodel.schema.*;
    +import org.apache.metamodel.util.SimpleTableDef;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +
    +import java.util.Collection;
    +import java.util.Iterator;
    +import java.util.List;
    +
    +/**
    + * DataContext implementation for Apache Cassandra  database.
    + *
    + * When instantiating this DataContext, a keyspace name is provided. In 
Cassandra,
    + * the keyspace is the container for your application data, similar to a 
schema in
    + * a relational database. Keyspaces are used to group column families 
together.
    + * 
    + * This implementation supports either automatic discovery of a schema or 
manual
    + * specification of a schema, through the {@link SimpleTableDef} class.
    + *
    + * @author Alberto Rodriguez
    + */
    +public class CassandraDataContext extends QueryPostprocessDataContext 
implements DataContext {
    +
    +    private static final Logger logger = 
LoggerFactory.getLogger(CassandraDataContext.class);
    +
    +    private final Cluster cassandraCluster;
    +    private final SimpleTableDef[] tableDefs;
    +    private final String keySpaceName;
    +
    +    /**
    +     * Constructs a {@link CassandraDataContext}. This constructor accepts 
a
    +     * custom array of {@link SimpleTableDef}s which allows the user to 
define
    +     * his own view on the indexes in the engine.
    +     *
    +     * @param cluster
    +     *            the Cassandra cluster
    +     * @param keySpace
    +     *            the name of the Cassandra keyspace
    +     * @param tableDefs
    +     *            an array of {@link SimpleTableDef}s, which define the 
table
    +     *            and column model of the ElasticSearch index.
    +     */
    +    public CassandraDataContext(Cluster cluster, String keySpace, 
SimpleTableDef... tableDefs) {
    +        this.cassandraCluster = cluster;
    +        this.keySpaceName = keySpace;
    +        this.tableDefs = tableDefs;
    +    }
    +
    +    /**
    +     * Constructs a {@link CassandraDataContext} and automatically detects
    +     * the schema structure/view on the keyspace (see
    +     * {@link #detectSchema(Cluster, String)}).
    +     *
    +     * @param cluster
    +     *            the Cassandra cluster
    +     * @param keySpace
    +     *            the name of the Cassandra keyspace to represent
    +     */
    +    public CassandraDataContext(Cluster cluster, String keySpace) {
    +        this(cluster, keySpace, detectSchema(cluster, keySpace));
    +    }
    +
    +    /**
    +     * Performs an analysis of the given keyspace in a Cassandra cluster
    +     * {@link Cluster} instance and detects the cassandra types structure
    +     * based on the metadata provided by the datastax cassandra java 
client.
    +     *
    +     * @see #detectTable(TableMetadata)
    +     *
    +     * @param cluster
    +     *            the cluster to inspect
    +     * @param keyspaceName
    +     * @return a mutable schema instance, useful for further fine tuning 
by the
    +     *         user.
    +     */
    +    public static SimpleTableDef[] detectSchema(Cluster cluster, String 
keyspaceName) {
    +        Metadata metadata = cluster.getMetadata();
    +        KeyspaceMetadata keyspace = metadata.getKeyspace(keyspaceName);
    +        Collection<TableMetadata> tables = keyspace.getTables();
    +        SimpleTableDef[] result = new SimpleTableDef[tables.size()];
    +        int i = 0;
    +        for (TableMetadata tableMetaData : tables) {
    +            SimpleTableDef table = detectTable(tableMetaData);
    +            result[i] = table;
    +            i++;
    +        }
    +        return result;
    +    }
    +
    +    /**
    +     * Performs an analysis of an available table in Cassandra.
    +     *
    +     * @param tableMetaData
    +     *            the table meta data
    +     * @return a table definition for cassandra.
    +     */
    +    public static SimpleTableDef detectTable(TableMetadata tableMetaData) {
    +        List<ColumnMetadata> columns = tableMetaData.getColumns();
    +        final String[] columnNames = new String[columns.size()];
    +        final ColumnType[] columnTypes = new ColumnType[columns.size()];
    +        int i = 0;
    +        for (ColumnMetadata column: columns) {
    +            columnNames[i] = column.getName();
    +            columnTypes[i] = 
getColumnTypeFromMetaDataField(column.getType().getName());
    +            i++;
    +        }
    +
    +        return new SimpleTableDef(tableMetaData.getName(), columnNames, 
columnTypes);
    +    }
    +
    +    @Override
    +    protected Schema getMainSchema() throws MetaModelException {
    +        final MutableSchema theSchema = new 
MutableSchema(getMainSchemaName());
    +        for (final SimpleTableDef tableDef : tableDefs) {
    +            final MutableTable table = 
tableDef.toTable().setSchema(theSchema);
    +            theSchema.addTable(table);
    +        }
    +        return theSchema;
    +    }
    +
    +
    +    @Override
    +    protected String getMainSchemaName() throws MetaModelException {
    +        return keySpaceName;
    +    }
    +
    +    @Override
    +    protected DataSet materializeMainSchemaTable(Table table, Column[] 
columns, int maxRows) {
    +        Select query = QueryBuilder.select().all().from(keySpaceName, 
table.getName());
    +        if (limitMaxRowsIsSet(maxRows)) {
    +            query.limit(maxRows);
    +        }
    +        final Iterator<Row> response = 
cassandraCluster.connect().execute(query).iterator();
    +        return new CassandraDataSet(response, columns, false);
    +    }
    +
    +    private boolean limitMaxRowsIsSet(int maxRows) {
    +        return (maxRows != -1);
    +    }
    +
    +
    +    @Override
    +    protected Number executeCountQuery(Table table, List<FilterItem> 
whereItems, boolean functionApproximationAllowed) {
    +        if (!whereItems.isEmpty()) {
    +            // not supported - will have to be done by counting client-side
    +            return null;
    +        }
    +        Statement statement = 
QueryBuilder.select().countAll().from(keySpaceName, table.getName());
    +        final Row response = 
cassandraCluster.connect().execute(statement).one();
    +        return response.getLong(0);
    +    }
    +
    +
    +    private static ColumnType getColumnTypeFromMetaDataField(DataType.Name 
metaDataName) {
    +        switch (metaDataName) {
    +            case BIGINT: return ColumnType.BIGINT;
    +            case BLOB: return ColumnType.BLOB;
    +            case BOOLEAN: return ColumnType.BOOLEAN;
    +            case DECIMAL: return ColumnType.DECIMAL;
    +            case DOUBLE: return ColumnType.DOUBLE;
    +            case FLOAT: return ColumnType.FLOAT;
    +            case INT: return ColumnType.INTEGER;
    +            case TEXT: return ColumnType.STRING;
    +            case TIMESTAMP: return ColumnType.TIMESTAMP;
    +            case UUID: return ColumnType.STRING;
    --- End diff --
    
    This line is what I am referring to in the previous comment.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---

Reply via email to