cequel 1.0.0.rc1 → 1.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|