sessionm-cassandra_object 4.0.27 → 4.0.28

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c93aa37334ac497b7c97b5c0a1c04350502e230
4
- data.tar.gz: 894c0e7ffac48271d0efa1b75defe0c67f7c3b47
3
+ metadata.gz: 23762bc97b24f059702d33a82198651dc12a5849
4
+ data.tar.gz: e5bdeca74f220ad8ade8f35a20b3751efd256eec
5
5
  SHA512:
6
- metadata.gz: 4162a2b08feefbe4ed8cffa60826421344b6982f4e82b31627495dcf2e6dcfbe2f3af4cc666051918a868d2e410a9d97077f34c14e2d651c164206870a24684d
7
- data.tar.gz: 936877179c08b6e3b3ffdf4d74d7384bc3da5e32dbafb29f4d361daa10b2a417be76e20fee99139858a7db7399aa495400112aee04a4882258eef77d9e899c70
6
+ metadata.gz: ffff8841ff8da649d139ddc24d54c0a28bbba823fbe25ec7a00cde71a3685bc33e2ac92b1973a09208f419ef0660a03a2ae840dc008bd4af57ed3f8120399a39
7
+ data.tar.gz: 88af7c90d6177d05afaf0d37f0eee2ecc563dd4ea9a48e3195d587dad18e88768f5f40389be12eedac86554de24c507cca1f14af4f9a33711feb4d79cf301312
@@ -99,8 +99,13 @@ module CassandraObject
99
99
 
100
100
  insert_into_options = ttl ? " USING TTL #{ttl}" : ''
101
101
 
102
+ key_fields = get_key_fields(column_family)
103
+ column_fields = get_column_fields(column_family)
104
+
105
+ key_parts = get_parts(column_family, key, key_fields)
102
106
  insert_query = values.map do |name, value|
103
- " INSERT INTO \"#{column_family}\" (#{KEY_FIELD}, #{NAME_FIELD}, #{VALUE_FIELD}) VALUES (#{escape(key, key_type(column_family))}, #{escape(name, name_type(column_family))}, #{escape(value, value_type(column_family))})#{insert_into_options}"
107
+ column_parts = get_parts(column_family, name, column_fields)
108
+ " INSERT INTO \"#{column_family}\" (#{key_fields.map(&:first).join(', ')}, #{column_fields.map(&:first).join(', ')}, #{VALUE_FIELD}) VALUES (#{key_parts.map { |f, v| escape(v, get_type(column_family, f)) }.join(', ')}, #{column_parts.map { |f, v| escape(v, get_type(column_family, f)) }.join(', ')}, #{escape(value, value_type(column_family))})#{insert_into_options}"
104
109
  end.join("\n")
105
110
 
106
111
  if batch_mode?
@@ -118,12 +123,13 @@ module CassandraObject
118
123
  async = opts.try(:[], :async)
119
124
 
120
125
  columns = columns_options.flatten.compact
126
+ column_fields = get_column_fields(column_family)
121
127
 
122
128
  query =
123
129
  if columns.size == 1
124
- "SELECT #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))} AND #{NAME_FIELD} = #{escape(columns.first, name_type(column_family))}"
130
+ "SELECT #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{key_clause(column_family, key)} AND #{column_clause(column_family, columns.first)}"
125
131
  else
126
- "SELECT #{NAME_FIELD}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))}"
132
+ "SELECT #{column_fields.map(&:first).join(', ')}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{key_clause(column_family, key)}"
127
133
  end
128
134
 
129
135
  result = async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
@@ -132,7 +138,7 @@ module CassandraObject
132
138
  if columns.size == 1
133
139
  result.size > 0 ? result.first[VALUE_FIELD] : nil
134
140
  else
135
- data = result.inject({}) { |hsh, row| hsh[row[NAME_FIELD]] = row[VALUE_FIELD]; hsh }
141
+ data = result.inject({}) { |hsh, row| hsh[column_string(row, column_fields)] = row[VALUE_FIELD]; hsh }
136
142
  columns.size > 0 ? data.slice(*columns.map(&:to_s)) : data
137
143
  end
138
144
  end
@@ -142,7 +148,7 @@ module CassandraObject
142
148
 
143
149
  name_fields = columns.map { |c| escape(c, name_type(column_family)) }.join(', ')
144
150
 
145
- query = "SELECT #{NAME_FIELD}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{NAME_FIELD} IN(#{name_fields}) AND #{KEY_FIELD} = #{escape(key, key_type(column_family))}"
151
+ query = "SELECT #{NAME_FIELD}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{NAME_FIELD} IN(#{name_fields}) AND #{key_clause(column_family, key)};"
146
152
 
147
153
  result = async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
148
154
  return result if async
@@ -158,7 +164,7 @@ module CassandraObject
158
164
 
159
165
  name_fields = columns.map { |c| "'#{c}'" }.join(', ')
160
166
 
161
- query = "SELECT #{NAME_FIELD}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{NAME_FIELD} IN(#{name_fields}) AND #{KEY_FIELD} = #{escape(key, key_type(column_family))}"
167
+ query = "SELECT #{NAME_FIELD}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{NAME_FIELD} IN(#{name_fields}) AND #{key_clause(column_family, key)};"
162
168
 
163
169
  result = async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
164
170
  return result if async
@@ -176,7 +182,7 @@ module CassandraObject
176
182
  fields = [fields] unless fields.is_a?(Array)
177
183
 
178
184
  fields.each do |field|
179
- query = "UPDATE \"#{column_family}\" SET #{VALUE_FIELD} = #{VALUE_FIELD} + #{by} WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))} AND #{NAME_FIELD} = #{escape(field, name_type(column_family))};"
185
+ query = "UPDATE \"#{column_family}\" SET #{VALUE_FIELD} = #{VALUE_FIELD} + #{by} WHERE #{key_clause(column_family, key)} AND #{column_clause(column_family, field)};"
180
186
  async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
181
187
  end
182
188
  end
@@ -186,7 +192,7 @@ module CassandraObject
186
192
  fields = [fields] unless fields.is_a?(Array)
187
193
 
188
194
  hash.each do |field, by|
189
- query = "UPDATE \"#{column_family}\" SET #{VALUE_FIELD} = #{VALUE_FIELD} + #{by} WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))} AND #{NAME_FIELD} = #{escape(field, name_type(column_family))};"
195
+ query = "UPDATE \"#{column_family}\" SET #{VALUE_FIELD} = #{VALUE_FIELD} + #{by} WHERE #{key_clause(column_family, key)} AND #{column_clause(column_family, field)};"
190
196
  async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
191
197
  end
192
198
  end
@@ -197,9 +203,9 @@ module CassandraObject
197
203
 
198
204
  query =
199
205
  if args.first.nil? || args.first.is_a?(Hash)
200
- "DELETE FROM \"#{column_family}\" WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))};"
206
+ "DELETE FROM \"#{column_family}\" WHERE #{key_clause(column_family, key)};"
201
207
  else
202
- "DELETE \"#{column_family}\" WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))} AND #{NAME_FIELD} = #{escape(args.first, name_type(column_family))};"
208
+ "DELETE FROM \"#{column_family}\" WHERE #{key_clause(column_family, key)} AND #{column_clause(column_family, args.first)};"
203
209
  end
204
210
 
205
211
  async ? self.execute_async(query, execute_options(opts)) : self.execute(query, execute_options(opts))
@@ -227,15 +233,21 @@ module CassandraObject
227
233
  def get_slice(column_family, key, column, start, finish, count, reversed, consistency, opts={})
228
234
  opts[:consistency] = consistency
229
235
 
230
- query = "SELECT * FROM \"#{column_family}\" WHERE #{KEY_FIELD} = #{escape(key, key_type(column_family))}"
231
- query << " AND #{NAME_FIELD} = #{escape(column, name_type(column_family))}" if column
232
- query << " AND #{NAME_FIELD} >= #{escape(start, name_type(column_family))}" unless start.empty?
233
- query << " AND #{NAME_FIELD} <= #{escape(finish, name_type(column_family))}" unless finish.empty?
234
- query << " ORDER BY #{NAME_FIELD} #{reverse_comparator(column_family) ? 'ASC' : 'DESC'}" if reversed
236
+ column_fields = get_column_fields(column_family)
237
+
238
+ query = "SELECT #{column_fields.map(&:first).join(', ')}, #{VALUE_FIELD} FROM \"#{column_family}\" WHERE #{key_clause(column_family, key)}"
239
+ query << " AND #{column_clause(column_family, column)}" if column
240
+ query << " AND #{column_clause(column_family, start, '>=')}" unless start.empty?
241
+ query << " AND #{column_clause(column_family, finish, '<=')}" unless finish.empty?
242
+ if reversed
243
+ direction = reverse_comparator(column_family) ? 'ASC' : 'DESC'
244
+ query << " ORDER BY "
245
+ query << column_fields.map { |f, _| "#{f} #{direction}" }.join(', ')
246
+ end
235
247
  query << " LIMIT #{count}"
236
248
 
237
249
  self.execute(query, execute_options(opts)).inject({}) do |results, row|
238
- results[decode(row[NAME_FIELD], name_type(column_family))] = decode(row[VALUE_FIELD], value_type(column_family))
250
+ results[column_string(row, column_fields)] = decode(row[VALUE_FIELD], value_type(column_family))
239
251
  results
240
252
  end
241
253
  end
@@ -329,32 +341,87 @@ CQL
329
341
  end
330
342
 
331
343
  def key_type(column_family)
332
- self.cluster.keyspace(keyspace).table(column_family).column(KEY_FIELD).type.kind
344
+ get_type(column_family, KEY_FIELD)
333
345
  end
334
346
 
335
347
  def name_type(column_family)
336
- self.cluster.keyspace(keyspace).table(column_family).column(NAME_FIELD).type.kind
348
+ get_type(column_family, NAME_FIELD)
337
349
  end
338
350
 
339
351
  def value_type(column_family)
340
- self.cluster.keyspace(keyspace).table(column_family).column(VALUE_FIELD).type.kind
352
+ get_type(column_family, VALUE_FIELD)
353
+ end
354
+
355
+ def get_type(column_family, field)
356
+ cluster.keyspace(keyspace).table(column_family).column(field).type.kind
357
+ end
358
+
359
+ def get_key_fields(column_family)
360
+ cluster.keyspace(keyspace).table(column_family).columns.select { |c| c.name =~ /^key/ }.map { |c| [c.name, c.type.kind] }
361
+ end
362
+
363
+ def get_column_fields(column_family)
364
+ cluster.keyspace(keyspace).table(column_family).columns.select { |c| c.name =~ /^column/ }.map { |c| [c.name, c.type.kind] }
341
365
  end
342
366
 
343
367
  def reverse_comparator(column_family)
344
368
  self.cluster.keyspace(keyspace).table(column_family).send(:clustering_order).first == :desc
345
369
  end
346
370
 
371
+ def get_parts(column_family, val, fields)
372
+ val =
373
+ if fields.size > 1
374
+ Cassandra::Composite.new_from_packed(val.dup).parts
375
+ else
376
+ [val]
377
+ end
378
+
379
+ fields.each_with_index.map { |(field, type), idx| [field, normalize_composite_key_part(val[idx], type), type] }
380
+ end
381
+
382
+ def key_clause(column_family, val)
383
+ clause(column_family, val, get_key_fields(column_family))
384
+ end
385
+
386
+ def column_clause(column_family, val, operator='=')
387
+ clause(column_family, val, get_column_fields(column_family), operator)
388
+ end
389
+
390
+ def clause(column_family, val, fields, operator='=')
391
+ if operator == '='
392
+ get_parts(column_family, val, fields).map { |field, val, type| "#{field} #{operator} #{escape(val, type)}" }.join(' AND ')
393
+ else
394
+ field, val, type = get_parts(column_family, val, fields).first
395
+ "#{field} #{operator} #{escape(val, type)}"
396
+ end
397
+ end
398
+
347
399
  def escape(str, type)
348
400
  case type
349
401
  when :timeuuid
350
402
  convert_str_to_timeuuid str
351
403
  when :blob
352
404
  convert_str_to_hex str
405
+ when :int, :bigint
406
+ str
353
407
  else
354
408
  "'#{str}'"
355
409
  end
356
410
  end
357
411
 
412
+ def normalize_composite_key_part(val, type)
413
+ case type
414
+ when :timeuuid
415
+ SimpleUUID::UUID.new(val).to_s
416
+ when :int
417
+ val.unpack('N').first
418
+ when :bigint
419
+ Cassandra::Long.new(val).to_i
420
+ else
421
+ val
422
+ end
423
+ end
424
+
358
425
  def decode(val, type)
359
426
  case type
360
427
  when :timeuuid
@@ -373,6 +440,15 @@ CQL
373
440
  def convert_str_to_hex(str)
374
441
  '0x' << str.unpack('H*').first
375
442
  end
443
+
444
+ def column_string(row, fields)
445
+ if fields.size > 1
446
+ parts = fields.map { |f, t| decode(row[f], t) }
447
+ Cassandra::Composite.new(*parts).to_s
448
+ else
449
+ row[NAME_FIELD]
450
+ end
451
+ end
376
452
  end
377
453
  end
378
454
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'sessionm-cassandra_object'
5
- s.version = '4.0.27'
5
+ s.version = '4.0.28'
6
6
  s.description = 'Cassandra ActiveModel'
7
7
  s.summary = 'Cassandra ActiveModel'
8
8
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sessionm-cassandra_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.27
4
+ version: 4.0.28
5
5
  platform: ruby
6
6
  authors:
7
7
  - Doug Youch
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-12-05 00:00:00.000000000 Z
12
+ date: 2017-12-06 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Cassandra ActiveModel
15
15
  email: doug@sessionm.com