From e4a8d7cf710dad0a0e2949a38becfab736130ddf Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Thu, 15 Jan 2015 13:25:39 +0200 Subject: [PATCH] cql3: Convert ModificationStatement to C++ Signed-off-by: Pekka Enberg --- configure.py | 1 + cql3/cql3.cc | 1 + cql3/statements/modification_statement.cc | 37 +++ ...atement.java => modification_statement.hh} | 239 +++++++++++------- db/column_family.hh | 12 + 5 files changed, 201 insertions(+), 89 deletions(-) create mode 100644 cql3/statements/modification_statement.cc rename cql3/statements/{ModificationStatement.java => modification_statement.hh} (84%) create mode 100644 db/column_family.hh diff --git a/configure.py b/configure.py index 9d0f5c0d51..29094fb6fe 100755 --- a/configure.py +++ b/configure.py @@ -227,6 +227,7 @@ deps = { 'cql3/cql3.cc', 'cql3/cql3_type.cc', 'cql3/functions/functions.cc', + 'cql3/statements/modification_statement.cc', 'thrift/handler.cc', 'thrift/server.cc', 'utils/murmur_hash.cc', diff --git a/cql3/cql3.cc b/cql3/cql3.cc index 828511d418..d692abd8a4 100644 --- a/cql3/cql3.cc +++ b/cql3/cql3.cc @@ -24,6 +24,7 @@ #include "statements/alter_type_statement.hh" #include "statements/cf_statement.hh" #include "statements/ks_prop_defs.hh" +#include "statements/modification_statement.hh" #include "statements/use_statement.hh" #include "statements/parsed_statement.hh" #include "statements/property_definitions.hh" diff --git a/cql3/statements/modification_statement.cc b/cql3/statements/modification_statement.cc new file mode 100644 index 0000000000..d26a4b9f84 --- /dev/null +++ b/cql3/statements/modification_statement.cc @@ -0,0 +1,37 @@ +/* + * 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. + */ + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +#include "cql3/statements/modification_statement.hh" + +#include "core/shared_ptr.hh" + +namespace cql3 { + +namespace statements { + +::shared_ptr modification_statement::CAS_RESULT_COLUMN = ::make_shared("[applied]", false); + +} + +} diff --git a/cql3/statements/ModificationStatement.java b/cql3/statements/modification_statement.hh similarity index 84% rename from cql3/statements/ModificationStatement.java rename to cql3/statements/modification_statement.hh index 8347ef5825..a68f438935 100644 --- a/cql3/statements/ModificationStatement.java +++ b/cql3/statements/modification_statement.hh @@ -15,6 +15,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/* + * Copyright 2015 Cloudius Systems + * + * Modified by Cloudius Systems + */ + +#ifndef CQL3_STATEMENTS_MODIFICATION_STATEMENT_HH +#define CQL3_STATEMENTS_MODIFICATION_STATEMENT_HH + +#include "cql3/statements/cf_statement.hh" +#include "cql3/column_identifier.hh" +#include "cql3/update_parameters.hh" +#include "cql3/column_condition.hh" +#include "cql3/cql_statement.hh" +#include "cql3/attributes.hh" +#include "cql3/operation.hh" + +#include "config/cf_meta_data.hh" + +#include "db/column_family.hh" + +#include "core/shared_ptr.hh" + +#include + +namespace cql3 { + +namespace statements { + +#if 0 package org.apache.cassandra.cql3.statements; import java.nio.ByteBuffer; @@ -43,119 +74,128 @@ import org.apache.cassandra.service.StorageProxy; import org.apache.cassandra.thrift.ThriftValidation; import org.apache.cassandra.transport.messages.ResultMessage; import org.apache.cassandra.utils.Pair; +#endif /* * Abstract parent class of individual modifications, i.e. INSERT, UPDATE and DELETE. */ -public abstract class ModificationStatement implements CQLStatement -{ - private static final ColumnIdentifier CAS_RESULT_COLUMN = new ColumnIdentifier("[applied]", false); +class modification_statement : public cql_statement { +private: + static ::shared_ptr CAS_RESULT_COLUMN; - public static enum StatementType { INSERT, UPDATE, DELETE } - public final StatementType type; +public: + enum class statement_type { INSERT, UPDATE, DELETE }; - private final int boundTerms; - public final CFMetaData cfm; - public final Attributes attrs; + const statement_type type; +private: + const int32_t _bound_terms; + +public: + const ::shared_ptr cfm; + const std::unique_ptr attrs; + +#if 0 protected final Map processedKeys = new HashMap<>(); - private final List columnOperations = new ArrayList(); +#endif + +private: + const std::vector>> _column_operations; // Separating normal and static conditions makes things somewhat easier - private List columnConditions; - private List staticConditions; - private boolean ifNotExists; - private boolean ifExists; + std::vector>> _column_conditions; + std::vector>> _static_conditions; - private boolean hasNoClusteringColumns = true; + bool _if_not_exists = false; + bool _if_exists = false; - private boolean setsStaticColumns; - private boolean setsRegularColumns; + bool _has_no_clustering_columns = true; - private final Function getColumnForCondition = new Function() - { - public ColumnDefinition apply(ColumnCondition cond) - { - return cond.column; - } - }; + bool _sets_static_columns = false; + bool _sets_regular_columns = false; - public ModificationStatement(StatementType type, int boundTerms, CFMetaData cfm, Attributes attrs) - { - this.type = type; - this.boundTerms = boundTerms; - this.cfm = cfm; - this.attrs = attrs; - } + const std::function<::shared_ptr(::shared_ptr)> get_column_for_condition = + [](::shared_ptr cond) -> ::shared_ptr { + return cond->column; + }; - public boolean usesFunction(String ksName, String functionName) - { - if (attrs.usesFunction(ksName, functionName)) +public: + modification_statement(statement_type type_, int32_t bound_terms, ::shared_ptr cfm_, std::unique_ptr&& attrs_) + : type{type_} + , _bound_terms{bound_terms} + , cfm{cfm_} + , attrs{std::move(attrs_)} + , _column_operations{} + { } + + virtual bool uses_function(sstring ks_name, sstring function_name) const override { + if (attrs->uses_function(ks_name, function_name)) return true; +#if 0 for (Restriction restriction : processedKeys.values()) if (restriction != null && restriction.usesFunction(ksName, functionName)) return true; - for (Operation operation : columnOperations) - if (operation != null && operation.usesFunction(ksName, functionName)) +#endif + for (auto&& operation : _column_operations) { + if (operation && operation.value()->uses_function(ks_name, function_name)) return true; - for (ColumnCondition condition : columnConditions) - if (condition != null && condition.usesFunction(ksName, functionName)) + } + for (auto&& condition : _column_conditions) { + if (condition && condition.value()->uses_function(ks_name, function_name)) return true; - for (ColumnCondition condition : staticConditions) - if (condition != null && condition.usesFunction(ksName, functionName)) + } + for (auto&& condition : _static_conditions) { + if (condition && condition.value()->uses_function(ks_name, function_name)) return true; + } return false; } - public abstract boolean requireFullClusteringKey(); - public abstract void addUpdateForKey(ColumnFamily updates, ByteBuffer key, Composite prefix, UpdateParameters params) throws InvalidRequestException; + virtual bool require_full_clustering_key() const = 0; - public int getBoundTerms() - { - return boundTerms; + virtual void add_update_for_key(::shared_ptr updates, bytes key, ::shared_ptr prefix, ::shared_ptr params) = 0; + + virtual int get_bound_terms() override { + return _bound_terms; } - public String keyspace() - { - return cfm.ksName; + virtual sstring keyspace() const { + return cfm->ks_name; } - public String columnFamily() - { - return cfm.cfName; + virtual sstring column_family() const { + return cfm->cf_name; } - public boolean isCounter() - { - return cfm.isCounter(); + virtual bool is_counter() const { + return cfm->is_counter(); } - public long getTimestamp(long now, QueryOptions options) throws InvalidRequestException - { - return attrs.getTimestamp(now, options); + int64_t get_timestamp(int64_t now, const query_options& options) const { + return attrs->get_timestamp(now, options); } - public boolean isTimestampSet() - { - return attrs.isTimestampSet(); + bool is_timestamp_set() const { + return attrs->is_timestamp_set(); } - public int getTimeToLive(QueryOptions options) throws InvalidRequestException - { - return attrs.getTimeToLive(options); + int32_t get_time_to_live(const query_options& options) const { + return attrs->get_time_to_live(options); } - public void checkAccess(ClientState state) throws InvalidRequestException, UnauthorizedException - { + virtual void check_access(const service::client_state& state) override { +#if 0 state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.MODIFY); // CAS updates can be used to simulate a SELECT query, so should require Permission.SELECT as well. if (hasConditions()) state.hasColumnFamilyAccess(keyspace(), columnFamily(), Permission.SELECT); +#endif + throw std::runtime_error("not implemented"); } - public void validate(ClientState state) throws InvalidRequestException - { + virtual void validate(const service::client_state& state) override { +#if 0 if (hasConditions() && attrs.isTimestampSet()) throw new InvalidRequestException("Cannot provide custom timestamp for conditional updates"); @@ -164,8 +204,11 @@ public abstract class ModificationStatement implements CQLStatement if (isCounter() && attrs.isTimeToLiveSet()) throw new InvalidRequestException("Cannot provide custom TTL for counter updates"); +#endif + throw std::runtime_error("not implemented"); } +#if 0 public void addOperation(Operation op) { if (op.column.isStatic()) @@ -208,27 +251,25 @@ public abstract class ModificationStatement implements CQLStatement } conds.add(cond); } +#endif - public void setIfNotExistCondition() - { - ifNotExists = true; + void set_if_not_exist_condition() { + _if_not_exists = true; } - public boolean hasIfNotExistCondition() - { - return ifNotExists; + bool has_if_not_exist_condition() const { + return _if_not_exists; } - public void setIfExistCondition() - { - ifExists = true; + void set_if_exist_condition() { + _if_exists = true; } - public boolean hasIfExistCondition() - { - return ifExists; + bool has_if_exist_condition() const { + return _if_exists; } +#if 0 private void addKeyValues(ColumnDefinition def, Restriction values) throws InvalidRequestException { if (def.kind == ColumnDefinition.Kind.CLUSTERING_COLUMN) @@ -671,33 +712,46 @@ public abstract class ModificationStatement implements CQLStatement Map rows = readRequiredRows(keys, prefix, local, options.getConsistency()); return new UpdateParameters(cfm, options, getTimestamp(now, options), getTimeToLive(options), rows); } +#endif +protected: /** * If there are conditions on the statement, this is called after the where clause and conditions have been * processed to check that they are compatible. * @throws InvalidRequestException */ - protected void validateWhereClauseForConditions() throws InvalidRequestException - { + virtual void validate_where_clause_for_conditions() { // no-op by default } - public static abstract class Parsed extends CFStatement - { - protected final Attributes.Raw attrs; - protected final List> conditions; - private final boolean ifNotExists; - private final boolean ifExists; - - protected Parsed(CFName name, Attributes.Raw attrs, List> conditions, boolean ifNotExists, boolean ifExists) +public: + class parsed : public cf_statement { + public: + using conditions_vector = std::vector, ::shared_ptr>>; + protected: + const ::shared_ptr _attrs; + const std::vector, ::shared_ptr>> _conditions; + private: + const bool _if_not_exists; + const bool _if_exists; + protected: + parsed(std::experimental::optional&& name, ::shared_ptr attrs, const conditions_vector& conditions, bool if_not_exists, bool if_exists) + : cf_statement{std::move(name)} + , _attrs{attrs} + , _conditions{conditions} + , _if_not_exists{if_not_exists} + , _if_exists{if_exists} { +#if 0 super(name); this.attrs = attrs; this.conditions = conditions == null ? Collections.>emptyList() : conditions; this.ifNotExists = ifNotExists; this.ifExists = ifExists; +#endif } +#if 0 public ParsedStatement.Prepared prepare() throws InvalidRequestException { VariableSpecifications boundNames = getBoundVariables(); @@ -766,5 +820,12 @@ public abstract class ModificationStatement implements CQLStatement } protected abstract ModificationStatement prepareInternal(CFMetaData cfm, VariableSpecifications boundNames, Attributes attrs) throws InvalidRequestException; - } +#endif + }; +}; + } + +} + +#endif diff --git a/db/column_family.hh b/db/column_family.hh new file mode 100644 index 0000000000..8af38116e5 --- /dev/null +++ b/db/column_family.hh @@ -0,0 +1,12 @@ +#ifndef DB_COLUMN_FAMILY_HH +#define DB_COLUMN_FAMILY_HH + +namespace db { + +class column_family { + // FIXME: stub +}; + +} + +#endif