Example usage for org.apache.cassandra.cql3 QueryProcessor process

List of usage examples for org.apache.cassandra.cql3 QueryProcessor process

Introduction

In this page you can find the example usage for org.apache.cassandra.cql3 QueryProcessor process.

Prototype

public static UntypedResultSet process(String query, ConsistencyLevel cl) throws RequestExecutionException 

Source Link

Usage

From source file:com.protectwise.cassandra.retrospect.deletion.RuleBasedDeletionConvictor.java

License:Apache License

/**
 * Keyed by rulename, then by column name, then contains a list of 2-element arrays of ranges for that column.
 * This is not typed, everything is byte buffers, type is collapsed at testing time.
 *
 * @param statement/*from   ww  w .j  a v  a 2s.  co m*/
 * @return
 * @throws ConfigurationException
 */
public static Map<ByteBuffer, Map<ByteBuffer, List<ByteBuffer[]>>> parseRules(String statement)
        throws ConfigurationException {
    UntypedResultSet rawRuleData = null;
    try {
        if (!QueryHelper.hasStartedCQL()) {
            // Yuck, exceptions for control flow.  This will be caught upstream during compaction as a signal that
            // we should move to spooked mode.  Outside of compaction the exception will bubble up and be presented
            // to the user (though it seems extremely unlikely)
            throw new ConfigurationException(
                    "Node is not fully joined, so we cannot read deletion rules.  Falling back to standard compaction");
        }
        rawRuleData = QueryProcessor.process(statement, ConsistencyLevel.LOCAL_QUORUM);
    } catch (RequestExecutionException e) {
        ConfigurationException ce = new ConfigurationException(
                "Unable to query for rule data.  The failed statement was " + statement, e);
        throw ce;
    }

    Map<String, ColumnSpecification> cols = new HashMap<>();
    for (ColumnSpecification cs : rawRuleData.metadata()) {
        cols.put(cs.name.toString(), cs);
    }

    if (!cols.containsKey("column") || !cols.containsKey("rulename") || !cols.containsKey("range")) {
        throw new ConfigurationException(
                "The select statement must return the columns 'column', 'rulename', and 'range'");
    }

    CQL3Type columnType = cols.get("column").type.asCQL3Type();
    if (!columnType.equals(CQL3Type.Native.TEXT)) {
        throw new ConfigurationException(
                "The 'column' column must be a text type.  Found " + columnType.toString());
    }

    //  Validate that "range" is of type tuple<text,text>, ugh.
    CQL3Type rangeType = cols.get("range").type.asCQL3Type();
    if (!(rangeType instanceof CQL3Type.Tuple)) {
        throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found "
                + cols.get("column").type.getSerializer().getType());
    }
    List<AbstractType<?>> subtypes = ((TupleType) ((CQL3Type.Tuple) rangeType).getType()).allTypes();
    if (subtypes.size() != 2) {
        throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found "
                + cols.get("column").type.getSerializer().getType());
    }
    for (AbstractType<?> t : subtypes) {
        if (!t.asCQL3Type().equals(CQL3Type.Native.TEXT)) {
            throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found "
                    + cols.get("column").type.getSerializer().getType());
        }
    }

    Iterator<UntypedResultSet.Row> resultIterator = rawRuleData.iterator();

    Map<ByteBuffer, Map<ByteBuffer, List<ByteBuffer[]>>> rules = new HashMap<>();
    while (resultIterator.hasNext()) {
        UntypedResultSet.Row row = resultIterator.next();
        ByteBuffer rulename = row.getBlob("rulename");
        Map<ByteBuffer, List<ByteBuffer[]>> rule;
        if (!rules.containsKey(rulename)) {
            rule = new HashMap<>();
            rules.put(rulename, rule);
        } else {
            rule = rules.get(rulename);
        }

        ByteBuffer column = row.getBlob("column");
        List<ByteBuffer[]> ranges;
        if (rule.containsKey(column)) {
            ranges = rule.get(column);
        } else {
            ranges = new ArrayList<>();
            rule.put(column, ranges);
        }
        ByteBuffer[] rawRange = ((TupleType) rangeType.getType()).split(row.getBlob("range"));
        ranges.add(rawRange);
        if (logger.isDebugEnabled()) {
            logger.debug("Rule {} on column {} is range {} to {} (now {} ranges on this column)",
                    PrintHelper.bufToString(rulename), PrintHelper.bufToString(column),
                    PrintHelper.bufToString(rawRange[0]), PrintHelper.bufToString(rawRange[1]), ranges.size());
        }
    }

    return rules;
}

From source file:com.protectwise.cassandra.retrospect.deletion.RuleBasedLateTTLConvictor.java

License:Apache License

/**
 * Keyed by rulename, then by column name, then contains a list of 2-element arrays of ranges for that column.
 * This is not typed, everything is byte buffers, type is collapsed at testing time.
 *
 * @param statement//w w w .j  av a2  s  . c  om
 * @return
 * @throws ConfigurationException
 */
public static Map<ByteBuffer, Pair<Map<ByteBuffer, List<ByteBuffer[]>>, Long>> parseRules(String statement)
        throws ConfigurationException {
    UntypedResultSet rawRuleData = null;
    try {
        if (!QueryHelper.hasStartedCQL()) {
            // Yuck, exceptions for control flow.  This will be caught upstream during compaction as a signal that
            // we should move to spooked mode.  Outside of compaction the exception will bubble up and be presented
            // to the user (though it seems extremely unlikely)
            throw new ConfigurationException(
                    "Node is not fully joined, so we cannot read deletion rules.  Falling back to standard compaction");
        }
        rawRuleData = QueryProcessor.process(statement, ConsistencyLevel.LOCAL_QUORUM);
    } catch (RequestExecutionException e) {
        ConfigurationException ce = new ConfigurationException(
                "Unable to query for rule data, the failed statement was " + statement, e);
        throw ce;
    }

    Map<String, ColumnSpecification> cols = new HashMap<>();
    for (ColumnSpecification cs : rawRuleData.metadata()) {
        cols.put(cs.name.toString(), cs);
    }

    if (!cols.containsKey("column") || !cols.containsKey("rulename") || !cols.containsKey("range_lower")
            || !cols.containsKey("range_upper") || !cols.containsKey("ttl")) {
        throw new ConfigurationException(
                "The select statement must return the columns 'column', 'rulename', 'range', and 'ttl'");
    }

    CQL3Type columnType = cols.get("column").type.asCQL3Type();
    if (!columnType.equals(CQL3Type.Native.TEXT)) {
        throw new ConfigurationException(
                "The 'column' column must be a text type.  Found " + columnType.toString());
    }

    //  Validate that "range" is of type tuple<text,text>, ugh.
    /*CQL3Type rangeType = cols.get("range").type.asCQL3Type();
    if (!(rangeType instanceof CQL3Type.Tuple))
    {
       throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found " + cols.get("column").type.getSerializer().getType());
    }
    List<AbstractType<?>> subtypes = ((TupleType) ((CQL3Type.Tuple) rangeType).getType()).allTypes();
    if (subtypes.size() != 2)
    {
       throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found " + cols.get("column").type.getSerializer().getType());
    }
    for (AbstractType<?> t : subtypes)
    {
       if (!t.asCQL3Type().equals(CQL3Type.Native.TEXT))
       {
    throw new ConfigurationException("The column 'range' must be of type tuple<text,text>  Found " + cols.get("column").type.getSerializer().getType());
       }
    }*/

    // validate that range, range_lower, range_upper
    CQL3Type rangeLowerType = cols.get("range_lower").type.asCQL3Type();
    if (!rangeLowerType.equals(CQL3Type.Native.TEXT)) {
        throw new ConfigurationException("The column 'range_lower' must be of type text  Found "
                + cols.get("range_lower").type.getSerializer().getType());
    }

    CQL3Type rangeUpperType = cols.get("range_upper").type.asCQL3Type();
    if (!rangeLowerType.equals(CQL3Type.Native.TEXT)) {
        throw new ConfigurationException("The column 'range' must be of type map<text,text>  Found "
                + cols.get("range_upper").type.getSerializer().getType());
    }

    // Validate that 'ttl' is of type bigint
    CQL3Type ttlType = cols.get("ttl").type.asCQL3Type();
    if (!ttlType.equals(CQL3Type.Native.BIGINT)) {
        throw new ConfigurationException(
                "The 'ttl' column must be a bigint type.  Found " + ttlType.toString());
    }

    Iterator<UntypedResultSet.Row> resultIterator = rawRuleData.iterator();

    Map<ByteBuffer, Pair<Map<ByteBuffer, List<ByteBuffer[]>>, Long>> rules = new HashMap<>();
    while (resultIterator.hasNext()) {
        UntypedResultSet.Row row = resultIterator.next();
        ByteBuffer rulename = row.getBlob("rulename");
        Map<ByteBuffer, List<ByteBuffer[]>> rule;
        Long ttl = row.getLong("ttl");
        if (!rules.containsKey(rulename)) {
            rule = new HashMap<>();
            rules.put(rulename, Pair.create(rule, ttl));
        } else {
            Pair<Map<ByteBuffer, List<ByteBuffer[]>>, Long> p = rules.get(rulename);
            if (!p.right.equals(ttl)) {
                throw new ConfigurationException("The 'ttl' value for rule " + PrintHelper.bufToString(rulename)
                        + " has inconsistent values between the columns and ranges of this rule.  The value of the TTL must be consistent for the entire rule.");
            }
            rule = p.left;
        }

        ByteBuffer column = row.getBlob("column");
        List<ByteBuffer[]> ranges;
        if (rule.containsKey(column)) {
            ranges = rule.get(column);
        } else {
            ranges = new ArrayList<>();
            rule.put(column, ranges);
        }
        ByteBuffer[] rawRange = new ByteBuffer[2];
        rawRange[0] = row.getBlob("range_lower");
        rawRange[1] = row.getBlob("range_upper");
        ranges.add(rawRange);
        if (logger.isDebugEnabled()) {
            logger.debug("Rule {} on column {} is range {} to {} (now {} ranges on this column)",
                    PrintHelper.bufToString(rulename), PrintHelper.bufToString(column),
                    PrintHelper.bufToString(rawRange[0]), PrintHelper.bufToString(rawRange[1]), ranges.size());
        }
    }

    return rules;
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

/**
 * Don't use QueryProcessor.executeInternal, we need to propagate this on
 * all nodes.//from  w  w w  .  j a v  a 2  s. c om
 * 
 * @see org.elasticsearch.cassandra.ElasticSchemaService#createIndexKeyspace(java.lang.String,
 *      int)
 **/
@Override
public void createIndexKeyspace(final String ksname, final int replicationFactor) throws IOException {
    try {
        Keyspace ks = Keyspace.open(ksname);
        if (ks != null && !(ks.getReplicationStrategy() instanceof NetworkTopologyStrategy)) {
            throw new IOException(
                    "Cannot create index, underlying keyspace requires the NetworkTopologyStrategy.");
        }
    } catch (AssertionError | NullPointerException e) {
    }

    try {
        QueryProcessor.process(String.format((Locale) null,
                "CREATE KEYSPACE IF NOT EXISTS \"%s\" WITH replication = {'class':'NetworkTopologyStrategy', '%s':'%d' };",
                ksname, DatabaseDescriptor.getLocalDataCenter(), replicationFactor),
                ConsistencyLevel.LOCAL_ONE);
    } catch (Throwable e) {
        throw new IOException(e.getMessage(), e);
    }
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

@Override
public void dropIndexKeyspace(final String ksname) throws IOException {
    try {/*from w  w w  . ja v a 2 s  . co m*/
        String query = String.format((Locale) null, "DROP KEYSPACE IF EXISTS \"%s\"", ksname);
        logger.debug(query);
        QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
    } catch (Throwable e) {
        throw new IOException(e.getMessage(), e);
    }
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

public String buildUDT(final String ksName, final String cfName, final String name,
        final ObjectMapper objectMapper) throws RequestExecutionException {
    String typeName = cfName + "_" + objectMapper.fullPath().replace('.', '_');

    if (!objectMapper.iterator().hasNext()) {
        throw new InvalidRequestException("Cannot create an empty nested type (not supported)");
    }/*from   w w w.ja v a  2s.  c  o  m*/

    // create sub-type first
    for (Iterator<Mapper> it = objectMapper.iterator(); it.hasNext();) {
        Mapper mapper = it.next();
        if (mapper instanceof ObjectMapper) {
            buildCql(ksName, cfName, mapper.simpleName(), (ObjectMapper) mapper);
        } else if (mapper instanceof GeoPointFieldMapper) {
            buildGeoPointType(ksName);
        }
    }

    Pair<List<String>, List<String>> udt = getUDTInfo(ksName, typeName);
    if (udt == null) {
        // create new UDT.
        StringBuilder create = new StringBuilder(
                String.format((Locale) null, "CREATE TYPE IF NOT EXISTS \"%s\".\"%s\" ( ", ksName, typeName));
        boolean first = true;
        for (Iterator<Mapper> it = objectMapper.iterator(); it.hasNext();) {
            Mapper mapper = it.next();
            if (first)
                first = false;
            else
                create.append(", ");

            // Use only the last part of the fullname to build UDT.
            int lastDotIndex = mapper.name().lastIndexOf('.');
            String shortName = (lastDotIndex > 0) ? mapper.name().substring(lastDotIndex + 1) : mapper.name();

            if (isReservedKeyword(shortName))
                throw new ConfigurationException(shortName + " is a reserved keyword");
            create.append('\"').append(shortName).append("\" ");
            if (mapper instanceof ObjectMapper) {
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(mapper.cqlCollectionTag()).append("<");
                create.append("frozen<").append(cfName).append('_')
                        .append(((ObjectMapper) mapper).fullPath().replace('.', '_')).append(">");
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(">");
            } else if (mapper instanceof BaseGeoPointFieldMapper) {
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(mapper.cqlCollectionTag()).append("<");
                create.append("frozen<").append(GEO_POINT_TYPE).append(">");
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(">");
            } else if (mapper instanceof GeoShapeFieldMapper) {
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(mapper.cqlCollectionTag()).append("<");
                create.append("frozen<").append("text").append(">");
                if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                    create.append(">");
            } else {
                String cqlType = mapperToCql.get(mapper.getClass());
                if (mapper.cqlCollection().equals(CqlCollection.SINGLETON)) {
                    create.append(cqlType);
                } else {
                    create.append(mapper.cqlCollectionTag()).append("<");
                    if (!isNativeCql3Type(cqlType))
                        create.append("frozen<");
                    create.append(cqlType);
                    if (!isNativeCql3Type(cqlType))
                        create.append(">");
                    create.append(">");
                }
            }
        }
        create.append(" )");
        if (logger.isDebugEnabled())
            logger.debug("create UDT:" + create.toString());

        QueryProcessor.process(create.toString(), ConsistencyLevel.LOCAL_ONE);
    } else {
        // update existing UDT
        for (Iterator<Mapper> it = objectMapper.iterator(); it.hasNext();) {
            Mapper mapper = it.next();
            int lastDotIndex = mapper.name().lastIndexOf('.');
            String shortName = (lastDotIndex > 0) ? mapper.name().substring(lastDotIndex + 1) : mapper.name();
            if (isReservedKeyword(shortName))
                throw new ConfigurationException(shortName + " is a reserved keyword");

            StringBuilder update = new StringBuilder(String.format((Locale) null,
                    "ALTER TYPE \"%s\".\"%s\" ADD \"%s\" ", ksName, typeName, shortName));
            if (!udt.left.contains(shortName)) {
                if (mapper instanceof ObjectMapper) {
                    if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                        update.append(mapper.cqlCollectionTag()).append("<");
                    update.append("frozen<").append(cfName).append('_')
                            .append(((ObjectMapper) mapper).fullPath().replace('.', '_')).append(">");
                    if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                        update.append(">");
                } else if (mapper instanceof GeoPointFieldMapper) {
                    if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                        update.append(mapper.cqlCollectionTag()).append("<");
                    update.append("frozen<").append(GEO_POINT_TYPE).append(">");
                    if (!mapper.cqlCollection().equals(CqlCollection.SINGLETON))
                        update.append(">");
                } else {
                    String cqlType = mapperToCql.get(mapper.getClass());
                    if (mapper.cqlCollection().equals(CqlCollection.SINGLETON)) {
                        update.append(cqlType);
                    } else {
                        update.append(mapper.cqlCollectionTag()).append("<");
                        if (!isNativeCql3Type(cqlType))
                            update.append("frozen<");
                        update.append(cqlType);
                        if (!isNativeCql3Type(cqlType))
                            update.append(">");
                        update.append(">");
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("update UDT: " + update.toString());
                }
                QueryProcessor.process(update.toString(), ConsistencyLevel.LOCAL_ONE);
            }
        }
    }
    return typeName;
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

private void buildGeoPointType(String ksName) throws RequestExecutionException {
    String query = String.format((Locale) null,
            "CREATE TYPE IF NOT EXISTS \"%s\".\"%s\" ( %s double, %s double)", ksName, GEO_POINT_TYPE,
            org.elasticsearch.index.mapper.geo.BaseGeoPointFieldMapper.Names.LAT,
            org.elasticsearch.index.mapper.geo.BaseGeoPointFieldMapper.Names.LON);
    QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

private void buildAttachementType(String ksName) throws RequestExecutionException {
    String query = String.format((Locale) null,
            "CREATE TYPE IF NOT EXISTS \"%s\".\"%s\" (context text, content_type text, content_length bigint, date timestamp, title text, author text, keywords text, language text)",
            ksName, ATTACHEMENT_TYPE);/* ww w . java  2 s.  c  o m*/
    QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

private void buildCompletionType(String ksName) throws RequestExecutionException {
    String query = String.format((Locale) null,
            "CREATE TYPE IF NOT EXISTS \"%s\".\"%s\" (input list<text>, output text, weight bigint, payload text)",
            ksName, COMPLETION_TYPE);//from   ww  w.j  a v a  2 s  .c om
    QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

@Override
public void updateTableSchema(final IndexService indexService, final MappingMetaData mappingMd)
        throws IOException {
    try {/*from   w  w  w .  j av a2 s .  c om*/
        String ksName = indexService.keyspace();
        String cfName = InternalCassandraClusterService.typeToCfName(mappingMd.type());

        createIndexKeyspace(ksName, settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, 0) + 1);

        CFMetaData cfm = Schema.instance.getCFMetaData(ksName, cfName);
        boolean newTable = (cfm == null);

        DocumentMapper docMapper = indexService.mapperService().documentMapper(mappingMd.type());
        Map<String, Object> mappingMap = mappingMd.sourceAsMap();

        Set<String> columns = new HashSet();
        if (docMapper.sourceMapper().enabled())
            columns.add(SourceFieldMapper.NAME);
        if (mappingMap.get("properties") != null)
            columns.addAll(((Map<String, Object>) mappingMap.get("properties")).keySet());

        logger.debug("Updating CQL3 schema {}.{} columns={}", ksName, cfName, columns);
        StringBuilder columnsList = new StringBuilder();
        Map<String, Boolean> columnsMap = new HashMap<String, Boolean>(columns.size());
        String[] primaryKeyList = new String[(newTable) ? columns.size() + 1
                : cfm.partitionKeyColumns().size() + cfm.clusteringColumns().size()];
        int primaryKeyLength = 0;
        int partitionKeyLength = 0;
        for (String column : columns) {
            if (isReservedKeyword(column))
                throw new ConfigurationException(column + " is a CQL reserved keyword");

            if (column.equals(TokenFieldMapper.NAME))
                continue; // ignore pseudo column known by Elasticsearch

            if (columnsList.length() > 0)
                columnsList.append(',');

            String cqlType = null;
            String cqlNativeType = null;
            boolean isStatic = false;
            FieldMapper fieldMapper = docMapper.mappers().smartNameFieldMapper(column);
            if (fieldMapper != null) {
                if (fieldMapper instanceof GeoPointFieldMapper
                        || fieldMapper instanceof GeoPointFieldMapperLegacy) {
                    cqlType = GEO_POINT_TYPE;
                    buildGeoPointType(ksName);
                } else if (fieldMapper instanceof GeoShapeFieldMapper) {
                    cqlType = "text";
                } else if (fieldMapper instanceof CompletionFieldMapper) {
                    cqlType = COMPLETION_TYPE;
                    buildCompletionType(ksName);
                } else if (fieldMapper.getClass().getName()
                        .equals("org.elasticsearch.mapper.attachments.AttachmentMapper")) {
                    // attachement is a plugin, so class may not found.
                    cqlType = ATTACHEMENT_TYPE;
                    buildAttachementType(ksName);
                } else if (fieldMapper instanceof SourceFieldMapper) {
                    cqlType = "blob";
                } else {
                    cqlType = mapperToCql.get(fieldMapper.getClass());
                    if (cqlType == null) {
                        logger.warn("Ignoring field [{}] type [{}]", column, fieldMapper.name());
                        continue;
                    }
                }

                columnsMap.put(column, fieldMapper.cqlPartialUpdate());
                if (fieldMapper.cqlPrimaryKeyOrder() >= 0) {
                    if (fieldMapper.cqlPrimaryKeyOrder() < primaryKeyList.length
                            && primaryKeyList[fieldMapper.cqlPrimaryKeyOrder()] == null) {
                        primaryKeyList[fieldMapper.cqlPrimaryKeyOrder()] = column;
                        primaryKeyLength = Math.max(primaryKeyLength, fieldMapper.cqlPrimaryKeyOrder() + 1);
                        if (fieldMapper.cqlPartitionKey()) {
                            partitionKeyLength++;
                        }
                    } else {
                        throw new Exception("Wrong primary key order for column " + column);
                    }
                }

                if (!isNativeCql3Type(cqlType)) {
                    cqlType = "frozen<" + cqlType + ">";
                }
                if (!fieldMapper.cqlCollection().equals(CqlCollection.SINGLETON)) {
                    cqlType = fieldMapper.cqlCollectionTag() + "<" + cqlType + ">";
                }
                isStatic = fieldMapper.cqlStaticColumn();
            } else {
                ObjectMapper objectMapper = docMapper.objectMappers().get(column);
                if (objectMapper == null) {
                    logger.warn("Cannot infer CQL type from object mapping for field [{}]", column);
                    continue;
                }
                columnsMap.put(column, objectMapper.cqlPartialUpdate());
                if (objectMapper.cqlPrimaryKeyOrder() >= 0) {
                    if (objectMapper.cqlPrimaryKeyOrder() < primaryKeyList.length
                            && primaryKeyList[objectMapper.cqlPrimaryKeyOrder()] == null) {
                        primaryKeyList[objectMapper.cqlPrimaryKeyOrder()] = column;
                        primaryKeyLength = Math.max(primaryKeyLength, objectMapper.cqlPrimaryKeyOrder() + 1);
                        if (objectMapper.cqlPartitionKey()) {
                            partitionKeyLength++;
                        }
                    } else {
                        throw new Exception("Wrong primary key order for column " + column);
                    }
                }
                if (objectMapper.cqlStruct().equals(CqlStruct.MAP)) {
                    // TODO: check columnName exists and is map<text,?>
                    cqlType = buildCql(ksName, cfName, column, objectMapper);
                    if (!objectMapper.cqlCollection().equals(CqlCollection.SINGLETON)) {
                        cqlType = objectMapper.cqlCollectionTag() + "<" + cqlType + ">";
                    }
                    //logger.debug("Expecting column [{}] to be a map<text,?>", column);
                } else if (objectMapper.cqlStruct().equals(CqlStruct.UDT)) {
                    if (!objectMapper.iterator().hasNext()) {
                        // opaque json object
                        cqlType = "text";
                    } else {
                        // Cassandra 2.1.8 : Non-frozen collections are not allowed inside collections
                        cqlType = "frozen<\"" + buildCql(ksName, cfName, column, objectMapper) + "\">";
                    }
                    if (!objectMapper.cqlCollection().equals(CqlCollection.SINGLETON)
                            && !(cfName.equals(PERCOLATOR_TABLE) && column.equals("query"))) {
                        cqlType = objectMapper.cqlCollectionTag() + "<" + cqlType + ">";
                    }
                }
                isStatic = objectMapper.cqlStaticColumn();
            }

            if (newTable) {
                if (cqlType != null) {
                    columnsList.append("\"").append(column).append("\" ").append(cqlType);
                    if (isStatic)
                        columnsList.append(" static");
                }
            } else {
                ColumnDefinition cdef = cfm.getColumnDefinition(new ColumnIdentifier(column, true));
                if (cqlType != null) {
                    if (cdef == null) {
                        for (int i = 0; i < primaryKeyLength; i++) {
                            if (primaryKeyList[i].equals(column))
                                throw new Exception("Cannot alter primary key of an existing table");
                        }
                        try {
                            String query = String.format((Locale) null,
                                    "ALTER TABLE \"%s\".\"%s\" ADD \"%s\" %s %s", ksName, cfName, column,
                                    cqlType, (isStatic) ? "static" : "");
                            logger.debug(query);
                            QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
                        } catch (Exception e) {
                            logger.warn("Cannot alter table {}.{} column {} with type {}", e, ksName, cfName,
                                    column, cqlType);
                        }
                    } else {
                        // check that the existing column matches the provided mapping
                        // TODO: do this check for collection
                        String existingCqlType = cdef.type.asCQL3Type().toString();
                        if (!cdef.type.isCollection()) {
                            // cdef.type.asCQL3Type() does not include frozen, nor quote, so can do this check for collection.
                            if (!existingCqlType.equals(cqlType)
                                    && !cqlType.equals("frozen<" + existingCqlType + ">")) {
                                throw new IOException(
                                        "Existing column " + column + " mismatch type " + cqlType);
                            }
                        }
                    }
                }
            }

        }

        // add _parent column if necessary. Parent and child documents should have the same partition key.
        if (docMapper.parentFieldMapper().active() && docMapper.parentFieldMapper().pkColumns() == null) {
            if (newTable) {
                // _parent is a JSON array representation of the parent PK.
                if (columnsList.length() > 0)
                    columnsList.append(", ");
                columnsList.append("\"_parent\" text");
            } else {
                try {
                    String query = String.format((Locale) null,
                            "ALTER TABLE \"%s\".\"%s\" ADD \"_parent\" text", ksName, cfName);
                    logger.debug(query);
                    QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
                } catch (Exception e) {
                    logger.warn("Cannot alter table {}.{} column _parent with type text", e, ksName, cfName);
                }
            }
        }

        if (newTable) {
            if (partitionKeyLength == 0) {
                // build a default primary key _id text
                if (columnsList.length() > 0)
                    columnsList.append(',');
                columnsList.append("\"").append(ELASTIC_ID_COLUMN_NAME).append("\" text");
                primaryKeyList[0] = ELASTIC_ID_COLUMN_NAME;
                primaryKeyLength = 1;
                partitionKeyLength = 1;
            }
            // build the primary key definition
            StringBuilder primaryKey = new StringBuilder();
            primaryKey.append("(");
            for (int i = 0; i < primaryKeyLength; i++) {
                if (primaryKeyList[i] == null)
                    throw new Exception("Incomplet primary key definition at index " + i);
                primaryKey.append("\"").append(primaryKeyList[i]).append("\"");
                if (i == partitionKeyLength - 1)
                    primaryKey.append(")");
                if (i + 1 < primaryKeyLength)
                    primaryKey.append(",");
            }
            String query = String.format((Locale) null,
                    "CREATE TABLE IF NOT EXISTS \"%s\".\"%s\" ( %s, PRIMARY KEY (%s) ) WITH COMMENT='Auto-created by Elassandra'",
                    ksName, cfName, columnsList.toString(), primaryKey.toString());
            logger.debug(query);
            QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
        }

        updateMapping(indexService.index().name(), mappingMd);

    } catch (Throwable e) {
        throw new IOException(e.getMessage(), e);
    }
}

From source file:org.elassandra.cluster.InternalCassandraClusterService.java

License:Apache License

public void createSecondaryIndex(String ksName, MappingMetaData mapping, String className) throws IOException {
    final String cfName = typeToCfName(mapping.type());
    final CFMetaData cfm = Schema.instance.getCFMetaData(ksName, cfName);
    if (cfm != null) {
        String query = null;/*from w w w. j a  v a  2 s.c om*/
        try {
            Map<String, Object> mappingProperties = (Map<String, Object>) mapping.sourceAsMap()
                    .get("properties");
            if (mappingProperties != null) {
                for (Map.Entry<String, Object> entry : mappingProperties.entrySet()) {
                    String column = entry.getKey();
                    if (column.startsWith("_")) {
                        continue; // ignore pseudo column known by Elasticsearch
                    }
                    if ("no".equals(((Map<String, Object>) entry.getValue()).get("index"))) {
                        continue; // ignore field with index:no
                    }
                    ColumnDefinition cdef = (cfm == null) ? null
                            : cfm.getColumnDefinition(new ColumnIdentifier(column, true));
                    if ((cdef != null) && !cdef.isIndexed() && !(cfm.partitionKeyColumns().size() == 1
                            && cdef.kind == ColumnDefinition.Kind.PARTITION_KEY)) {
                        query = String.format((Locale) null,
                                "CREATE CUSTOM INDEX IF NOT EXISTS \"%s\" ON \"%s\".\"%s\" (\"%s\") USING '%s'",
                                buildIndexName(cfName, column), ksName, cfName, column, className);
                        logger.debug(query);
                        QueryProcessor.process(query, ConsistencyLevel.LOCAL_ONE);
                    }
                }
            }
        } catch (Throwable e) {
            throw new IOException("Failed to process query=[" + query + "]:" + e.getMessage(), e);
        }
    } else {
        logger.warn("Cannot create SECONDARY INDEX, [{}.{}] does not exist", ksName, cfName);
    }
}