ciql 0.2.0 → 0.2.2

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: 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