require File.expand_path('spec_helper.rb', File.dirname(__FILE__)) include CassandraCQL describe "initialize" do it "should set a handle and prepare statement" do statement = "use keyspace1" handle = double("Database") sth = Statement.new(handle, statement) sth.statement.should eq(statement) sth.instance_variable_get("@handle").should eq(handle) end end describe "execute" do context "when performing keyspace operations" do before(:each) do @connection = setup_cassandra_connection end it "should set keyspace without compression" do @connection.keyspace.should_not eq('system') stmt = @connection.prepare("use system") stmt.execute([], :compression => false).should be_nil @connection.keyspace.should eq('system') end it "should set keyspace with compression" do @connection.keyspace.should_not eq('system') stmt = @connection.prepare("use system") stmt.execute([], :compression => true).should be_nil @connection.keyspace.should eq('system') end it "should set keyspace to nil when deleting keyspace" do @connection.execute("DROP KEYSPACE #{@connection.keyspace}").should be_nil @connection.keyspace.should be_nil end end context "when performing void-returning column_family operations" do before(:each) do @connection = setup_cassandra_connection if !column_family_exists?(@connection, 'colfam_ops') @connection.execute("CREATE COLUMNFAMILY colfam_ops (id varchar PRIMARY KEY, column varchar)") else @connection.execute("TRUNCATE colfam_ops") end end it "should return nil when inserting" do @connection.execute("INSERT INTO colfam_ops (id, column) VALUES (?, ?)", "key", "value").should be_nil end it "should return nil when updating" do @connection.execute("UPDATE colfam_ops SET column=? WHERE id=?", "value", "key").should be_nil end it "should return nil when deleting" do @connection.execute("DELETE FROM colfam_ops WHERE id=?", "key").should be_nil end end end describe "escape" do it "should escape quotes" do Statement.escape(%q{'}).should eq(%q{''}) Statement.escape(%q{\'}).should eq(%q{\''}) Statement.escape(%q{''}).should eq(%q{''''}) end end describe "quote" do context "with a string" do it "should add quotes" do Statement.quote("test", USE_CQL3).should eq("'test'") end end context "with an integer" do it "should not add quotes" do Statement.quote(15, USE_CQL3).should eq("15") end end context "with an array" do it "should return a comma-separated list" do Statement.quote([1, 2, 3], USE_CQL3).should eq("1,2,3") Statement.quote(["a", "b''", "c"], USE_CQL3).should eq("'a','b''','c'") end end context "with a big decimal" do let :big_decimal do BigDecimal.new('129182739481237481341234123411.1029348102934810293481039') end let :result do '0.1291827394812374813412341234111029348102934810293481039E30' end it "should add quotes", cql_version: '2.0.0' do Statement.quote(BigDecimal.new(big_decimal), USE_CQL3).should eq("'#{result}'") end it "should not add quotes", cql_version: '3.0.0' do Statement.quote(big_decimal, USE_CQL3).should eq(result) end end context "with a boolean" do it "should not add quotes" do Statement.quote(true, USE_CQL3).should eq("true") Statement.quote(false, USE_CQL3).should eq("false") end end context "with an unsupported object" do it "should raise an exception" do expect { Statement.quote(Time.new, USE_CQL3) }.to raise_error(CassandraCQL::Error::UnescapableObject) end end end describe "cast_to_cql" do context "with a Time object" do it "should return a Time object with the number of microseconds since epoch" do ts = Time.new - 86400 # set it to yesterday just to be sure no defaulting to today misses an error long = Statement.cast_to_cql(ts) long.should be_kind_of(Integer) Time.at(long / 1000.0).to_f.should be_within(0.001).of(ts.to_f) end end context "with a Date object" do it "should return a corresponding Time object" do date = Date.today << 1 str = Statement.cast_to_cql(date) str.should eq(date.strftime('%Y-%m-%d')) end end context "with a Fixnum object" do it "should return the same object" do Statement.cast_to_cql(15).should eq(15) end end context "with a UUID object" do it "should return the a guid" do uuid = UUID.new guid = Statement.cast_to_cql(uuid) guid.should eq(uuid) end end context "with a SimpleUUID::UUID object" do it "should return the guid" do uuid = SimpleUUID::UUID.new guid = Statement.cast_to_cql(uuid) guid.should eq(uuid) end end context "with a String without quotes" do it "should return a copy of itself" do str = "This is a string" new_str = Statement.cast_to_cql(str) str.should eq(str) new_str.object_id.should_not eq(str.object_id) end end context "with a String with quotes" do it "should return a quoted version" do str = "This is a ' string" new_str = Statement.cast_to_cql(str) new_str.should_not eq(str) new_str.should eq(Statement.escape(str)) end end context "with binary data" do it "should return an unpacked version" do bytes = "binary\x00" bytes = bytes.force_encoding('ASCII-8BIT') if RUBY_VERSION >= "1.9" new_data = Statement.cast_to_cql(bytes) new_data.should_not eq(bytes) [new_data].pack('H*').should eq(bytes) end end context "with an array of Fixnums" do it "should equal itself" do arr = [1, 2, 3] Statement.cast_to_cql(arr).should eq(arr) end end context "with an array of Strings" do it "should return quoted versions of itself" do arr = ["test", "'"] res = Statement.cast_to_cql(arr) arr.map { |o| Statement.cast_to_cql(o) }.should eq(res) end end end describe "sanitize" do context "with no bind vars" do it "should return itself" do Statement.sanitize("use keyspace", [], USE_CQL3).should eq("use keyspace") end end context "when expecting bind vars" do it "should raise an exception with bind variable mismatch" do expect { Statement.sanitize("use keyspace ?", ['too', 'many'], USE_CQL3) }.to raise_error(Error::InvalidBindVariable) end it "should not raise an exception with matching bind vars" do expect { Statement.sanitize("use keyspace ?", ["test"], USE_CQL3).should eq("use keyspace 'test'") }.to_not raise_error(Error::InvalidBindVariable) end it "should have bind vars in the right order" do expect { Statement.sanitize("use keyspace ? with randomness (?)", ["test", "stuff"], USE_CQL3).should eq("use keyspace 'test' with randomness ('stuff')") }.to_not raise_error(Error::InvalidBindVariable) end it "should not double-escape the single quotes in your string" do Statement.sanitize( "insert into keyspace (key, ?) values (?)", ["vanilla", %Q{I\'m a string with \'cool\' quotes}], USE_CQL3 ).should eq("insert into keyspace (key, 'vanilla') values ('I''m a string with ''cool'' quotes')") end it "should handle numbers and stuff appropriately" do Statement.sanitize( "insert into keyspace (key, ?) values (?)", [488, 60.368], USE_CQL3 ).should eq("insert into keyspace (key, 488) values (60.368)") end end end describe "finish" do it "should just return true .. nothing to clean up yet" do Statement.new(nil, 'whatever').finish.should be_true end end