Class: Cequel::DataSet

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/cequel/data_set.rb

Overview

TODO:

Support ALTER, CREATE, CREATE INDEX, DROP

Encapsulates a data set, specified as a column family and optionally various query elements.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(column_family, keyspace) ⇒ DataSet

Returns a new instance of DataSet.

Parameters:

  • column_family (Symbol)

    column family for this data set

  • keyspace (Keyspace)

    keyspace this data set’s column family lives in

See Also:



25
26
27
28
# File 'lib/cequel/data_set.rb', line 25

def initialize(column_family, keyspace)
  @column_family, @keyspace = column_family, keyspace
  @select_columns, @select_options, @row_specifications = [], {}, []
end

Instance Attribute Details

#column_familySymbol (readonly)

Returns the name of the column family this data set draws from.

Returns:

  • (Symbol)

    the name of the column family this data set draws from



17
18
19
# File 'lib/cequel/data_set.rb', line 17

def column_family
  @column_family
end

#consistency(consistency) ⇒ DataSet

Add consistency option for data set retrieval

Parameters:

  • consistency (:one, :quorum, :local_quorum, :each_quorum)

Returns:

  • (DataSet)

    new data set with specified consistency



160
161
162
# File 'lib/cequel/data_set.rb', line 160

def consistency(consistency)
  clone.tap { |data_set| data_set.consistency = consistency.to_sym }
end

#keyspaceKeyspace (readonly)

Returns the keyspace this data set lives in.

Returns:

  • (Keyspace)

    the keyspace this data set lives in



14
15
16
# File 'lib/cequel/data_set.rb', line 14

def keyspace
  @keyspace
end

#limit(limit) ⇒ DataSet

Limit the number of rows returned by this data set

Parameters:

  • limit (Integer)

    maximum number of rows to return

Returns:

  • (DataSet)

    new data set scoped with given limit



199
200
201
# File 'lib/cequel/data_set.rb', line 199

def limit(limit)
  clone.tap { |data_set| data_set.limit = limit }
end

#row_specificationsObject (readonly)

Returns the value of attribute row_specifications.



276
277
278
# File 'lib/cequel/data_set.rb', line 276

def row_specifications
  @row_specifications
end

#select_columnsObject (readonly)

Returns the value of attribute select_columns.



276
277
278
# File 'lib/cequel/data_set.rb', line 276

def select_columns
  @select_columns
end

#select_optionsObject (readonly)

Returns the value of attribute select_options.



276
277
278
# File 'lib/cequel/data_set.rb', line 276

def select_options
  @select_options
end

Instance Method Details

#==(other) ⇒ Object



272
273
274
# File 'lib/cequel/data_set.rb', line 272

def ==(other)
  cql == other.cql
end

#countFixnum

Returns the number of rows in this data set.

Returns:

  • (Fixnum)

    the number of rows in this data set



237
238
239
240
241
# File 'lib/cequel/data_set.rb', line 237

def count
  @keyspace.execute(*count_cql).fetch_row['count']
rescue EmptySubquery
  0
end

#count_cqlString

Returns CQL statement to get count of rows in this data set.

Returns:

  • (String)

    CQL statement to get count of rows in this data set



260
261
262
263
264
265
266
# File 'lib/cequel/data_set.rb', line 260

def count_cql
  Statement.new.
    append("SELECT COUNT(*) FROM #{@column_family}").
    append(consistency_cql).
    append(*row_specifications_cql).
    append(limit_cql).args
end

#cqlString

Returns CQL select statement encoding this data set’s scope.

Returns:

  • (String)

    CQL select statement encoding this data set’s scope.

Raises:

  • (EmptySubquery)

    if row specifications use a subquery that returns no results



247
248
249
250
251
252
253
254
255
# File 'lib/cequel/data_set.rb', line 247

def cql
  statement = Statement.new.
    append(*select_cql).
    append(" FROM #{@column_family}").
    append(consistency_cql).
    append(*row_specifications_cql).
    append(limit_cql).
    args
end

#decrement(data, options = {}) ⇒ Object Also known as: decr



85
86
87
# File 'lib/cequel/data_set.rb', line 85

def decrement(data, options = {})
  increment(Hash[data.map { |column, count| [column, -count] }], options)
end

#delete(*columns) ⇒ Object

Note:

if a enclosed in a Keyspace#batch block, this method will be executed as part of the batch.

Delete data from the column family

Parameters:

  • columns

    zero or more columns to delete. Deletes the entire row if none specified.

  • options

    persistence options



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/cequel/data_set.rb', line 97

def delete(*columns)
  options = columns.extract_options!
  column_aliases = columns.empty? ? '' : " #{columns.join(', ')}"
  statement = Statement.new.append('DELETE')
  statement = statement.append(' ?', columns) if columns.any?
  statement = statement.
    append(" FROM #{@column_family}").
    append(generate_upsert_options(options)).
    append(*row_specifications_cql)

  @keyspace.write(*statement.args)
rescue EmptySubquery
  # Noop -- no rows to delete
end

#each {|Hash| ... } ⇒ Enumerator

Enumerate over rows in this data set. Along with #each, all other Enumerable methods are implemented.

Yields:

  • (Hash)

    result rows

Returns:

  • (Enumerator)

    enumerator for rows, if no block given



210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/cequel/data_set.rb', line 210

def each
  if block_given?
    begin
      @keyspace.execute(*cql).fetch do |row|
        yield row.to_hash.with_indifferent_access
      end
    rescue EmptySubquery
      # Noop -- yield no results
    end
  else
    enum_for(:each)
  end
end

#firstHash

Returns the first row in this data set.

Returns:

  • (Hash)

    the first row in this data set



227
228
229
230
231
232
# File 'lib/cequel/data_set.rb', line 227

def first
  row = @keyspace.execute(*limit(1).cql).fetch_row
  row.to_hash.with_indifferent_access if row
rescue EmptySubquery
  nil
end

#increment(data, options = {}) ⇒ Object Also known as: incr



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/cequel/data_set.rb', line 68

def increment(data, options = {})
  operations = data.map do |key, value|
    operator = value < 0 ? '-' : '+'
    "? = ? #{operator} ?"
  end
  statement = Statement.new.
    append("UPDATE #{@column_family}").
    append(generate_upsert_options(options)).
    append(
      " SET " << operations.join(', '),
      *data.flat_map { |column, count| [column, column, count.abs] }
    ).append(*row_specifications_cql)

  @keyspace.write(*statement.args)
end

#insert(data, options = {}) ⇒ Object

Note:

if a enclosed in a Keyspace#batch block, this method will be executed as part of the batch.

Insert a row into the column family.

Parameters:

  • data (Hash)

    column-value pairs. The first entry must be the key column.

  • options (Options) (defaults to: {})

    options for persisting the row

Options Hash (options):

  • :consistency (Symbol, String)

    required consistency for the write

  • :ttl (Integer)

    time-to-live in seconds for the written data

  • :timestamp (Time, Integer)

    the timestamp associated with the column values



38
39
40
41
42
43
44
45
# File 'lib/cequel/data_set.rb', line 38

def insert(data, options = {})
  options.symbolize_keys!
  cql = "INSERT INTO #{@column_family}" <<
    " (?) VALUES (?)" <<
    generate_upsert_options(options)

  @keyspace.write(cql, data.keys, data.values)
end

#inspectObject



268
269
270
# File 'lib/cequel/data_set.rb', line 268

def inspect
  "#<#{self.class.name}: #{CassandraCQL::Statement.sanitize(cql.first, cql[1..-1])}>"
end

#select(*columns) ⇒ DataSet

Select specified columns from this data set.

Parameters:

  • *columns (Symbol, Array)

    columns to select

Returns:

  • (DataSet)

    new data set scoped to specified columns



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/cequel/data_set.rb', line 128

def select(*columns)
  options = columns.extract_options!.symbolize_keys
  clone.tap do |data_set|
    if columns.length == 1 && Range === columns.first
      range = columns.first
      options[:from] = range.first
      options[:to] = range.last
    else
      data_set.select_columns.concat(columns.flatten)
    end
    data_set.select_options.merge!(options)
  end
end

#select!(*columns) ⇒ DataSet

Select specified columns from this data set, overriding chained scope.

Parameters:

  • *columns (Symbol, Array)

    columns to select

Returns:

  • (DataSet)

    new data set scoped to specified columns



148
149
150
151
152
# File 'lib/cequel/data_set.rb', line 148

def select!(*columns)
  clone.tap do |data_set|
    data_set.select_columns.replace(columns.flatten)
  end
end

#truncateObject

Note:

This method always executes immediately, even if called within a batch block. This method does not respect scoped row specifications.

Remove all data from the column family.

See Also:



118
119
120
# File 'lib/cequel/data_set.rb', line 118

def truncate
  @keyspace.execute("TRUNCATE #{@column_family}")
end

#update(data, options = {}) ⇒ Object

TODO:

support counter columns

Note:

if a enclosed in a Keyspace#batch block, this method will be executed as part of the batch.

Update rows

Parameters:

  • data (Hash)

    column-value pairs

  • options (Options) (defaults to: {})

    options for persisting the column data

Options Hash (options):

  • :consistency (Symbol, String)

    required consistency for the write

  • :ttl (Integer)

    time-to-live in seconds for the written data

  • :timestamp (Time, Integer)

    the timestamp associated with the column values



57
58
59
60
61
62
63
64
65
66
# File 'lib/cequel/data_set.rb', line 57

def update(data, options = {})
  statement = Statement.new.
    append("UPDATE #{@column_family}").
    append(generate_upsert_options(options)).
    append(" SET " << data.keys.map { |k| "? = ?" }.join(', '), *data.to_a.flatten).
    append(*row_specifications_cql)
  @keyspace.write(*statement.args)
rescue EmptySubquery
  # Noop -- no rows to update
end

#where(row_specification, *bind_vars) ⇒ DataSet

Add a row_specification to this data set

Examples:

Using a simple hash

DB[:posts].where(:title => 'Hey')

Using a CQL string

DB[:posts].where("title = 'Hey'")

Using a CQL string with bind variables

DB[:posts].where('title = ?', 'Hey')

Use another data set as an input – inner data set must return a single column per row!

DB[:blogs].where(:id => DB[:posts].select(:blog_id).where(:title => 'Hey'))

Parameters:

  • row_specification (Hash, String)

    row_specification statement

  • *bind_vars

    bind variables, only if using a CQL string row_specification

Returns:

  • (DataSet)

    new data set scoped to this row_specification



179
180
181
182
183
184
# File 'lib/cequel/data_set.rb', line 179

def where(row_specification, *bind_vars)
  clone.tap do |data_set|
    data_set.row_specifications.
      concat(build_row_specifications(row_specification, bind_vars))
  end
end

#where!(row_specification, *bind_vars) ⇒ Object



186
187
188
189
190
191
# File 'lib/cequel/data_set.rb', line 186

def where!(row_specification, *bind_vars)
  clone.tap do |data_set|
    data_set.row_specifications.
      replace(build_row_specifications(row_specification, bind_vars))
  end
end