spec/mri/pg_interface_spec.rb in pod4-0.7.2 vs spec/mri/pg_interface_spec.rb in pod4-0.8.0

- old
+ new

@@ -6,10 +6,13 @@ class TestPgInterface < PgInterface set_table :customer set_id_fld :id + + # We open a lot of connections, unusually + def stop; close; end end class SchemaPgInterface < PgInterface set_schema :public set_table :customer @@ -22,38 +25,53 @@ class BadPgInterface2 < PgInterface set_id_fld :id end +class ProdPgInterface < PgInterface + set_table :product + set_id_fld :code +end + describe TestPgInterface do def db_setup(connect) client = PG.connect(connect) - client.exec(%Q|drop table if exists customer;|) - client.exec(%Q| + drop table if exists customer; + drop table if exists product; + create table customer ( - id serial, + id serial primary key, name text, level real null, day date null, timestamp timestamp null, price money null, - qty numeric null );| ) + qty numeric null ); + create table product ( + code text, + name text );| ) + ensure client.finish if client end def fill_data(ifce) @data.each{|r| ifce.create(r) } end + def fill_product_data(ifce) + ifce.create( {code: "foo", name: "bar"} ) + end + + before(:all) do @connect_hash = DB[:pg] db_setup(@connect_hash) @data = [] @@ -80,19 +98,31 @@ end before do - # TRUNCATE TABLE also resets the identity counter - interface.execute(%Q|truncate table customer restart identity;|) + interface.execute(%Q| + truncate table customer restart identity; + truncate table product;|) + end + after do + # We open a lot of connections, unusually + interface.stop if interface + end + + let(:interface) do TestPgInterface.new(@connect_hash) end + let(:prod_interface) do + ProdPgInterface.new(@connect_hash) + end + ##### it_behaves_like 'an interface' do @@ -210,24 +240,33 @@ expect{ interface.read(id) }.not_to raise_exception expect( interface.read(id).to_h ).to include ot.to_h end - it 'shouldnt have a problem with record values of nil' do + it 'shouldn\'t have a problem with record values of nil' do record = {name: 'Ranger', price: nil} expect{ interface.create(record) }.not_to raise_exception id = interface.create(record) expect( interface.read(id).to_h ).to include(record) end - it 'shouldnt have a problem with strings containing special characters' do + it 'shouldn\'t have a problem with strings containing special characters' do record = {name: %Q|T'Challa""|, price: nil} expect{ interface.create(record) }.not_to raise_exception id = interface.create(record) expect( interface.read(id).to_h ).to include(record) end + it 'shouldn\'t have a problem with non-integer keys' do + hash = {code: "foo", name: "bar"} + id = prod_interface.create( Octothorpe.new(hash) ) + + expect( id ).to eq "foo" + expect{ prod_interface.read("foo") }.not_to raise_exception + expect( prod_interface.read("foo").to_h ).to include hash + end + end ## describe '#read' do @@ -282,10 +321,18 @@ expect( price ).to be_a_kind_of BigDecimal expect( price ).to eq @data.first[:price] end + it 'shouldn\'t have a problem with non-integer keys' do + # this is a 100% overlap with the create test above... + fill_product_data(prod_interface) + + expect{ prod_interface.read("foo") }.not_to raise_exception + expect( prod_interface.read("foo").to_h ).to include(code: "foo", name: "bar") + end + end ## describe '#list' do @@ -335,12 +382,10 @@ it 'updates the record at ID with record parameter' do record = {name: 'Booboo', price: 99.99} interface.update(id, record) - # It so happens that TinyTds returns money as BigDecimal -- - # this is a really good thing, even though it screws with our test. expect( float_price( interface.read(id).to_h ) ).to include(record) end it 'raises a CantContinue if anything weird happens with the ID' do expect{ interface.update(99, name: 'Booboo') }. @@ -352,30 +397,36 @@ expect{ interface.update(id, smarts: 'more') }. to raise_exception DatabaseError end - it 'shouldnt have a problem with record values of nil' do + it 'shouldn\'t have a problem with record values of nil' do record = {name: 'Ranger', price: nil} expect{ interface.update(id, record) }.not_to raise_exception expect( interface.read(id).to_h ).to include(record) end - it 'shouldnt have a problem with strings containing special characters' do + it 'shouldn\'t have a problem with strings containing special characters' do record = {name: %Q|T'Challa""|, price: nil} expect{ interface.update(id, record) }.not_to raise_exception expect( interface.read(id).to_h ).to include(record) end + it 'shouldn\'t have a problem with non-integer keys' do + fill_product_data(prod_interface) + expect{ prod_interface.update("foo", name: "baz") }.not_to raise_error + expect( prod_interface.read("foo").to_h[:name] ).to eq "baz" + end + end ## describe '#delete' do - def list_contains(id) - interface.list.find {|x| x[interface.id_fld] == id } + def list_contains(ifce, id) + ifce.list.find {|x| x[ifce.id_fld] == id } end let(:id) { interface.list.first[:id] } before { fill_data(interface) } @@ -384,15 +435,22 @@ expect{ interface.delete(:foo) }.to raise_exception CantContinue expect{ interface.delete(99) }.to raise_exception CantContinue end it 'makes the record at ID go away' do - expect( list_contains(id) ).to be_truthy + expect( list_contains(interface, id) ).to be_truthy interface.delete(id) - expect( list_contains(id) ).to be_falsy + expect( list_contains(interface, id) ).to be_falsy end + it 'shouldn\'t have a problem with non-integer keys' do + fill_product_data(prod_interface) + expect( list_contains(prod_interface, "foo") ).to be_truthy + prod_interface.delete("foo") + expect( list_contains(prod_interface, "foo") ).to be_falsy + end + end ## describe '#execute' do @@ -421,10 +479,38 @@ end ## + describe '#executep' do + + let(:sql) { 'delete from customer where cast(price as numeric) < %s and name = %s;' } + + before { fill_data(interface) } + + it 'requires an SQL string' do + expect{ interface.executep }.to raise_exception ArgumentError + expect{ interface.executep(nil) }.to raise_exception ArgumentError + expect{ interface.executep(14) }.to raise_exception ArgumentError + end + + it 'raises some sort of Pod4 error if it runs into problems' do + expect{ interface.executep('delete from not_a_table where foo = %s', 12) }. + to raise_exception Pod4Error + + end + + it 'executes the string with the given parameters' do + expect{ interface.executep(sql, 12.0, 'Barney') }.not_to raise_exception + expect( interface.list.size ).to eq(@data.size - 1) + expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney' + end + + end + ## + + describe '#select' do before { fill_data(interface) } it 'requires an SQL string' do @@ -455,9 +541,47 @@ expect( interface.list.size ).to eq(@data.size - 1) expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney' expect( ret ).to eq( [] ) end + + end + ## + + + describe '#selectp' do + + before { fill_data(interface) } + + it 'requires an SQL string' do + expect{ interface.selectp }.to raise_exception ArgumentError + expect{ interface.selectp(nil) }.to raise_exception ArgumentError + expect{ interface.selectp(14) }.to raise_exception ArgumentError + end + + it 'raises some sort of Pod4 error if it runs into problems' do + expect{ interface.selectp('select * from not_a_table where thingy = %s', 12) }. + to raise_exception Pod4Error + + end + + it 'returns the result of the sql' do + sql = 'select name from customer where cast(price as numeric) < %s;' + + expect{ interface.selectp(sql, 2.0) }.not_to raise_exception + expect( interface.selectp(sql, 2.0) ).to eq( [{name: 'Barney'}] ) + expect( interface.selectp(sql, 0.0) ).to eq( [] ) + end + + it 'works if you pass a non-select' do + sql = 'delete from customer where cast(price as numeric) < %s;' + ret = interface.selectp(sql, 2.0) + + expect( interface.list.size ).to eq(@data.size - 1) + expect( interface.list.map{|r| r[:name] } ).not_to include 'Barney' + expect( ret ).to eq( [] ) + end + end ##