cequel 1.0.0.rc1 → 1.0.0.rc2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/cequel.rb +18 -0
- data/lib/cequel/errors.rb +8 -4
- data/lib/cequel/metal.rb +14 -0
- data/lib/cequel/metal/batch.rb +21 -11
- data/lib/cequel/metal/batch_manager.rb +74 -0
- data/lib/cequel/metal/cql_row_specification.rb +19 -6
- data/lib/cequel/metal/data_set.rb +400 -163
- data/lib/cequel/metal/deleter.rb +45 -11
- data/lib/cequel/metal/incrementer.rb +23 -10
- data/lib/cequel/metal/inserter.rb +19 -6
- data/lib/cequel/metal/keyspace.rb +82 -159
- data/lib/cequel/metal/logger.rb +71 -0
- data/lib/cequel/metal/logging.rb +47 -0
- data/lib/cequel/metal/new_relic_instrumentation.rb +26 -0
- data/lib/cequel/metal/row.rb +36 -10
- data/lib/cequel/metal/row_specification.rb +21 -8
- data/lib/cequel/metal/statement.rb +30 -6
- data/lib/cequel/metal/updater.rb +89 -12
- data/lib/cequel/metal/writer.rb +23 -14
- data/lib/cequel/record.rb +52 -6
- data/lib/cequel/record/association_collection.rb +13 -6
- data/lib/cequel/record/associations.rb +146 -54
- data/lib/cequel/record/belongs_to_association.rb +34 -7
- data/lib/cequel/record/bound.rb +69 -12
- data/lib/cequel/record/bulk_writes.rb +29 -1
- data/lib/cequel/record/callbacks.rb +22 -6
- data/lib/cequel/record/collection.rb +273 -36
- data/lib/cequel/record/configuration_generator.rb +5 -0
- data/lib/cequel/record/data_set_builder.rb +86 -0
- data/lib/cequel/record/dirty.rb +11 -8
- data/lib/cequel/record/errors.rb +38 -4
- data/lib/cequel/record/has_many_association.rb +42 -9
- data/lib/cequel/record/lazy_record_collection.rb +39 -10
- data/lib/cequel/record/mass_assignment.rb +14 -6
- data/lib/cequel/record/persistence.rb +157 -20
- data/lib/cequel/record/properties.rb +147 -24
- data/lib/cequel/record/railtie.rb +15 -2
- data/lib/cequel/record/record_set.rb +504 -75
- data/lib/cequel/record/schema.rb +77 -13
- data/lib/cequel/record/scoped.rb +16 -11
- data/lib/cequel/record/secondary_indexes.rb +42 -6
- data/lib/cequel/record/tasks.rb +2 -1
- data/lib/cequel/record/validations.rb +51 -11
- data/lib/cequel/schema.rb +9 -0
- data/lib/cequel/schema/column.rb +172 -33
- data/lib/cequel/schema/create_table_dsl.rb +62 -31
- data/lib/cequel/schema/keyspace.rb +106 -7
- data/lib/cequel/schema/migration_validator.rb +128 -0
- data/lib/cequel/schema/table.rb +183 -20
- data/lib/cequel/schema/table_property.rb +92 -34
- data/lib/cequel/schema/table_reader.rb +45 -15
- data/lib/cequel/schema/table_synchronizer.rb +101 -43
- data/lib/cequel/schema/table_updater.rb +114 -19
- data/lib/cequel/schema/table_writer.rb +31 -13
- data/lib/cequel/schema/update_table_dsl.rb +71 -40
- data/lib/cequel/type.rb +214 -53
- data/lib/cequel/util.rb +6 -9
- data/lib/cequel/version.rb +2 -1
- data/spec/examples/record/associations_spec.rb +12 -12
- data/spec/examples/record/persistence_spec.rb +5 -5
- data/spec/examples/record/record_set_spec.rb +62 -50
- data/spec/examples/schema/table_synchronizer_spec.rb +37 -11
- data/spec/examples/schema/table_updater_spec.rb +3 -3
- data/spec/examples/spec_helper.rb +2 -11
- data/spec/examples/type_spec.rb +3 -3
- metadata +23 -4
- data/lib/cequel/new_relic_instrumentation.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4988b87b5a5a9fc843dcaaf3bdfb3a5842b20cc8
|
4
|
+
data.tar.gz: ce93eaeb725d23f31a22dc3f8e2e84fc4d9ec0e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b738d10a75bd0f977eeff27c119ccd9d7980c66e2e1bdf004ef74e980dc847514ea7083cd9432f28b4d1099a151c635a71f50cd1f1757d6a20c16c42074504a0
|
7
|
+
data.tar.gz: be8264f1142625d8755a149550f68a9c2dc66b93c7a6a562f0c893043dbaf859ab879632911c8b753b96cdd07ea025b2348f12a237e07bdc4c7cad27015093a8
|
data/lib/cequel.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
1
3
|
require 'active_support/core_ext'
|
2
4
|
require 'cassandra-cql/1.2'
|
3
5
|
require 'connection_pool'
|
@@ -9,7 +11,23 @@ require 'cequel/type'
|
|
9
11
|
require 'cequel/util'
|
10
12
|
require 'cequel/record'
|
11
13
|
|
14
|
+
#
|
15
|
+
# Cequel is a library providing robust data modeling and query building
|
16
|
+
# capabilities for Cassandra using CQL3.
|
17
|
+
#
|
18
|
+
# @see Cequel::Record Cequel::Record, an object-row mapper for CQL3
|
19
|
+
# @see Cequel::Metal Cequel::Metal, a query builder for CQL3 statements
|
20
|
+
# @see Cequel::Schema Cequel::Schema::Keyspace, which provides full read-write
|
21
|
+
# access to the database schema defined in Cassandra
|
22
|
+
#
|
12
23
|
module Cequel
|
24
|
+
#
|
25
|
+
# Get a handle to a keyspace
|
26
|
+
#
|
27
|
+
# @param (see Metal::Keyspace#initialize)
|
28
|
+
# @option (see Metal::Keyspace#initialize)
|
29
|
+
# @return [Metal::Keyspace] a handle to a keyspace
|
30
|
+
#
|
13
31
|
def self.connect(configuration = nil)
|
14
32
|
Metal::Keyspace.new(configuration || {})
|
15
33
|
end
|
data/lib/cequel/errors.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
#
|
3
|
+
# @since 1.0.0
|
4
|
+
#
|
5
|
+
# Raised when the schema defined in Cassandra cannot be modified to match
|
6
|
+
# the schema defined in the application (e.g., changing the type of a primary
|
7
|
+
# key)
|
8
|
+
#
|
9
|
+
InvalidSchemaMigration = Class.new(StandardError)
|
6
10
|
end
|
data/lib/cequel/metal.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'cequel/metal/batch'
|
2
|
+
require 'cequel/metal/batch_manager'
|
2
3
|
require 'cequel/metal/cql_row_specification'
|
3
4
|
require 'cequel/metal/data_set'
|
5
|
+
require 'cequel/metal/logging'
|
4
6
|
require 'cequel/metal/keyspace'
|
7
|
+
require 'cequel/metal/logger'
|
5
8
|
require 'cequel/metal/row'
|
6
9
|
require 'cequel/metal/row_specification'
|
7
10
|
require 'cequel/metal/statement'
|
@@ -12,6 +15,17 @@ require 'cequel/metal/inserter'
|
|
12
15
|
require 'cequel/metal/updater'
|
13
16
|
|
14
17
|
module Cequel
|
18
|
+
#
|
19
|
+
# The Cequel::Metal layer provides a low-level interface to the Cassandra
|
20
|
+
# database. Most of the functionality is exposed via the DataSet class, which
|
21
|
+
# encapsulates a table with optional filtering, and provides an interface for
|
22
|
+
# constructing read and write queries. The Metal layer is not schema-aware,
|
23
|
+
# and relies on the user to construct valid CQL queries.
|
24
|
+
#
|
25
|
+
# @see Keyspace
|
26
|
+
# @see DataSet
|
27
|
+
# @since 1.0.0
|
28
|
+
#
|
15
29
|
module Metal
|
16
30
|
end
|
17
31
|
end
|
data/lib/cequel/metal/batch.rb
CHANGED
@@ -1,26 +1,30 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
3
|
module Cequel
|
4
|
-
|
5
4
|
module Metal
|
6
|
-
|
7
5
|
#
|
8
6
|
# Encapsulates a batch operation
|
9
7
|
#
|
10
8
|
# @see Keyspace::batch
|
9
|
+
# @api private
|
11
10
|
#
|
12
11
|
class Batch
|
13
|
-
|
14
12
|
#
|
15
|
-
# @param keyspace [Keyspace] the keyspace that this batch will be
|
13
|
+
# @param keyspace [Keyspace] the keyspace that this batch will be
|
14
|
+
# executed on
|
16
15
|
# @param options [Hash]
|
17
|
-
# @option options
|
16
|
+
# @option options [Integer] :auto_apply If specified, flush the batch
|
17
|
+
# after this many statements have been added.
|
18
|
+
# @option options [Boolean] :unlogged (false) Whether to use an [unlogged
|
19
|
+
# batch](http://www.datastax.com/documentation/cql/3.0/webhelp/cql/cql_reference/batch_r.html).
|
20
|
+
# Logged batches guarantee atomicity (but not isolation) at the
|
21
|
+
# cost of a performance penalty; unlogged batches are useful for bulk
|
22
|
+
# write operations but behave the same as discrete writes.
|
18
23
|
# @see Keyspace#batch
|
19
|
-
# @todo support batch-level consistency options
|
20
24
|
#
|
21
25
|
def initialize(keyspace, options = {})
|
22
26
|
@keyspace = keyspace
|
23
|
-
@auto_apply = options
|
27
|
+
@auto_apply = options[:auto_apply]
|
24
28
|
@unlogged = options.fetch(:unlogged, false)
|
25
29
|
reset
|
26
30
|
end
|
@@ -39,7 +43,7 @@ module Cequel
|
|
39
43
|
end
|
40
44
|
end
|
41
45
|
|
42
|
-
#
|
46
|
+
#
|
43
47
|
# Send the batch to Cassandra
|
44
48
|
#
|
45
49
|
def apply
|
@@ -51,10 +55,19 @@ module Cequel
|
|
51
55
|
@keyspace.execute(*@statement.args)
|
52
56
|
end
|
53
57
|
|
58
|
+
#
|
59
|
+
# Is this an unlogged batch?
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
54
62
|
def unlogged?
|
55
63
|
@unlogged
|
56
64
|
end
|
57
65
|
|
66
|
+
#
|
67
|
+
# Is this a logged batch?
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
#
|
58
71
|
def logged?
|
59
72
|
!unlogged?
|
60
73
|
end
|
@@ -69,9 +82,6 @@ module Cequel
|
|
69
82
|
def begin_statement
|
70
83
|
"BEGIN #{"UNLOGGED " if unlogged?}BATCH\n"
|
71
84
|
end
|
72
|
-
|
73
85
|
end
|
74
|
-
|
75
86
|
end
|
76
|
-
|
77
87
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Cequel
|
2
|
+
module Metal
|
3
|
+
#
|
4
|
+
# Manage a current batch per thread. Used by {Keyspace}
|
5
|
+
#
|
6
|
+
# @api private
|
7
|
+
#
|
8
|
+
class BatchManager
|
9
|
+
#
|
10
|
+
# @param keyspace [Keyspace] keyspace to make writes to
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
def initialize(keyspace)
|
14
|
+
@keyspace = keyspace
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Execute write operations in a batch. Any inserts, updates, and deletes
|
19
|
+
# inside this method's block will be executed inside a CQL BATCH
|
20
|
+
# operation.
|
21
|
+
#
|
22
|
+
# @param options [Hash]
|
23
|
+
# @option (see Batch#initialize)
|
24
|
+
# @yield context within which all write operations will be batched
|
25
|
+
# @return return value of block
|
26
|
+
# @raise [ArgumentError] if attempting to start a logged batch while
|
27
|
+
# already in an unlogged batch, or vice versa.
|
28
|
+
#
|
29
|
+
# @example Perform inserts in a batch
|
30
|
+
# DB.batch do
|
31
|
+
# DB[:posts].insert(:id => 1, :title => 'One')
|
32
|
+
# DB[:posts].insert(:id => 2, :title => 'Two')
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# @note If this method is created while already in a batch of the same
|
36
|
+
# type (logged or unlogged), this method is a no-op.
|
37
|
+
#
|
38
|
+
def batch(options = {})
|
39
|
+
new_batch = Batch.new(keyspace, options)
|
40
|
+
|
41
|
+
if current_batch
|
42
|
+
if current_batch.unlogged? && new_batch.logged?
|
43
|
+
fail ArgumentError,
|
44
|
+
"Already in an unlogged batch; can't start a logged batch."
|
45
|
+
end
|
46
|
+
return yield
|
47
|
+
end
|
48
|
+
|
49
|
+
begin
|
50
|
+
self.current_batch = new_batch
|
51
|
+
yield.tap { new_batch.apply }
|
52
|
+
ensure
|
53
|
+
self.current_batch = nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :keyspace
|
60
|
+
|
61
|
+
def current_batch
|
62
|
+
::Thread.current[batch_key]
|
63
|
+
end
|
64
|
+
|
65
|
+
def current_batch=(batch)
|
66
|
+
::Thread.current[batch_key] = batch
|
67
|
+
end
|
68
|
+
|
69
|
+
def batch_key
|
70
|
+
:"cequel-batch-#{object_id}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,26 +1,39 @@
|
|
1
1
|
module Cequel
|
2
|
-
|
3
2
|
module Metal
|
4
|
-
|
3
|
+
#
|
4
|
+
# Encapsulates a row specification (`WHERE` clause) specified by a CQL
|
5
|
+
# string
|
5
6
|
#
|
6
7
|
# @api private
|
7
8
|
#
|
8
9
|
class CqlRowSpecification
|
9
|
-
|
10
|
+
#
|
11
|
+
# Build a new row specification
|
12
|
+
#
|
13
|
+
# @param (see #initialize)
|
14
|
+
# @return [Array<CqlRowSpecification>]
|
15
|
+
#
|
10
16
|
def self.build(condition, bind_vars)
|
11
17
|
[new(condition, bind_vars)]
|
12
18
|
end
|
13
19
|
|
20
|
+
#
|
21
|
+
# Create a new row specification
|
22
|
+
#
|
23
|
+
# @param [String] condition CQL string representing condition
|
24
|
+
# @param [Array] bind_vars Bind variables
|
25
|
+
#
|
14
26
|
def initialize(condition, bind_vars)
|
15
27
|
@condition, @bind_vars = condition, bind_vars
|
16
28
|
end
|
17
29
|
|
30
|
+
#
|
31
|
+
# CQL and bind variables for this condition
|
32
|
+
#
|
33
|
+
# @return [Array] CQL string followed by zero or more bind variables
|
18
34
|
def cql
|
19
35
|
[@condition, *@bind_vars]
|
20
36
|
end
|
21
|
-
|
22
37
|
end
|
23
|
-
|
24
38
|
end
|
25
|
-
|
26
39
|
end
|
@@ -1,29 +1,58 @@
|
|
1
|
-
|
1
|
+
require 'forwardable'
|
2
2
|
|
3
|
+
module Cequel
|
3
4
|
module Metal
|
4
|
-
|
5
5
|
#
|
6
|
-
# Encapsulates a data set, specified as a
|
6
|
+
# Encapsulates a data set, specified as a table and optionally
|
7
7
|
# various query elements.
|
8
8
|
#
|
9
|
-
# @
|
9
|
+
# @example Data set representing entire contents of a table
|
10
|
+
# data_set = database[:posts]
|
11
|
+
#
|
12
|
+
# @example Data set limiting rows returned
|
13
|
+
# data_set = database[:posts].limit(10)
|
14
|
+
#
|
15
|
+
# @example Data set targeting only one partition
|
16
|
+
# data_set = database[:posts].where(blog_subdomain: 'cassandra')
|
17
|
+
#
|
18
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/select_r.html CQL documentation for SELECT
|
10
19
|
#
|
11
20
|
class DataSet
|
12
|
-
|
13
21
|
include Enumerable
|
14
22
|
extend Forwardable
|
15
23
|
|
16
|
-
|
17
|
-
|
24
|
+
# @return [Keyspace] keyspace that this data set's table resides in
|
25
|
+
attr_reader :keyspace
|
26
|
+
# @return [Symbol] name of the table that this data set retrieves data
|
27
|
+
# from
|
28
|
+
attr_reader :table_name
|
29
|
+
# @return [Array<Symbol>] columns that this data set restricts result
|
30
|
+
# rows to; empty if none
|
31
|
+
attr_reader :select_columns
|
32
|
+
# @return [Array<Symbol>] columns that this data set will select the TTLs
|
33
|
+
# of
|
34
|
+
attr_reader :ttl_columns
|
35
|
+
# @return [Array<Symbol>] columns that this data set will select the
|
36
|
+
# writetimes of
|
37
|
+
attr_reader :writetime_columns
|
38
|
+
# @return [Array<RowSpecification>] row specifications limiting the
|
39
|
+
# result rows returned by this data set
|
40
|
+
attr_reader :row_specifications
|
41
|
+
# @return [Hash<Symbol,Symbol>] map of column names to sort directions
|
42
|
+
attr_reader :sort_order
|
43
|
+
# @return [Integer] maximum number of rows to return, `nil` if no limit
|
44
|
+
attr_reader :row_limit
|
18
45
|
|
19
46
|
def_delegator :keyspace, :execute, :execute_cql
|
47
|
+
private :execute_cql
|
20
48
|
def_delegator :keyspace, :write
|
21
49
|
|
22
50
|
#
|
23
51
|
# @param table_name [Symbol] column family for this data set
|
24
|
-
# @param keyspace [Keyspace] keyspace this data set's
|
52
|
+
# @param keyspace [Keyspace] keyspace this data set's table lives in
|
25
53
|
#
|
26
54
|
# @see Keyspace#[]
|
55
|
+
# @api private
|
27
56
|
#
|
28
57
|
def initialize(table_name, keyspace)
|
29
58
|
@table_name, @keyspace = table_name, keyspace
|
@@ -34,22 +63,61 @@ module Cequel
|
|
34
63
|
#
|
35
64
|
# Insert a row into the column family.
|
36
65
|
#
|
37
|
-
# @param [Hash]
|
38
|
-
# @param [Options] options
|
39
|
-
# @option (see #
|
40
|
-
# @
|
66
|
+
# @param data [Hash] column-value pairs
|
67
|
+
# @param options [Options] options for persisting the row
|
68
|
+
# @option (see Writer#initialize)
|
69
|
+
# @return [void]
|
70
|
+
#
|
71
|
+
# @note `INSERT` statements will succeed even if a row at the specified
|
72
|
+
# primary key already exists. In this case, column values specified in
|
73
|
+
# the insert will overwrite the existing row.
|
74
|
+
# @note If a enclosed in a Keyspace#batch block, this method will be
|
75
|
+
# executed as part of the batch.
|
76
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/insert_r.html CQL documentation for INSERT
|
41
77
|
#
|
42
78
|
def insert(data, options = {})
|
43
79
|
inserter(options) { insert(data) }.execute
|
44
80
|
end
|
45
81
|
|
46
82
|
#
|
47
|
-
#
|
83
|
+
# Upsert data into one or more rows
|
84
|
+
#
|
85
|
+
# @overload update(column_values, options = {})
|
86
|
+
# Update the rows specified in the data set with new values
|
87
|
+
#
|
88
|
+
# @param column_values [Hash] map of column names to new values
|
89
|
+
# @param options [Options] options for persisting the column data
|
90
|
+
# @option (see #generate_upsert_options)
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# posts.where(blog_subdomain: 'cassandra', permalink: 'cequel').
|
94
|
+
# update(title: 'Announcing Cequel 1.0')
|
95
|
+
#
|
96
|
+
# @overload update(options = {}, &block)
|
97
|
+
# Construct an update statement consisting of multiple operations
|
98
|
+
#
|
99
|
+
# @param options [Options] options for persisting the data
|
100
|
+
# @option (see #generate_upsert_options)
|
101
|
+
# @yield DSL context for adding write operations
|
102
|
+
#
|
103
|
+
# @see Updater
|
104
|
+
# @since 1.0.0
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
# posts.where(blog_subdomain: 'bigdata', permalink: 'cql').update do
|
108
|
+
# set(title: 'Announcing Cequel 1.0')
|
109
|
+
# list_append(categories: 'ORMs')
|
110
|
+
# end
|
48
111
|
#
|
49
|
-
# @
|
50
|
-
#
|
51
|
-
# @
|
52
|
-
#
|
112
|
+
# @return [void]
|
113
|
+
#
|
114
|
+
# @note `UPDATE` statements will succeed even if targeting a row that
|
115
|
+
# does not exist. In this case a new row will be created.
|
116
|
+
# @note This statement will fail unless one or more rows are fully
|
117
|
+
# specified by primary key using `where`
|
118
|
+
# @note If a enclosed in a Keyspace#batch block, this method will be
|
119
|
+
# executed as part of the batch.
|
120
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/update_r.html CQL documentation for UPDATE
|
53
121
|
#
|
54
122
|
def update(*args, &block)
|
55
123
|
if block
|
@@ -60,24 +128,63 @@ module Cequel
|
|
60
128
|
end
|
61
129
|
end
|
62
130
|
|
63
|
-
|
64
|
-
|
131
|
+
#
|
132
|
+
# Increment one or more counter columns
|
133
|
+
#
|
134
|
+
# @param deltas [Hash<Symbol,Integer>] map of counter column names to
|
135
|
+
# amount by which to increment each column
|
136
|
+
# @return [void]
|
137
|
+
#
|
138
|
+
# @example
|
139
|
+
# post_analytics.
|
140
|
+
# where(blog_subdomain: 'cassandra', permalink: 'cequel').
|
141
|
+
# increment(pageviews: 10, tweets: 2)
|
142
|
+
#
|
143
|
+
# @note This can only be used on counter tables
|
144
|
+
# @since 0.5.0
|
145
|
+
# @see #decrement
|
146
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/../cql_using/use_counter_t.html CQL documentation for counter columns
|
147
|
+
#
|
148
|
+
def increment(deltas, options = {})
|
149
|
+
incrementer(options) { increment(deltas) }.execute
|
65
150
|
end
|
151
|
+
alias_method :incr, :increment
|
66
152
|
|
67
|
-
|
68
|
-
|
153
|
+
#
|
154
|
+
# Decrement one or more counter columns
|
155
|
+
#
|
156
|
+
# @param deltas [Hash<Symbol,Integer>] map of counter column names to
|
157
|
+
# amount by which to decrement each column
|
158
|
+
# @return [void]
|
159
|
+
#
|
160
|
+
# @see #increment
|
161
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/../cql_using/use_counter_t.html CQL documentation for counter columns
|
162
|
+
# @since 0.5.0
|
163
|
+
#
|
164
|
+
def decrement(deltas, options = {})
|
165
|
+
incrementer(options) { decrement(deltas) }.execute
|
69
166
|
end
|
70
167
|
alias_method :decr, :decrement
|
71
168
|
|
72
169
|
#
|
73
170
|
# Prepend element(s) to a list in the row(s) matched by this data set.
|
74
171
|
#
|
75
|
-
# @param [Symbol]
|
76
|
-
# @param [Object,Array]
|
77
|
-
#
|
78
|
-
# @
|
79
|
-
# @
|
80
|
-
# @
|
172
|
+
# @param column [Symbol] name of list column to prepend to
|
173
|
+
# @param elements [Object,Array] one element or an array of elements to
|
174
|
+
# prepend
|
175
|
+
# @param options [Options] options for persisting the column data
|
176
|
+
# @option (see Writer#initialize)
|
177
|
+
# @return [void]
|
178
|
+
#
|
179
|
+
# @example
|
180
|
+
# posts.list_prepend(:categories, ['CQL', 'ORMs'])
|
181
|
+
#
|
182
|
+
# @note If multiple elements are passed, they will appear in the list in
|
183
|
+
# reverse order.
|
184
|
+
# @note If a enclosed in a Keyspace#batch block, this method will be
|
185
|
+
# executed as part of the batch.
|
186
|
+
# @see #list_append
|
187
|
+
# @see #update
|
81
188
|
#
|
82
189
|
def list_prepend(column, elements, options = {})
|
83
190
|
updater(options) { list_prepend(column, elements) }.execute
|
@@ -86,11 +193,21 @@ module Cequel
|
|
86
193
|
#
|
87
194
|
# Append element(s) to a list in the row(s) matched by this data set.
|
88
195
|
#
|
89
|
-
# @param [Symbol]
|
90
|
-
# @param [Object,Array]
|
91
|
-
#
|
92
|
-
# @
|
93
|
-
# @
|
196
|
+
# @param column [Symbol] name of list column to append to
|
197
|
+
# @param elements [Object,Array] one element or an array of elements to
|
198
|
+
# append
|
199
|
+
# @param options [Options] options for persisting the column data
|
200
|
+
# @option (see Writer#initialize)
|
201
|
+
# @return [void]
|
202
|
+
#
|
203
|
+
# @example
|
204
|
+
# posts.list_append(:categories, ['CQL', 'ORMs'])
|
205
|
+
#
|
206
|
+
# @note If a enclosed in a Keyspace#batch block, this method will be
|
207
|
+
# executed as part of the batch.
|
208
|
+
# @see #list_append
|
209
|
+
# @see #update
|
210
|
+
# @since 1.0.0
|
94
211
|
#
|
95
212
|
def list_append(column, elements, options = {})
|
96
213
|
updater(options) { list_append(column, elements) }.execute
|
@@ -99,12 +216,20 @@ module Cequel
|
|
99
216
|
#
|
100
217
|
# Replace a list element at a specified index with a new value
|
101
218
|
#
|
102
|
-
# @param [Symbol]
|
103
|
-
# @param [Integer]
|
104
|
-
# @param [Object]
|
105
|
-
# @param [Options] options
|
106
|
-
# @option (see #
|
107
|
-
# @
|
219
|
+
# @param column [Symbol] name of list column
|
220
|
+
# @param index [Integer] which element to replace
|
221
|
+
# @param value [Object] new value at this index
|
222
|
+
# @param options [Options] options for persisting the data
|
223
|
+
# @option (see Writer#initialize)
|
224
|
+
# @return [void]
|
225
|
+
#
|
226
|
+
# @example
|
227
|
+
# posts.list_replace(:categories, 2, 'Object-Relational Mapper')
|
228
|
+
#
|
229
|
+
# @note if a enclosed in a Keyspace#batch block, this method will be
|
230
|
+
# executed as part of the batch.
|
231
|
+
# @see #update
|
232
|
+
# @since 1.0.0
|
108
233
|
#
|
109
234
|
def list_replace(column, index, value, options = {})
|
110
235
|
updater(options) { list_replace(column, index, value) }.execute
|
@@ -113,24 +238,43 @@ module Cequel
|
|
113
238
|
#
|
114
239
|
# Remove all occurrences of a given value from a list column
|
115
240
|
#
|
116
|
-
# @param [Symbol]
|
117
|
-
# @param [Object] value
|
118
|
-
# @param [Options] options for persisting the data
|
119
|
-
# @option (see #
|
120
|
-
# @
|
241
|
+
# @param column [Symbol] name of list column
|
242
|
+
# @param value [Object] value to remove
|
243
|
+
# @param options [Options] options for persisting the data
|
244
|
+
# @option (see Writer#initialize)
|
245
|
+
# @return [void]
|
246
|
+
#
|
247
|
+
# @example
|
248
|
+
# posts.list_remove(:categories, 'CQL3')
|
249
|
+
#
|
250
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
251
|
+
# executed as part of the batch.
|
252
|
+
# @see #list_remove_at
|
253
|
+
# @see #update
|
254
|
+
# @since 1.0.0
|
121
255
|
#
|
122
256
|
def list_remove(column, value, options = {})
|
123
257
|
updater(options) { list_remove(column, value) }.execute
|
124
258
|
end
|
125
259
|
|
126
260
|
#
|
127
|
-
#
|
261
|
+
# @overload list_remove_at(column, *positions, options = {})
|
262
|
+
# Remove the value from a given position or positions in a list column
|
263
|
+
#
|
264
|
+
# @param column [Symbol] name of list column
|
265
|
+
# @param positions [Integer] position(s) in list to remove value from
|
266
|
+
# @param options [Options] options for persisting the data
|
267
|
+
# @option (see Writer#initialize)
|
268
|
+
# @return [void]
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# posts.list_remove_at(:categories, 2)
|
128
272
|
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
273
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
274
|
+
# executed as part of the batch.
|
275
|
+
# @see #list_remove
|
276
|
+
# @see #update
|
277
|
+
# @since 1.0.0
|
134
278
|
#
|
135
279
|
def list_remove_at(column, *positions)
|
136
280
|
options = positions.extract_options!
|
@@ -138,13 +282,22 @@ module Cequel
|
|
138
282
|
end
|
139
283
|
|
140
284
|
#
|
141
|
-
#
|
285
|
+
# @overload map_remove(column, *keys, options = {})
|
286
|
+
# Remove a given key from a map column
|
142
287
|
#
|
143
|
-
#
|
144
|
-
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
#
|
288
|
+
# @param column [Symbol] name of map column
|
289
|
+
# @param keys [Object] map key to remove
|
290
|
+
# @param options [Options] options for persisting the data
|
291
|
+
# @option (see Writer#initialize)
|
292
|
+
# @return [void]
|
293
|
+
#
|
294
|
+
# @example
|
295
|
+
# posts.map_remove(:credits, 'editor')
|
296
|
+
#
|
297
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
298
|
+
# executed as part of the batch.
|
299
|
+
# @see #update
|
300
|
+
# @since 1.0.0
|
148
301
|
#
|
149
302
|
def map_remove(column, *keys)
|
150
303
|
options = keys.extract_options!
|
@@ -152,50 +305,112 @@ module Cequel
|
|
152
305
|
end
|
153
306
|
|
154
307
|
#
|
155
|
-
# Add one or more elements to a set
|
308
|
+
# Add one or more elements to a set column
|
309
|
+
#
|
310
|
+
# @param column [Symbol] name of set column
|
311
|
+
# @param values [Object,Set] value or values to add
|
312
|
+
# @param options [Options] options for persisting the data
|
313
|
+
# @option (see Writer#initialize)
|
314
|
+
# @return [void]
|
315
|
+
#
|
316
|
+
# @example
|
317
|
+
# posts.set_add(:tags, 'cql3')
|
156
318
|
#
|
157
|
-
# @
|
158
|
-
#
|
159
|
-
# @
|
160
|
-
# @
|
161
|
-
# @note if a enclosed in a Keyspace#batch block, this method will be executed as part of the batch.
|
319
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
320
|
+
# executed as part of the batch.
|
321
|
+
# @see #update
|
322
|
+
# @since 1.0.0
|
162
323
|
#
|
163
324
|
def set_add(column, values, options = {})
|
164
325
|
updater(options) { set_add(column, values) }.execute
|
165
326
|
end
|
166
327
|
|
167
328
|
#
|
168
|
-
# Remove
|
329
|
+
# Remove an element from a set
|
169
330
|
#
|
170
|
-
# @param [Symbol]
|
171
|
-
# @param [Object
|
172
|
-
# @param [Options] options for persisting the data
|
173
|
-
# @option (see #
|
174
|
-
# @
|
331
|
+
# @param column [Symbol] name of set column
|
332
|
+
# @param value [Object] value to remove
|
333
|
+
# @param options [Options] options for persisting the data
|
334
|
+
# @option (see Writer#initialize)
|
335
|
+
# @return [void]
|
336
|
+
#
|
337
|
+
# @example
|
338
|
+
# posts.set_remove(:tags, 'cql3')
|
339
|
+
#
|
340
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
341
|
+
# executed as part of the batch.
|
342
|
+
# @see #update
|
343
|
+
# @since 1.0.0
|
175
344
|
#
|
176
345
|
def set_remove(column, value, options = {})
|
177
346
|
updater(options) { set_remove(column, value) }.execute
|
178
347
|
end
|
179
348
|
|
180
349
|
#
|
181
|
-
# Update one or more map
|
350
|
+
# Update one or more keys in a map column
|
351
|
+
#
|
352
|
+
# @param column [Symbol] name of set column
|
353
|
+
# @param updates [Hash] map of map keys to new values
|
354
|
+
# @param options [Options] options for persisting the data
|
355
|
+
# @option (see Writer#initialize)
|
356
|
+
# @return [void]
|
182
357
|
#
|
183
|
-
# @
|
184
|
-
#
|
185
|
-
#
|
186
|
-
# @
|
187
|
-
#
|
358
|
+
# @example
|
359
|
+
# posts.map_update(:credits, 'editor' => 34)
|
360
|
+
#
|
361
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
362
|
+
# executed as part of the batch.
|
363
|
+
# @see #update
|
364
|
+
# @since 1.0.0
|
188
365
|
#
|
189
366
|
def map_update(column, updates, options = {})
|
190
367
|
updater(options) { map_update(column, updates) }.execute
|
191
368
|
end
|
192
369
|
|
193
370
|
#
|
194
|
-
#
|
371
|
+
# @overload delete(options = {})
|
372
|
+
# Delete one or more rows from the table
|
373
|
+
#
|
374
|
+
# @param options [Options] options for persistence
|
375
|
+
# @option (See Writer#initialize)
|
376
|
+
#
|
377
|
+
# @example
|
378
|
+
# posts.where(blog_subdomain: 'cassandra', permalink: 'cequel').
|
379
|
+
# delete
|
380
|
+
#
|
381
|
+
# @overload delete(*columns, options = {})
|
382
|
+
# Delete data from given columns in the specified rows. This is
|
383
|
+
# equivalent to setting columns to `NULL` in an SQL database.
|
384
|
+
#
|
385
|
+
# @param columns [Symbol] columns to remove
|
386
|
+
# @param options [Options] options for persistence
|
387
|
+
# @option (see Writer#initialize)
|
388
|
+
#
|
389
|
+
# @example
|
390
|
+
# posts.where(blog_subdomain: 'cassandra', permalink: 'cequel').
|
391
|
+
# delete(:body)
|
392
|
+
#
|
393
|
+
# @overload delete(options = {}, &block)
|
394
|
+
# Construct a `DELETE` statement with multiple operations (column
|
395
|
+
# deletions, collection element removals, etc.)
|
195
396
|
#
|
196
|
-
#
|
197
|
-
#
|
198
|
-
#
|
397
|
+
# @param options [Options] options for persistence
|
398
|
+
# @option (see Writer#initialize)
|
399
|
+
# @yield DSL context for construction delete statement
|
400
|
+
#
|
401
|
+
# @example
|
402
|
+
# posts.where(blog_subdomain: 'bigdata', permalink: 'cql').delete do
|
403
|
+
# delete_columns :body
|
404
|
+
# list_remove_at :categories, 2
|
405
|
+
# end
|
406
|
+
#
|
407
|
+
# @see Deleter
|
408
|
+
#
|
409
|
+
# @return [void]
|
410
|
+
#
|
411
|
+
# @note If enclosed in a Keyspace#batch block, this method will be
|
412
|
+
# executed as part of the batch.
|
413
|
+
# @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_reference/delete_r.html CQL documentation for DELETE
|
199
414
|
#
|
200
415
|
def delete(*columns, &block)
|
201
416
|
options = columns.extract_options!
|
@@ -211,7 +426,7 @@ module Cequel
|
|
211
426
|
#
|
212
427
|
# Select specified columns from this data set.
|
213
428
|
#
|
214
|
-
# @param
|
429
|
+
# @param columns [Symbol] columns columns to select
|
215
430
|
# @return [DataSet] new data set scoped to specified columns
|
216
431
|
#
|
217
432
|
def select(*columns)
|
@@ -223,9 +438,11 @@ module Cequel
|
|
223
438
|
#
|
224
439
|
# Return the remaining TTL for the specified columns from this data set.
|
225
440
|
#
|
226
|
-
# @param
|
441
|
+
# @param columns [Symbol] columns to select
|
227
442
|
# @return [DataSet] new data set scoped to specified columns
|
228
443
|
#
|
444
|
+
# @since 1.0.0
|
445
|
+
#
|
229
446
|
def select_ttl(*columns)
|
230
447
|
clone.tap do |data_set|
|
231
448
|
data_set.ttl_columns.concat(columns.flatten)
|
@@ -235,9 +452,11 @@ module Cequel
|
|
235
452
|
#
|
236
453
|
# Return the write time for the specified columns in the data set
|
237
454
|
#
|
238
|
-
# @param
|
455
|
+
# @param columns [Symbol] columns to select
|
239
456
|
# @return [DataSet] new data set scoped to specified columns
|
240
457
|
#
|
458
|
+
# @since 1.0.0
|
459
|
+
#
|
241
460
|
def select_writetime(*columns)
|
242
461
|
clone.tap do |data_set|
|
243
462
|
data_set.writetime_columns.concat(columns.flatten)
|
@@ -247,7 +466,7 @@ module Cequel
|
|
247
466
|
#
|
248
467
|
# Select specified columns from this data set, overriding chained scope.
|
249
468
|
#
|
250
|
-
# @param
|
469
|
+
# @param columns [Symbol,Array] columns to select
|
251
470
|
# @return [DataSet] new data set scoped to specified columns
|
252
471
|
#
|
253
472
|
def select!(*columns)
|
@@ -257,31 +476,40 @@ module Cequel
|
|
257
476
|
end
|
258
477
|
|
259
478
|
#
|
260
|
-
#
|
479
|
+
# Filter this data set with a row specification
|
480
|
+
#
|
481
|
+
# @overload where(column_values)
|
482
|
+
# @param column_values [Hash] Map of column name to values to match
|
261
483
|
#
|
262
|
-
#
|
263
|
-
#
|
264
|
-
#
|
265
|
-
# @
|
266
|
-
#
|
267
|
-
#
|
268
|
-
#
|
269
|
-
#
|
270
|
-
#
|
271
|
-
#
|
272
|
-
#
|
484
|
+
# @example
|
485
|
+
# database[:posts].where(title: 'Hey')
|
486
|
+
#
|
487
|
+
# @overload where(cql, *bind_vars)
|
488
|
+
# @param cql [String] CQL fragment representing `WHERE` statement
|
489
|
+
# @param bind_vars [Object] Bind variables for the CQL fragment
|
490
|
+
#
|
491
|
+
# @example
|
492
|
+
# DB[:posts].where('title = ?', 'Hey')
|
493
|
+
#
|
494
|
+
# @return [DataSet] New data set scoped to the row specification
|
273
495
|
#
|
274
496
|
def where(row_specification, *bind_vars)
|
275
497
|
clone.tap do |data_set|
|
276
|
-
data_set.row_specifications
|
277
|
-
concat(build_row_specifications(row_specification, bind_vars))
|
498
|
+
data_set.row_specifications
|
499
|
+
.concat(build_row_specifications(row_specification, bind_vars))
|
278
500
|
end
|
279
501
|
end
|
280
502
|
|
503
|
+
#
|
504
|
+
# Replace existing row specifications
|
505
|
+
#
|
506
|
+
# @see #where
|
507
|
+
# @return [DataSet] New data set with only row specifications given
|
508
|
+
#
|
281
509
|
def where!(row_specification, *bind_vars)
|
282
510
|
clone.tap do |data_set|
|
283
|
-
data_set.row_specifications
|
284
|
-
replace(build_row_specifications(row_specification, bind_vars))
|
511
|
+
data_set.row_specifications
|
512
|
+
.replace(build_row_specifications(row_specification, bind_vars))
|
285
513
|
end
|
286
514
|
end
|
287
515
|
|
@@ -296,10 +524,13 @@ module Cequel
|
|
296
524
|
end
|
297
525
|
|
298
526
|
#
|
299
|
-
# Control how the result rows are sorted
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
527
|
+
# Control how the result rows are sorted
|
528
|
+
#
|
529
|
+
# @param pairs [Hash] Map of column name to sort direction
|
530
|
+
# @return [DataSet] new data set with the specified ordering
|
531
|
+
#
|
532
|
+
# @note The only valid ordering column is the first clustering column
|
533
|
+
# @since 1.0.0
|
303
534
|
#
|
304
535
|
def order(pairs)
|
305
536
|
clone.tap do |data_set|
|
@@ -311,89 +542,74 @@ module Cequel
|
|
311
542
|
# Enumerate over rows in this data set. Along with #each, all other
|
312
543
|
# Enumerable methods are implemented.
|
313
544
|
#
|
314
|
-
# @
|
315
|
-
#
|
545
|
+
# @overload each
|
546
|
+
# @return [Enumerator] enumerator for rows, if no block given
|
547
|
+
#
|
548
|
+
# @overload each(&block)
|
549
|
+
# @yield [Hash] result rows
|
550
|
+
# @return [void]
|
551
|
+
#
|
552
|
+
# @return [Enumerator,void]
|
316
553
|
#
|
317
554
|
def each
|
318
|
-
|
319
|
-
|
320
|
-
keyspace.execute(*cql).fetch do |row|
|
321
|
-
yield Row.from_result_row(row)
|
322
|
-
end
|
323
|
-
rescue EmptySubquery
|
324
|
-
# Noop -- yield no results
|
325
|
-
end
|
326
|
-
else
|
327
|
-
enum_for(:each)
|
328
|
-
end
|
555
|
+
return enum_for(:each) unless block_given?
|
556
|
+
execute_cql(*cql).fetch { |row| yield Row.from_result_row(row) }
|
329
557
|
end
|
330
558
|
|
331
559
|
#
|
332
560
|
# @return [Hash] the first row in this data set
|
333
561
|
#
|
334
562
|
def first
|
335
|
-
row =
|
563
|
+
row = execute_cql(*limit(1).cql).fetch_row
|
336
564
|
Row.from_result_row(row)
|
337
|
-
rescue EmptySubquery
|
338
|
-
nil
|
339
565
|
end
|
340
566
|
|
341
567
|
#
|
342
568
|
# @return [Fixnum] the number of rows in this data set
|
343
569
|
#
|
344
570
|
def count
|
345
|
-
|
346
|
-
rescue EmptySubquery
|
347
|
-
0
|
571
|
+
execute_cql(*count_cql).fetch_row['count']
|
348
572
|
end
|
349
573
|
|
350
574
|
#
|
351
|
-
# @return [String] CQL
|
575
|
+
# @return [String] CQL `SELECT` statement encoding this data set's scope.
|
352
576
|
#
|
353
577
|
def cql
|
354
|
-
statement = Statement.new
|
355
|
-
append(select_cql)
|
356
|
-
append(" FROM #{table_name}")
|
357
|
-
append(*row_specifications_cql)
|
358
|
-
append(sort_order_cql)
|
359
|
-
append(limit_cql)
|
360
|
-
args
|
578
|
+
statement = Statement.new
|
579
|
+
.append(select_cql)
|
580
|
+
.append(" FROM #{table_name}")
|
581
|
+
.append(*row_specifications_cql)
|
582
|
+
.append(sort_order_cql)
|
583
|
+
.append(limit_cql)
|
584
|
+
.args
|
361
585
|
end
|
362
586
|
|
363
587
|
#
|
364
588
|
# @return [String] CQL statement to get count of rows in this data set
|
365
589
|
#
|
366
590
|
def count_cql
|
367
|
-
Statement.new
|
368
|
-
append("SELECT COUNT(*) FROM #{table_name}")
|
369
|
-
append(*row_specifications_cql)
|
370
|
-
append(limit_cql).args
|
591
|
+
Statement.new
|
592
|
+
.append("SELECT COUNT(*) FROM #{table_name}")
|
593
|
+
.append(*row_specifications_cql)
|
594
|
+
.append(limit_cql).args
|
371
595
|
end
|
372
596
|
|
597
|
+
#
|
598
|
+
# @return [String]
|
599
|
+
#
|
373
600
|
def inspect
|
374
|
-
"#<#{self.class.name}:
|
601
|
+
"#<#{self.class.name}: " \
|
602
|
+
"#{CassandraCQL::Statement.sanitize(cql.first, cql[1..-1])}>"
|
375
603
|
end
|
376
604
|
|
605
|
+
#
|
606
|
+
# @return [Boolean]
|
607
|
+
#
|
377
608
|
def ==(other)
|
378
609
|
cql == other.cql
|
379
610
|
end
|
380
611
|
|
381
|
-
|
382
|
-
Inserter.new(self, options, &block)
|
383
|
-
end
|
384
|
-
|
385
|
-
def updater(options = {}, &block)
|
386
|
-
Updater.new(self, options, &block)
|
387
|
-
end
|
388
|
-
|
389
|
-
def incrementer(options = {}, &block)
|
390
|
-
Incrementer.new(self, options, &block)
|
391
|
-
end
|
392
|
-
|
393
|
-
def deleter(options = {}, &block)
|
394
|
-
Deleter.new(self, options, &block)
|
395
|
-
end
|
396
|
-
|
612
|
+
# @private
|
397
613
|
def row_specifications_cql
|
398
614
|
if row_specifications.any?
|
399
615
|
cql_fragments, bind_vars = [], []
|
@@ -407,11 +623,30 @@ module Cequel
|
|
407
623
|
end
|
408
624
|
end
|
409
625
|
|
626
|
+
# @private
|
627
|
+
def updater(options = {}, &block)
|
628
|
+
Updater.new(self, options, &block)
|
629
|
+
end
|
630
|
+
|
631
|
+
# @private
|
632
|
+
def deleter(options = {}, &block)
|
633
|
+
Deleter.new(self, options, &block)
|
634
|
+
end
|
635
|
+
|
410
636
|
protected
|
637
|
+
|
411
638
|
attr_writer :row_limit
|
412
639
|
|
413
640
|
private
|
414
641
|
|
642
|
+
def inserter(options = {}, &block)
|
643
|
+
Inserter.new(self, options, &block)
|
644
|
+
end
|
645
|
+
|
646
|
+
def incrementer(options = {}, &block)
|
647
|
+
Incrementer.new(self, options, &block)
|
648
|
+
end
|
649
|
+
|
415
650
|
def initialize_copy(source)
|
416
651
|
super
|
417
652
|
@select_columns = source.select_columns.clone
|
@@ -426,11 +661,11 @@ module Cequel
|
|
426
661
|
ttl_columns.map { |column| "TTL(#{column})" } +
|
427
662
|
writetime_columns.map { |column| "WRITETIME(#{column})" }
|
428
663
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
664
|
+
if all_columns.any?
|
665
|
+
"SELECT #{all_columns.join(',')}"
|
666
|
+
else
|
667
|
+
'SELECT *'
|
668
|
+
end
|
434
669
|
end
|
435
670
|
|
436
671
|
def limit_cql
|
@@ -439,23 +674,25 @@ module Cequel
|
|
439
674
|
|
440
675
|
def sort_order_cql
|
441
676
|
if sort_order.any?
|
442
|
-
order = sort_order
|
443
|
-
map { |column, direction| "#{column} #{direction.to_s.upcase}" }
|
444
|
-
join(', ')
|
677
|
+
order = sort_order
|
678
|
+
.map { |column, direction| "#{column} #{direction.to_s.upcase}" }
|
679
|
+
.join(', ')
|
445
680
|
" ORDER BY #{order}"
|
446
681
|
end
|
447
682
|
end
|
448
683
|
|
449
684
|
def build_row_specifications(row_specification, bind_vars)
|
450
685
|
case row_specification
|
451
|
-
when Hash
|
452
|
-
|
453
|
-
|
686
|
+
when Hash
|
687
|
+
RowSpecification.build(row_specification)
|
688
|
+
when String
|
689
|
+
CqlRowSpecification.build(row_specification, bind_vars)
|
690
|
+
else
|
691
|
+
fail ArgumentError,
|
692
|
+
"Invalid argument #{row_specification.inspect}; " \
|
693
|
+
"expected Hash or String"
|
454
694
|
end
|
455
695
|
end
|
456
|
-
|
457
696
|
end
|
458
|
-
|
459
697
|
end
|
460
|
-
|
461
698
|
end
|