ciql 0.2.0 → 0.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cfaee067156de5c21c4464d6e363f146e2af07d8
4
- data.tar.gz: 682634838722e35ba3d18e65ffc2df5cbc3d496d
3
+ metadata.gz: 7db3d33bb56c654865ff2e3ad3e46f6798c3093b
4
+ data.tar.gz: b4eccb76bd74c58d5e9be208b92d6c9b9bb9db29
5
5
  SHA512:
6
- metadata.gz: 0d8c09472cf40154fd5db8c60a13aa4d15b5fdd97df158b9c1015c9cc3c9b5928463f14612725b0022067f9812072a9f03b43e7c96aac560a0558dd67d7d969c
7
- data.tar.gz: ec2bcbd27c692293f6f480362663ea63f61e512ca8832781c70b936d24caeef037d3248e4bd5ebad1943d4537d405195193eede7d5354fdedfa7f0cb31f70577
6
+ metadata.gz: bb62bd623430c38c570892686f993b329b82dd7d35b709bbf6e35563f6a830eb7417ff86eccdd76db2f2325ce71b1e786f0e6ed9e31ca76bed099673310c5482
7
+ data.tar.gz: dc9ec7029fbfd82c131d665dc2a3cb157d9af6819a7b40c821c275ecb1c16ab454073d09b362f15d4337ea5f6394b031f39195be19b6daf1a4fc08ab2f9174db
data/lib/ciql.rb CHANGED
@@ -1,6 +1,16 @@
1
1
  module Ciql
2
2
  Error = Class.new(StandardError)
3
+
4
+ def self.logger
5
+ @logger ||= Logger.new($stdout)
6
+ end
7
+
8
+ def self.logger=(logger)
9
+ @logger = logger
10
+ end
3
11
  end
4
12
 
5
13
  require 'ciql/configuration'
14
+ require 'ciql/sanitize'
6
15
  require 'ciql/client/thrift'
16
+ require 'ciql/rails' if defined?(Rails)
@@ -0,0 +1,10 @@
1
+ module Ciql::Client
2
+ module Log
3
+ DEFAULT_LOG_FORMAT = 'CQL %{query} [%{consistency}] (%<duration>.3fms) '.freeze
4
+
5
+ def log(message)
6
+ return unless Ciql.logger.debug?
7
+ Ciql.logger.debug (@log_format or DEFAULT_LOG_FORMAT) % message
8
+ end
9
+ end
10
+ end
@@ -1,30 +1,51 @@
1
1
  require 'cassandra-cql/1.2'
2
2
  require 'cassandra-cql'
3
+ require 'benchmark'
4
+
5
+ require 'ciql/client/log'
3
6
 
4
7
  module Ciql::Client
5
8
  class Thrift < CassandraCQL::Database
9
+ include Log
10
+
6
11
  def initialize(options={})
12
+ options = options.dup
13
+ @log_format = options.delete(:log_format)
14
+
7
15
  port = options.delete(:port) { 9160 }
8
- hosts = options.delete(:host) { 'localhost' }.split(',')
16
+ hosts = options.delete(:host) { '127.0.0.1' }.split(',')
9
17
  hosts_with_port = hosts.map { |host| [host, port].join(':') }
10
18
  super(hosts_with_port, options)
11
19
  end
12
20
 
13
21
  def execute(statement, *arguments)
14
22
  bind_variables = arguments.shift statement.count('?')
15
- bound_statement = CassandraCQL::Statement.sanitize(statement, bind_variables)
23
+ bound_statement = Ciql::Sanitize.sanitize(statement, *bind_variables)
16
24
  compression_type = CassandraCQL::Thrift::Compression::NONE
17
- consistency_level = CassandraCQL::Thrift::ConsistencyLevel.const_get(
18
- (arguments.shift or :quorum).to_s.upcase
19
- )
25
+ consistency_level = (arguments.shift or :quorum).to_s.upcase
20
26
 
21
- CassandraCQL::Result.new(
22
- @connection.execute_cql3_query(
23
- bound_statement, compression_type, consistency_level
27
+ result = nil
28
+ times = Benchmark.measure do
29
+ result = CassandraCQL::Result.new(
30
+ @connection.execute_cql3_query(
31
+ bound_statement, compression_type,
32
+ CassandraCQL::Thrift::ConsistencyLevel.const_get(consistency_level)
33
+ )
24
34
  )
35
+ end
36
+
37
+ log(
38
+ duration: times.real * 10**3,
39
+ query: bound_statement,
40
+ compression: compression_type,
41
+ consistency: consistency_level
25
42
  )
43
+
44
+ result
45
+
26
46
  rescue CassandraCQL::Thrift::InvalidRequestException
27
- raise CassandraCQL::Error::InvalidRequestException.new($!.why)
47
+ message = [$!.why, bound_statement].join(' -- ')
48
+ raise CassandraCQL::Error::InvalidRequestException.new(message)
28
49
  end
29
50
  end
30
51
  end
data/lib/ciql/rails.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Ciql
2
+ class Railtie < Rails::Railtie
3
+ initializer 'ciql.logger', after: 'data_mapper.logger' do
4
+ Ciql.logger = DataMapper.logger
5
+ end
6
+ end
7
+
8
+ module LogListener
9
+ def log(message)
10
+ ActiveSupport::Notifications.instrument('sql.data_mapper',
11
+ :name => 'CQL',
12
+ :sql => '%{query} [%{consistency}]' % message,
13
+ :duration => message[:duration]
14
+ )
15
+ rescue Exception => e
16
+ Ciql.logger.error "[ciql] #{e.class.name}: #{e.message}: #{message.inspect}}"
17
+ end
18
+ end
19
+
20
+ Client::Thrift.send(:include, LogListener)
21
+ end
data/lib/ciql/sanitize.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require 'simple_uuid'
2
- require 'cql'
3
2
 
4
3
  module Ciql
5
4
  module Sanitize
@@ -30,20 +29,16 @@ module Ciql
30
29
  def self.cast(obj)
31
30
  case obj
32
31
  when Hash
33
- obj.map do |key, value|
34
- [cast(key), cast(value)].join(':')
35
- end.join(',')
32
+ obj.map { |pair| pair.map(&method(:cast)).join(':') }.join(',')
36
33
 
37
34
  when Enumerable
38
35
  obj.map { |member| cast(member) }.join(',')
39
36
 
40
- when Numeric; obj
41
- when DateTime; (obj.to_time.to_f * 1000).to_i
42
- when Time; (obj.to_f * 1000).to_i
43
- when Date; quote(obj.strftime('%Y-%m-%d'))
37
+ when Numeric then obj
38
+ when DateTime, Time then obj.strftime('%s%3N').to_i
39
+ when Date then quote(obj.strftime('%Y-%m-%d'))
44
40
 
45
- when ::Cql::Uuid; obj.to_s
46
- when ::SimpleUUID::UUID; obj.to_guid
41
+ when ::SimpleUUID::UUID then obj.to_guid
47
42
 
48
43
  when String
49
44
  if obj.encoding == ::Encoding::BINARY
@@ -52,6 +47,9 @@ module Ciql
52
47
  quote obj.encode(::Encoding::UTF_8)
53
48
  end
54
49
 
50
+ when TrueClass, FalseClass
51
+ obj.to_s
52
+
55
53
  else
56
54
  quote obj.to_s.dup.force_encoding(::Encoding::BINARY)
57
55
  end
data/lib/ciql/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ciql
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.2.2'.freeze
3
3
  end
@@ -2,10 +2,24 @@ require 'spec_helper'
2
2
 
3
3
  module Ciql::Client
4
4
  describe Thrift do
5
- subject { described_class.new }
5
+ let(:logger) { mock(:debug? => true, :debug => nil) }
6
+
7
+ subject { described_class.new(log: logger) }
8
+
9
+ before do
10
+ Ciql.logger = logger
11
+ end
6
12
 
7
13
  it 'inherits from CassandraCQL::Database' do
8
14
  subject.should be_kind_of CassandraCQL::Database
9
15
  end
16
+
17
+ describe '#execute' do
18
+ it 'logs the query' do
19
+ subject # instantiate
20
+ logger.should_receive(:debug).with(/system.local where key = 'local' \[ONE\]/)
21
+ subject.execute('select * from system.local where key = ?', :local, :one)
22
+ end
23
+ end
10
24
  end
11
25
  end
@@ -61,18 +61,13 @@ module Ciql
61
61
  end
62
62
 
63
63
  it 'converts times' do
64
- subject.sanitize('?', Time.new(2013, 3, 26, 23, 1, 2.544, 0))
65
- .should == 1364338862544.to_s
64
+ subject.sanitize('?', Time.new(2013, 3, 26, 23, 1, 2.123, 0))
65
+ .should == 1364338862123.to_s
66
66
  end
67
67
 
68
68
  it 'converts DateTime instances as a time' do
69
- subject.sanitize('?', DateTime.new(2013, 3, 26, 23, 1, 2.544, 0))
70
- .should == 1364338862544.to_s
71
- end
72
-
73
- it 'converts Cql::Uuid to a bare string representation' do
74
- subject.sanitize('?', Cql::Uuid.new(2**127 - 1))
75
- .should == "7fffffff-ffff-ffff-ffff-ffffffffffff"
69
+ subject.sanitize('?', DateTime.new(2013, 3, 26, 23, 1, 2.123, 0))
70
+ .should == 1364338862123.to_s
76
71
  end
77
72
 
78
73
  it 'converts SimpleUUID::UUID to a bare string representation' do
@@ -85,6 +80,14 @@ module Ciql
85
80
  .should == "0x01020304"
86
81
  end
87
82
 
83
+ it 'converts TrueClass instances to true, without quotes' do
84
+ subject.sanitize('?', [true]).should == 'true'
85
+ end
86
+
87
+ it 'converts FalseClass instances to false, without quotes' do
88
+ subject.sanitize('?', [false]).should == 'false'
89
+ end
90
+
88
91
  it 'joins elements of an array with a comma separator' do
89
92
  subject.sanitize('?', [1,2,3]).should == '1,2,3'
90
93
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ciql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Bradford
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-14 00:00:00.000000000 Z
11
+ date: 2013-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-cql
@@ -59,15 +59,15 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - lib/ciql/client/log.rb
62
63
  - lib/ciql/client/thrift.rb
63
- - lib/ciql/client.rb
64
64
  - lib/ciql/configuration.rb
65
+ - lib/ciql/rails.rb
65
66
  - lib/ciql/sanitize.rb
66
67
  - lib/ciql/version.rb
67
68
  - lib/ciql.rb
68
69
  - README.md
69
70
  - spec/ciql/client/thrift_spec.rb
70
- - spec/ciql/client_spec.rb
71
71
  - spec/ciql/configuration_spec.rb
72
72
  - spec/ciql/sanitize_spec.rb
73
73
  - spec/spec_helper.rb
@@ -97,7 +97,6 @@ specification_version: 4
97
97
  summary: CQL Cassandra client for Ruby
98
98
  test_files:
99
99
  - spec/ciql/client/thrift_spec.rb
100
- - spec/ciql/client_spec.rb
101
100
  - spec/ciql/configuration_spec.rb
102
101
  - spec/ciql/sanitize_spec.rb
103
102
  - spec/spec_helper.rb
data/lib/ciql/client.rb DELETED
@@ -1,23 +0,0 @@
1
- require 'ciql/sanitize'
2
-
3
- module Ciql
4
- module Client
5
- class AsynchronousClient < Cql::Client::AsynchronousClient
6
- def execute(statement, *arguments)
7
- bind_variables = arguments.shift statement.count('?')
8
- bound_statement = Ciql::Sanitize.sanitize statement, *bind_variables
9
- super(bound_statement, *arguments)
10
- end
11
- end
12
-
13
- class SynchronousClient < Cql::Client::SynchronousClient
14
- def execute(statement, *arguments)
15
- @async_client.execute(statement, *arguments).get
16
- end
17
- end
18
-
19
- def self.connect(options={})
20
- SynchronousClient.new(AsynchronousClient.new(options)).connect
21
- end
22
- end
23
- end
@@ -1,67 +0,0 @@
1
- require 'spec_helper'
2
- require 'ciql/client'
3
-
4
- module Ciql::Client
5
- describe AsynchronousClient do
6
- let(:client) { described_class.new }
7
-
8
- describe '#execute' do
9
- before do
10
- client.instance_variable_set(:@connected, true)
11
- client.stub(:execute_request) do |request|
12
- Cql::Future.completed(request)
13
- end
14
- end
15
-
16
- it 'returns a Cql::Future' do
17
- client.execute('x').should be_kind_of Cql::Future
18
- end
19
-
20
- it 'binds query parameters' do
21
- client.execute('a = ? and b = ?', "a'b", [1,2].pack('C*'))
22
- .get.cql.should == "a = 'a''b' and b = 0x0102"
23
- end
24
-
25
- it 'uses an extra trailing argument as the consistency level' do
26
- client.execute('update', :any).get.consistency.should == :any
27
- client.execute('update ?', :any).get.consistency.should == :quorum
28
- client.execute('update ?', :any, :one).get.consistency.should == :one
29
- end
30
- end
31
- end
32
-
33
- describe SynchronousClient do
34
- let(:async_client) { mock('async client') }
35
- let(:client) { described_class.new(async_client) }
36
-
37
- describe '#execute' do
38
- before do
39
- async_client.should_receive(:execute) do |*arguments|
40
- Cql::Future.completed(arguments)
41
- end
42
- end
43
-
44
- it "returns the value of the async client's #execute result" do
45
- client.execute('??', 'a', 'b', :two).should == ['??', 'a', 'b', :two]
46
- end
47
- end
48
- end
49
-
50
- describe '.connect' do
51
- let(:reactor) { FakeReactor.new }
52
-
53
- before(:each) do
54
- Cql::Io::IoReactor.stub(:new).and_return(reactor)
55
- end
56
-
57
- subject { Ciql::Client.connect(port: 4000) }
58
-
59
- it 'returns a SynchronousClient' do
60
- subject.should be_instance_of Ciql::Client::SynchronousClient
61
- end
62
-
63
- it 'passes the options to the internal async client' do
64
- subject.async.instance_variable_get(:@port).should == 4000
65
- end
66
- end
67
- end