Files
scylladb/cql3/operation.hh
Avi Kivity 3d38708434 cql3: pass a database& instance to most foo::raw::prepare() variants
To prepare a user-defined type, we need to look up its name in the keyspace.
While we get the keyspace name as an argument to prepare(), it is useless
without the database instance.

Fix the problem by passing a database reference along with the keyspace.
This precolates through the class structure, so most cql3 raw types end up
receiving this treatment.

Origin gets along without it by using a singleton.  We can't do this due
to sharding (we could use a thread-local instance, but that's ugly too).

Hopefully the transition to a visitor will clean this up.
2015-04-20 16:15:34 +03:00

272 lines
8.7 KiB
C++

/*
* 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
*/
#ifndef CQL3_OPERATION_HH
#define CQL3_OPERATION_HH
#include "core/shared_ptr.hh"
#include "exceptions/exceptions.hh"
#include "database.hh"
#include "term.hh"
#include <experimental/optional>
namespace cql3 {
class update_parameters;
#if 0
package org.apache.cassandra.cql3;
import java.nio.ByteBuffer;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.db.ColumnFamily;
import org.apache.cassandra.db.composites.Composite;
import org.apache.cassandra.db.marshal.*;
import org.apache.cassandra.exceptions.InvalidRequestException;
#endif
/**
* An UPDATE or DELETE operation.
*
* For UPDATE this includes:
* - setting a constant
* - counter operations
* - collections operations
* and for DELETE:
* - deleting a column
* - deleting an element of collection column
*
* Fine grained operation are obtained from their raw counterpart (Operation.Raw, which
* correspond to a parsed, non-checked operation) by provided the receiver for the operation.
*/
class operation {
public:
// the column the operation applies to
// We can hold a reference because all operations have life bound to their statements and
// statements pin the schema.
const column_definition& column;
protected:
// Term involved in the operation. In theory this should not be here since some operation
// may require none of more than one term, but most need 1 so it simplify things a bit.
const ::shared_ptr<term> _t;
public:
operation(const column_definition& column_, ::shared_ptr<term> t)
: column{column_}
, _t{t}
{ }
virtual ~operation() {}
virtual bool uses_function(const sstring& ks_name, const sstring& function_name) const {
return _t && _t->uses_function(ks_name, function_name);
}
/**
* @return whether the operation requires a read of the previous value to be executed
* (only lists setterByIdx, discard and discardByIdx requires that).
*/
virtual bool requires_read() {
return false;
}
/**
* Collects the column specification for the bind variables of this operation.
*
* @param bound_names the list of column specification where to collect the
* bind variables of this term in.
*/
virtual void collect_marker_specification(::shared_ptr<variable_specifications> bound_names) {
if (_t) {
_t->collect_marker_specification(bound_names);
}
}
/**
* Execute the operation.
*/
virtual void execute(mutation& m, const exploded_clustering_prefix& prefix, const update_parameters& params) = 0;
/**
* A parsed raw UPDATE operation.
*
* This can be one of:
* - Setting a value: c = v
* - Setting an element of a collection: c[x] = v
* - An addition/subtraction to a variable: c = c +/- v (where v can be a collection literal)
* - An prepend operation: c = v + c
*/
class raw_update {
public:
virtual ~raw_update() {}
/**
* This method validates the operation (i.e. validate it is well typed)
* based on the specification of the receiver of the operation.
*
* It returns an Operation which can be though as post-preparation well-typed
* Operation.
*
* @param receiver the "column" this operation applies to. Note that
* contrarly to the method of same name in Term.Raw, the receiver should always
* be a true column.
* @return the prepared update operation.
*/
virtual ::shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) = 0;
/**
* @return whether this operation can be applied alongside the {@code
* other} update (in the same UPDATE statement for the same column).
*/
virtual bool is_compatible_with(::shared_ptr<raw_update> other) = 0;
};
/**
* A parsed raw DELETE operation.
*
* This can be one of:
* - Deleting a column
* - Deleting an element of a collection
*/
class raw_deletion {
public:
~raw_deletion() {}
/**
* The name of the column affected by this delete operation.
*/
virtual ::shared_ptr<column_identifier::raw> affected_column() = 0;
/**
* This method validates the operation (i.e. validate it is well typed)
* based on the specification of the column affected by the operation (i.e the
* one returned by affectedColumn()).
*
* It returns an Operation which can be though as post-preparation well-typed
* Operation.
*
* @param receiver the "column" this operation applies to.
* @return the prepared delete operation.
*/
virtual ::shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) = 0;
};
class set_value;
class set_element : public raw_update {
const shared_ptr<term::raw> _selector;
const shared_ptr<term::raw> _value;
public:
set_element(shared_ptr<term::raw> selector, shared_ptr<term::raw> value)
: _selector(std::move(selector)), _value(std::move(value)) {
}
virtual shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver);
#if 0
protected String toString(ColumnSpecification column)
{
return String.format("%s[%s] = %s", column.name, selector, value);
}
#endif
virtual bool is_compatible_with(shared_ptr<raw_update> other) override;
};
class addition : public raw_update {
const shared_ptr<term::raw> _value;
public:
addition(shared_ptr<term::raw> value)
: _value(value) {
}
virtual shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) override;
#if 0
protected String toString(ColumnSpecification column)
{
return String.format("%s = %s + %s", column.name, column.name, value);
}
#endif
virtual bool is_compatible_with(shared_ptr<raw_update> other) override;
};
class subtraction : public raw_update {
const shared_ptr<term::raw> _value;
public:
subtraction(shared_ptr<term::raw> value)
: _value(value) {
}
virtual shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) override;
#if 0
protected String toString(ColumnSpecification column)
{
return String.format("%s = %s - %s", column.name, column.name, value);
}
#endif
virtual bool is_compatible_with(shared_ptr<raw_update> other) override;
};
class prepend : public raw_update {
shared_ptr<term::raw> _value;
public:
prepend(shared_ptr<term::raw> value)
: _value(std::move(value)) {
}
virtual shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) override;
#if 0
protected String toString(ColumnSpecification column)
{
return String.format("%s = %s - %s", column.name, value, column.name);
}
#endif
virtual bool is_compatible_with(shared_ptr<raw_update> other) override;
};
class column_deletion;
class element_deletion : public raw_deletion {
shared_ptr<column_identifier::raw> _id;
shared_ptr<term::raw> _element;
public:
element_deletion(shared_ptr<column_identifier::raw> id, shared_ptr<term::raw> element)
: _id(std::move(id)), _element(std::move(element)) {
}
virtual shared_ptr<column_identifier::raw> affected_column() override;
virtual shared_ptr<operation> prepare(database& db, const sstring& keyspace, const column_definition& receiver) override;
};
};
}
#endif