# $Id: test_gadfly.py,v 1.8 2002/05/19 01:54:24 richard Exp $ import unittest, os, shutil, time, sys from gadfly import gadfly from gadfly.store import StorageError class harness(unittest.TestCase): def setUp(self): self.connect = gadfly() if os.path.exists('_test_dir'): shutil.rmtree('_test_dir') os.makedirs('_test_dir') self.connect.startup("test", '_test_dir') self.curs = self.connect.cursor() table_creates = ( "frequents (drinker varchar, bar varchar, perweek integer)", "likes (drinker varchar, beer varchar, perday integer)", "serves (bar varchar, beer varchar, quantity integer)", "work (name varchar, hours integer, rate float)", "empty (nothing varchar)", "accesses (page varchar, hits integer, month integer)", ) for x in table_creates: self.curs.execute('create table '+x) self.curs.execute("""Create view nondrinkers(d, b) as select drinker, bar from frequents where drinker not in (select drinker from likes)""") # inserts C = "insert into work (name, hours, rate) values (?, ?, ?)" D = [("sam", 30, 40.2), ("norm", 45, 10.2), ("woody", 80, 5.4), ("diane", 3, 4.4), ("rebecca", 120, 12.9), ("cliff", 26, 200.00), ("carla", 9, 3.5), ] self.curs.execute(C, D) self.curs.execute('select name, hours, rate from work order by name') l = self.curs.fetchall() D.sort() self.assertEquals(l, D) fdata = [ ('adam', 'lolas', 1), ('woody', 'cheers', 5), ('sam', 'cheers', 5), ('norm', 'cheers', 3), ('wilt', 'joes', 2), ('norm', 'joes', 1), ('lola', 'lolas', 6), ('norm', 'lolas', 2), ('woody', 'lolas', 1), ('pierre', 'frankies', 0), ] sdata = [ ('cheers', 'bud', 500), ('cheers', 'samaddams', 255), ('joes', 'bud', 217), ('joes', 'samaddams', 13), ('joes', 'mickies', 2222), ('lolas', 'mickies', 1515), ('lolas', 'pabst', 333), ('winkos', 'rollingrock', 432), ('frankies', 'snafu', 5), ] ldata = [ ('adam', 'bud', 2), ('wilt', 'rollingrock', 1), ('sam', 'bud', 2), ('norm', 'rollingrock', 3), ('norm', 'bud', 2), ('nan', 'sierranevada', 1), ('woody', 'pabst', 2), ('lola', 'mickies', 5), ] dpairs = [("frequents", fdata), ("serves", sdata), ("likes", ldata) ] for table, data in dpairs: ins = "insert into %s values (?, ?, ?)"%table if table!="frequents": for parameters in data: self.curs.execute(ins, parameters) else: self.curs.execute(ins, data) # indexes indices = [ "create index fd on frequents (drinker)", "create index sbb on serves (beer, bar)", "create index lb on likes (beer)", "create index fb on frequents (bar)", ] for ci in indices: self.curs.execute(ci) self.connect.commit() def runQueries(self, queries): for q, p in queries: self.curs.execute(q) self.assertEqual(self.curs.pp(), p) def tearDown(self): self.connect.close() if os.path.exists('_test_dir'): shutil.rmtree('_test_dir') class test_Gadfly(harness): def testIndex(self): # test unique index C = "create unique index wname on work(name)" self.curs.execute(C) C = "insert into work(name, hours, rate) values ('sam', 0, 0)" self.assertRaises(StorageError, self.curs.execute, C) def testIntrospection(self): # introspection itests = ["select 10*4 from dual", "select * from __table_names__", "select * from __datadefs__", "select * from __indices__", "select * from __columns__", "select * from __indexcols__", """ select i.index_name, is_unique, table_name, column_name from __indexcols__ c, __indices__ i where c.index_name = i.index_name""", ] # TODO: compare results for C in itests: self.curs.execute(C) def testComplexLiterals(self): # testing complex, neg literals in insert self.curs.execute('''insert into work(name, hours, rate) values ('jo', -1, 3.1e-44-1e26j)''') self.curs.execute("select name,hours,rate from work where name='jo'") self.assertEquals(self.curs.fetchall(), [('jo', -1, (3.1e-44-1e+26j))]) self.curs.execute("delete from work where name='jo'") def testParameterisedInsert(self): # parameterised inserts C = "insert into accesses(page, month, hits) values (?, ?, ?)" D = [ ("index.html", 1, 2100), ("index.html", 2, 3300), ("index.html", 3, 1950), ("products.html", 1, 15), ("products.html", 2, 650), ("products.html", 3, 98), ("people.html", 1, 439), ("people.html", 2, 12), ("people.html", 3, 665), ] self.curs.execute(C, D) self.curs.execute("""select sum(hits) from accesses where page='people.html'""") self.assertEquals(self.curs.fetchall(), [(439+12+665,)]) self.runQueries([ ("""select month, sum(hits) as totalhits from accesses where month<>1 group by month order by 2""", 'MONTH | TOTALHITS\n=================\n3 | 2713 \n2 | 3962 '), ("""select month, sum(hits) as totalhits from accesses group by month order by 2 desc""", 'MONTH | TOTALHITS\n=================\n2 | 3962 \n3 | 2713 \n1 | 2554 '), ("""select month, sum(hits) as totalhits from accesses group by month having sum(hits)<3000 order by 2 desc""", 'MONTH | TOTALHITS\n=================\n3 | 2713 \n1 | 2554 '), ("select count(distinct month), count(distinct page) from accesses", 'Count(distinct ACCESSES.MONTH) | Count(distinct ACCESSES.PAGE)\n==============================================================\n3 | 3 '), ("select month, hits, page from accesses order by month, hits desc", 'MONTH | HITS | PAGE \n============================\n1 | 2100 | index.html \n1 | 439 | people.html \n1 | 15 | products.html\n2 | 3300 | index.html \n2 | 650 | products.html\n2 | 12 | people.html \n3 | 1950 | index.html \n3 | 665 | people.html \n3 | 98 | products.html'), ]) def testTrivialQueries1(self): self.runQueries([ ("select name, hours from work", 'NAME | HOURS\n===============\nsam | 30 \nnorm | 45 \nwoody | 80 \ndiane | 3 \nrebecca | 120 \ncliff | 26 \ncarla | 9 '), ]) def testTrivialQueries2(self): self.runQueries([ ("select B,D from nondrinkers", 'B | D \n=================\nfrankies | pierre'), ]) def testTrivialQueries3(self): self.runQueries([ ("""select QUANTITY,BAR,BEER from serves""", 'QUANTITY | BAR | BEER \n=================================\n500 | cheers | bud \n255 | cheers | samaddams \n217 | joes | bud \n13 | joes | samaddams \n2222 | joes | mickies \n1515 | lolas | mickies \n333 | lolas | pabst \n432 | winkos | rollingrock\n5 | frankies | snafu '), ]) def testTrivialQueries4(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker = 'norm'""", 'BAR | PERWEEK | DRINKER\n==========================\ncheers | 3 | norm \njoes | 1 | norm \nlolas | 2 | norm '), ]) def testMedian(self): self.runQueries([ ("select median(hours) from work", 'Median(WORK.HOURS)\n==================\n30 ') ]) def testComments(self): self.runQueries([ ("select name,rate,hours from work where name='carla' -- just carla", 'NAME | RATE | HOURS\n====================\ncarla | 3.5 | 9 '), ("""select name, ' ain''t worth ', rate from work -- has more columns where name='carla'""", "NAME | ain't worth | RATE\n============================\ncarla | ain't worth | 3.5 "), ("""select name, -- name of worker hours -- hours worked from work""", 'NAME | HOURS\n===============\nsam | 30 \nnorm | 45 \nwoody | 80 \ndiane | 3 \nrebecca | 120 \ncliff | 26 \ncarla | 9 '), ]) def testSimpleRange(self): self.runQueries([ ("select name, rate from work where rate>=20 and rate<=100", 'NAME | RATE\n===========\nsam | 40.2'), ("select name, rate from work where rate between 20 and 100", 'NAME | RATE\n===========\nsam | 40.2'), ("select name, rate from work where rate not between 20 and 100", 'NAME | RATE \n===============\nnorm | 10.2 \nwoody | 5.4 \ndiane | 4.4 \nrebecca | 12.9 \ncliff | 200.0\ncarla | 3.5 '), ]) def testBetween(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek not between 2 and 5""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \njoes | 1 | norm \nlolas | 6 | lola \nlolas | 1 | woody \nfrankies | 0 | pierre '), ]) def testIn(self): self.runQueries([ ("""select drinker,beer,perday from likes where beer in ('bud', 'pabst')""", 'DRINKER | BEER | PERDAY\n========================\nadam | bud | 2 \nsam | bud | 2 \nnorm | bud | 2 \nwoody | pabst | 2 '), ]) def testNotIn(self): result = 'BEER \n=========\nsamaddams\nsamaddams\nsnafu ' self.runQueries([ ("""select beer from serves where beer not in (select beer from likes)""", result) ]) def testSimpleCalculations1(self): self.runQueries([ ("select name, hours*rate as pay from work order by name", 'NAME | PAY \n================\ncarla | 31.5 \ncliff | 5200.0\ndiane | 13.2 \nnorm | 459.0 \nrebecca | 1548.0\nsam | 1206.0\nwoody | 432.0 '), ]) def testSimpleCalculations2(self): self.runQueries([ ("select name, rate, hours, hours*rate as pay from work", 'NAME | RATE | HOURS | PAY \n================================\nsam | 40.2 | 30 | 1206.0\nnorm | 10.2 | 45 | 459.0 \nwoody | 5.4 | 80 | 432.0 \ndiane | 4.4 | 3 | 13.2 \nrebecca | 12.9 | 120 | 1548.0\ncliff | 200.0 | 26 | 5200.0\ncarla | 3.5 | 9 | 31.5 '), ]) def testSimpleCalculations3(self): self.runQueries([ ("""select name, rate, hours, hours*rate as pay from work where hours*rate>500 and (rate<100 or hours>5)""", 'NAME | RATE | HOURS | PAY \n================================\nsam | 40.2 | 30 | 1206.0\nrebecca | 12.9 | 120 | 1548.0\ncliff | 200.0 | 26 | 5200.0'), ]) def testSimpleCalculations4(self): self.runQueries([ ("""select name, rate, hours, hours*rate as pay from work where hours*rate>500 and rate<100 or hours>5""", 'NAME | RATE | HOURS | PAY \n================================\nsam | 40.2 | 30 | 1206.0\nnorm | 10.2 | 45 | 459.0 \nwoody | 5.4 | 80 | 432.0 \nrebecca | 12.9 | 120 | 1548.0\ncliff | 200.0 | 26 | 5200.0\ncarla | 3.5 | 9 | 31.5 '), ]) def testSimpleCalculations5(self): self.runQueries([ ("""select avg(rate), min(hours), max(hours), sum(hours*rate) as expenses from work""", 'Average(WORK.RATE) | Minimum(WORK.HOURS) | Maximum(WORK.HOURS) | EXPENSES\n=========================================================================\n39.5142857143 | 3 | 120 | 8889.7 '), ]) def testUnion1(self): self.runQueries([ ("""select drinker as x from likes union select beer as x from serves union select drinker as x from frequents""", 'X \n===========\nadam \nwoody \nsam \nnorm \nwilt \nnorm \nlola \nnorm \nwoody \npierre \nbud \nsamaddams \nbud \nsamaddams \nmickies \nmickies \npabst \nrollingrock\nsnafu \nadam \nwilt \nsam \nnorm \nnorm \nnan \nwoody \nlola '), ]) def testUnion2(self): self.runQueries([ ("""select drinker from likes union select drinker from frequents""", 'DRINKER\n=======\nadam \nwoody \nsam \nnorm \nwilt \nnorm \nlola \nnorm \nwoody \npierre \nadam \nwilt \nsam \nnorm \nnorm \nnan \nwoody \nlola '), ]) def testUnionDistinct(self): self.runQueries([ ("""select drinker from likes union distinct select drinker from frequents order by drinker""", 'DRINKER\n=======\nadam \nlola \nnan \nnorm \npierre \nsam \nwilt \nwoody '), ]) def testJoin1(self): self.runQueries([ ("""select f.drinker, s.bar, l.beer from frequents f, serves s, likes l where f.drinker=l.drinker and s.beer=l.beer and s.bar=f.bar""", 'DRINKER | BAR | BEER \n==========================\nsam | cheers | bud \nnorm | cheers | bud \nnorm | joes | bud \nlola | lolas | mickies\nwoody | lolas | pabst '), ]) def testJoin2(self): self.runQueries([ ("""select QUANTITY,BEER,PERWEEK,DRINKER,S.BAR,F.BAR from frequents as f, serves as s where f.bar = s.bar order by QUANTITY,BEER,PERWEEK,DRINKER,S.BAR,F.BAR""", 'QUANTITY | BEER | PERWEEK | DRINKER | BAR | F.BAR \n==============================================================\n5 | snafu | 0 | pierre | frankies | frankies\n13 | samaddams | 1 | norm | joes | joes \n13 | samaddams | 2 | wilt | joes | joes \n217 | bud | 1 | norm | joes | joes \n217 | bud | 2 | wilt | joes | joes \n255 | samaddams | 3 | norm | cheers | cheers \n255 | samaddams | 5 | sam | cheers | cheers \n255 | samaddams | 5 | woody | cheers | cheers \n333 | pabst | 1 | adam | lolas | lolas \n333 | pabst | 1 | woody | lolas | lolas \n333 | pabst | 2 | norm | lolas | lolas \n333 | pabst | 6 | lola | lolas | lolas \n500 | bud | 3 | norm | cheers | cheers \n500 | bud | 5 | sam | cheers | cheers \n500 | bud | 5 | woody | cheers | cheers \n1515 | mickies | 1 | adam | lolas | lolas \n1515 | mickies | 1 | woody | lolas | lolas \n1515 | mickies | 2 | norm | lolas | lolas \n1515 | mickies | 6 | lola | lolas | lolas \n2222 | mickies | 1 | norm | joes | joes \n2222 | mickies | 2 | wilt | joes | joes ') ]) def testJoin3(self): self.runQueries([ ("""select PERDAY,BAR,PERWEEK,BEER,F.DRINKER,L.DRINKER from likes l, frequents f where f.bar='cheers' and l.drinker=f.drinker and l.beer='bud' order by PERDAY,BAR,PERWEEK,BEER,F.DRINKER,L.DRINKER""", 'PERDAY | BAR | PERWEEK | BEER | DRINKER | L.DRINKER\n======================================================\n2 | cheers | 3 | bud | norm | norm \n2 | cheers | 5 | bud | sam | sam '), ]) def testComplex1(self): self.runQueries([ ("""select l.beer, l.drinker, count(distinct s.bar) from likes l, serves s where l.beer=s.beer group by l.beer, l.drinker order by 3 desc, l.beer, l.drinker""", 'BEER | DRINKER | Count(distinct S.BAR)\n=============================================\nbud | adam | 2 \nbud | norm | 2 \nbud | sam | 2 \nmickies | lola | 2 \npabst | woody | 1 \nrollingrock | norm | 1 \nrollingrock | wilt | 1 '), ]) def testComplex2(self): self.runQueries([ ("""select l.beer, l.drinker, count(distinct s.bar) as nbars from likes l, serves s where l.beer=s.beer group by l.beer, l.drinker union distinct select beer, drinker, 0 as nbars from likes where beer not in (select beer from serves) order by 3 desc, l.beer, l.drinker""", 'BEER | DRINKER | NBARS\n==============================\nbud | adam | 2 \nbud | norm | 2 \nbud | sam | 2 \nmickies | lola | 2 \npabst | woody | 1 \nrollingrock | norm | 1 \nrollingrock | wilt | 1 \nsierranevada | nan | 0 ' ), ]) def testAverage(self): self.runQueries([ ("""select avg(perweek) from frequents""", 'Average(FREQUENTS.PERWEEK)\n==========================\n2.6 '), ]) def testAverageSubQuery1(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek <= (select avg(perweek) from frequents)""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \njoes | 2 | wilt \njoes | 1 | norm \nlolas | 2 | norm \nlolas | 1 | woody \nfrankies | 0 | pierre ' ), ]) def testAverageSubQuery2(self): self.runQueries([ ("""select QUANTITY,BAR,BEER from serves s1 where quantity <= (select avg(quantity) from serves s2 where s1.bar=s2.bar)""", 'QUANTITY | BAR | BEER \n=================================\n255 | cheers | samaddams \n217 | joes | bud \n13 | joes | samaddams \n333 | lolas | pabst \n432 | winkos | rollingrock\n5 | frankies | snafu '), ]) def testAverageSubQuery3(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek > (select avg(perweek) from frequents)""", 'BAR | PERWEEK | DRINKER\n==========================\ncheers | 5 | woody \ncheers | 5 | sam \ncheers | 3 | norm \nlolas | 6 | lola '), ]) def testAverageSubQuery4(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents f1 where perweek > ( select avg(perweek) from frequents f2 where f1.drinker = f2.drinker)""", 'BAR | PERWEEK | DRINKER\n==========================\ncheers | 5 | woody \ncheers | 3 | norm '), ]) def testAverageSubQuery5(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek between 2 and (select avg(perweek) from frequents)""", 'BAR | PERWEEK | DRINKER\n=========================\njoes | 2 | wilt \nlolas | 2 | norm '), ]) def testAverageGroup(self): self.runQueries([ ("""select bar, avg(quantity) from serves group by bar order by bar""", 'BAR | Average(SERVES.QUANTITY)\n===================================\ncheers | 377.5 \nfrankies | 5.0 \njoes | 817.333333333 \nlolas | 924.0 \nwinkos | 432.0 '), ]) def testAny1(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek < any (select perweek from frequents)""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \ncheers | 5 | woody \ncheers | 5 | sam \ncheers | 3 | norm \njoes | 2 | wilt \njoes | 1 | norm \nlolas | 2 | norm \nlolas | 1 | woody \nfrankies | 0 | pierre '), ]) def testAny2(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents f1 where perweek < any (select perweek from frequents f2 where f1.drinker = f2.drinker)""", 'BAR | PERWEEK | DRINKER\n=========================\njoes | 1 | norm \nlolas | 2 | norm \nlolas | 1 | woody '), ]) def testAny3(self): result = 'BEER \n===========\nbud \nbud \nmickies \nmickies \npabst \nrollingrock' self.runQueries([ ("""select beer from serves where beer = any (select beer from likes)""", result)]) self.runQueries([ ("""select beer from serves where beer in (select beer from likes)""", result)]) def testAll1(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek >= all (select perweek from frequents)""", 'BAR | PERWEEK | DRINKER\n=========================\nlolas | 6 | lola '), ]) def testAll2(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where perweek <= all (select perweek from frequents)""", 'BAR | PERWEEK | DRINKER\n============================\nfrankies | 0 | pierre '), ]) def testAll3(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents f1 where perweek = all (select perweek from frequents f2 where f1.drinker = f2.drinker)""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \ncheers | 5 | sam \njoes | 2 | wilt \nlolas | 6 | lola \nfrankies | 0 | pierre '), ]) def testAll4(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents f1 where perweek <> all (select perweek from frequents f2 where f1.drinker <> f2.drinker)""", 'BAR | PERWEEK | DRINKER\n============================\ncheers | 3 | norm \nlolas | 6 | lola \nfrankies | 0 | pierre '), ]) def testAll5(self): self.runQueries([ ("""select beer from serves where beer <> all (select beer from likes)""", 'BEER \n=========\nsamaddams\nsamaddams\nsnafu '), ]) def testExcept(self): self.runQueries([ ("""select drinker from likes except select drinker from frequents""", 'DRINKER\n=======\nnan '), ]) def testIntersect(self): self.runQueries([ ("""select drinker from likes intersect select drinker from frequents order by drinker""", 'DRINKER\n=======\nadam \nlola \nnorm \nsam \nwilt \nwoody '), ]) def testStringComparison1(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker>'norm'""", 'BAR | PERWEEK | DRINKER\n============================\ncheers | 5 | woody \ncheers | 5 | sam \njoes | 2 | wilt \nlolas | 1 | woody \nfrankies | 0 | pierre '), ]) def testStringComparison2(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker<='norm'""", 'BAR | PERWEEK | DRINKER\n==========================\nlolas | 1 | adam \ncheers | 3 | norm \njoes | 1 | norm \nlolas | 6 | lola \nlolas | 2 | norm '), ]) def testStringComparison3(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker>'norm' or drinker<'b'""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \ncheers | 5 | woody \ncheers | 5 | sam \njoes | 2 | wilt \nlolas | 1 | woody \nfrankies | 0 | pierre '), ]) def testStringComparison4(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker<>'norm' and 'pierre'<>drinker""", 'BAR | PERWEEK | DRINKER\n==========================\nlolas | 1 | adam \ncheers | 5 | woody \ncheers | 5 | sam \njoes | 2 | wilt \nlolas | 6 | lola \nlolas | 1 | woody '), ]) def testStringComparison5(self): self.runQueries([ ("""select BAR,PERWEEK,DRINKER from frequents where drinker<>'norm'""", 'BAR | PERWEEK | DRINKER\n============================\nlolas | 1 | adam \ncheers | 5 | woody \ncheers | 5 | sam \njoes | 2 | wilt \nlolas | 6 | lola \nlolas | 1 | woody \nfrankies | 0 | pierre '), ]) def testStringComparison6(self): self.runQueries([ ("""select (drinker+' ')*2+bar from frequents where drinker>bar""", '(((FREQUENTS.DRINKER)+( ))*(2))+(FREQUENTS.BAR)\n===============================================\nwoody woody cheers \nsam sam cheers \nnorm norm cheers \nwilt wilt joes \nnorm norm joes \nnorm norm lolas \nwoody woody lolas \npierre pierre frankies '), ]) def testExists1(self): self.runQueries([ ("""select QUANTITY,BEER,PERWEEK,DRINKER,S.BAR,F.BAR from frequents as f, serves as s where f.bar = s.bar and not exists( select l.drinker, l.beer from likes l where l.drinker=f.drinker and s.beer=l.beer) order by QUANTITY,BEER,PERWEEK,DRINKER,S.BAR,F.BAR""", 'QUANTITY | BEER | PERWEEK | DRINKER | BAR | F.BAR \n==============================================================\n5 | snafu | 0 | pierre | frankies | frankies\n13 | samaddams | 1 | norm | joes | joes \n13 | samaddams | 2 | wilt | joes | joes \n217 | bud | 2 | wilt | joes | joes \n255 | samaddams | 3 | norm | cheers | cheers \n255 | samaddams | 5 | sam | cheers | cheers \n255 | samaddams | 5 | woody | cheers | cheers \n333 | pabst | 1 | adam | lolas | lolas \n333 | pabst | 2 | norm | lolas | lolas \n333 | pabst | 6 | lola | lolas | lolas \n500 | bud | 5 | woody | cheers | cheers \n1515 | mickies | 1 | adam | lolas | lolas \n1515 | mickies | 1 | woody | lolas | lolas \n1515 | mickies | 2 | norm | lolas | lolas \n2222 | mickies | 1 | norm | joes | joes \n2222 | mickies | 2 | wilt | joes | joes '), ]) def testExists2(self): self.runQueries([ ("""select QUANTITY,BAR,BEER from serves s where not exists ( select * from likes l, frequents f where f.bar = s.bar and f.drinker=l.drinker and s.beer=l.beer)""", 'QUANTITY | BAR | BEER \n=================================\n255 | cheers | samaddams \n13 | joes | samaddams \n2222 | joes | mickies \n432 | winkos | rollingrock\n5 | frankies | snafu '), ]) def testExists3(self): self.runQueries([ ("""select 'nonbeer drinker '+f.drinker from frequents f where not exists (select l.drinker, l.beer from likes l where l.drinker=f.drinker)""", '(nonbeer drinker )+(F.DRINKER)\n==============================\nnonbeer drinker pierre '), ]) def testExists4(self): self.runQueries([ ("""select l.drinker+' likes '+l.beer+' but goes to no bar' from likes l where not exists (select f.drinker from frequents f where f.drinker=l.drinker)""", '(((L.DRINKER)+( likes ))+(L.BEER))+( but goes to no bar)\n========================================================\nnan likes sierranevada but goes to no bar '), ]) def testDistinct(self): self.runQueries([ ("""select distinct bar from frequents order by bar""", 'BAR \n========\ncheers \nfrankies\njoes \nlolas '), ]) def Aggregations1(self): self.runQueries([ ("""select sum(quantity), avg(quantity), count(*), sum(quantity)/count(quantity) from serves""", 'Sum(SERVES.QUANTITY) | Average(SERVES.QUANTITY) | Count(*) | (Sum(SERVES.QUANTITY))/(Count(SERVES.QUANTITY))\n============================================================================================================\n5492 | 610.222222222 | 9 | 610 '), ]) def Aggregations2(self): self.runQueries([ ("""select beer, sum(quantity), avg(quantity), count(*), sum(quantity)/count(quantity) from serves group by beer""", 'BEER | Sum(SERVES.QUANTITY) | Average(SERVES.QUANTITY) | Count(*) | (Sum(SERVES.QUANTITY))/(Count(SERVES.QUANTITY))\n==========================================================================================================================\npabst | 333 | 333.0 | 1 | 333 \nmickies | 3737 | 1868.5 | 2 | 1868 \nbud | 717 | 358.5 | 2 | 358 \nsnafu | 5 | 5.0 | 1 | 5 \nrollingrock | 432 | 432.0 | 1 | 432 \nsamaddams | 268 | 134.0 | 2 | 134 '), ]) def Aggregations3(self): self.runQueries([ ("""select sum(quantity), avg(quantity), count(*), sum(quantity)/count(quantity) from serves where beer<>'bud'""", 'Sum(SERVES.QUANTITY) | Average(SERVES.QUANTITY) | Count(*) | (Sum(SERVES.QUANTITY))/(Count(SERVES.QUANTITY))\n============================================================================================================\n4775 | 682.142857143 | 7 | 682 '), ]) def Aggregations4(self): self.runQueries([ ("""select bar, sum(quantity), avg(quantity), count(*), sum(quantity)/count(quantity) from serves where beer<>'bud' group by bar having sum(quantity)>500 or count(*)>3 order by 2 desc""", 'BAR | Sum(SERVES.QUANTITY) | Average(SERVES.QUANTITY) | Count(*) | (Sum(SERVES.QUANTITY))/(Count(SERVES.QUANTITY))\n====================================================================================================================\njoes | 2235 | 1117.5 | 2 | 1117 \nlolas | 1848 | 924.0 | 2 | 924 '), ]) def Aggregations5(self): self.runQueries([ ("""select beer, sum(quantity), avg(quantity), count(*) from serves where beer<>'bud' group by beer having sum(quantity)>100 order by 4 desc, beer""", 'BEER | Sum(SERVES.QUANTITY) | Average(SERVES.QUANTITY) | Count(*)\n========================================================================\nmickies | 3737 | 1868.5 | 2 \nsamaddams | 268 | 134.0 | 2 \npabst | 333 | 333.0 | 1 \nrollingrock | 432 | 432.0 | 1 '), ]) def Aggregations6(self): self.runQueries([ ("""select l.drinker, l.beer, count(*), sum(l.perday*f.perweek) from likes l, frequents f where l.drinker=f.drinker group by l.drinker, l.beer order by 4 desc, l.drinker, l.beer""", 'DRINKER | BEER | Count(*) | Sum((L.PERDAY)*(F.PERWEEK))\n==============================================================\nlola | mickies | 1 | 30 \nnorm | rollingrock | 3 | 18 \nnorm | bud | 3 | 12 \nwoody | pabst | 2 | 12 \nsam | bud | 1 | 10 \nadam | bud | 1 | 2 \nwilt | rollingrock | 1 | 2 '), ]) def Aggregations7(self): self.runQueries([ ("""select l.drinker, l.beer, f.bar, l.perday, f.perweek from likes l, frequents f where l.drinker=f.drinker order by l.drinker, l.perday desc, f.perweek desc""", 'DRINKER | BEER | BAR | PERDAY | PERWEEK\n=================================================\nadam | bud | lolas | 2 | 1 \nlola | mickies | lolas | 5 | 6 \nnorm | rollingrock | cheers | 3 | 3 \nnorm | rollingrock | lolas | 3 | 2 \nnorm | rollingrock | joes | 3 | 1 \nnorm | bud | cheers | 2 | 3 \nnorm | bud | lolas | 2 | 2 \nnorm | bud | joes | 2 | 1 \nsam | bud | cheers | 2 | 5 \nwilt | rollingrock | joes | 1 | 2 \nwoody | pabst | cheers | 2 | 5 \nwoody | pabst | lolas | 2 | 1 '), ]) def testDynamicQueries(self): # DYNAMIC QUERIES dynamic_queries = [ ( "select bar from frequents where drinker=?", ("norm",) ), ( "select * from frequents where drinker=? or bar=?", ("norm", "cheers") ) ] for (x,y) in dynamic_queries: self.curs.execute(x, y) all = self.curs.fetchall() def testRepeatQueries(self): # "repeat test" repeats = [ """-- drinkers bars and beers -- where the drinker likes the beer -- the bar serves the beer -- and the drinker frequents the bar select f.drinker, l.beer, s.bar from frequents f, serves s, likes l where f.drinker=l.drinker and s.bar=f.bar and s.beer=l.beer""", """select * from frequents as f, serves as s where f.bar = s.bar and not exists( select l.drinker, l.beer from likes l where l.drinker=f.drinker and s.beer=l.beer)""", """select * from frequents where drinker = 'norm'""", ] for x in repeats: #print "repeating", x #now = time.time() self.curs.execute(x) #print time.time()-now, "first time" #now = time.time() self.curs.execute(x) #print time.time()-now, "second time" #now = time.time() self.curs.execute(x) #print time.time()-now, "third time" def testArgh(self): sqls = (""" select bar, sum(quantity), avg(quantity), count(*), sum(quantity)/count(quantity) from serves where beer<>'bud' group by bar having sum(quantity)>500 or count(*)>3 order by 2 desc """, """ select bar, sum(quantity),count(*) from serves group by bar """, """ select bar, sum(quantity) from serves group by bar having sum(quantity) > 2000 or sum(quantity) > 1 """, """ select bar, sum(quantity) from serves group by bar having sum(quantity) > 2000 or sum(quantity) > 200 """, """ select bar, sum(quantity) from serves group by bar having sum(quantity) > 1000 or sum(quantity) > 1 """, ) for stmt in sqls: self.curs.execute(stmt) class test_GadflyRollback(harness): def test(self): self.connect.autocheckpoint = 0 keep_updates = [ """insert into frequents(drinker, bar, perweek) values ('peter', 'pans', 1)""", """create view alldrinkers as select drinker from frequents union select drinker from likes""", ] for x in keep_updates: self.curs.execute(x) self.connect.commit() # self.connect.dumplog() preresults = [] rollback_queries = [ """select * from likes""", """select * from frequents""", """select * from nondrinkers""", """select * from alldrinkers""", """select * from dummy""", ] for s in rollback_queries: try: self.curs.execute(s) preresults.append(self.curs.fetchall()) except: d = sys.exc_type preresults.append(d) rollback_updates = [ """create table dummy (nothing varchar)""", """insert into frequents(drinker, bar, perweek) values ('nobody', 'nobar', 0)""", """insert into likes(drinker, beer, perday) values ('wally', 'nobar', 0)""", """drop view alldrinkers""", ] for s in rollback_updates: self.curs.execute(s) for dummy in (1,2): postresults = [] for s in rollback_queries: try: self.curs.execute(s) postresults.append(self.curs.fetchall()) except: d = sys.exc_type postresults.append(d) if dummy==1: self.assert_(preresults != postresults) self.connect.rollback() else: self.assert_(preresults == postresults) for s in rollback_updates: self.curs.execute(s) for dummy in (1,2): postresults = [] for s in rollback_queries: try: self.curs.execute(s) postresults.append(self.curs.fetchall()) except: d = sys.exc_type postresults.append(d) if dummy==1: self.assert_(preresults != postresults) # self.connect.dumplog() self.connect.restart() else: self.assert_(preresults == postresults) class test_GadflyReconnect(harness): def testClose(self): self.connect.commit() self.connect.close() self.connect = gadfly("test", '_test_dir') self.curs = self.connect.cursor() self.runTest() def testRestart(self): self.connect.restart() self.curs = self.connect.cursor() self.runTest() def runTest(self): updates = [ """select * from frequents""", """select * from likes""", """select * from serves""", """select count(*), d from nondrinkers group by d""", """insert into frequents (drinker, perweek, bar) values ('billybob', 4, 'cheers')""", """select * from nondrinkers""", """create table templikes (dr varchar, be varchar)""", """select * from templikes""", """insert into templikes(dr, be) select drinker, beer from likes""", """create index tdindex on templikes(dr)""", """create index tbindex on templikes(be)""", """select * from templikes""", """delete from templikes where be='rollingrock' """, """select * from templikes""", """update templikes set dr=dr+'an' where dr='norm' """, """drop index tdindex""", """delete from templikes where dr=(select min(dr) from templikes)""", """insert into templikes (dr, be) select max(dr), min(be) from templikes""", """select * from templikes""", """select * from frequents""", """update frequents set perweek=(select max(perweek) from frequents where drinker='norm') where drinker='woody'""", """select * from frequents""", """create view lazy as select drinker, sum(perweek) as wasted from frequents group by drinker having sum(perweek)>4 order by drinker""", """select * from lazy""", """drop view lazy""", """drop table templikes""", ] for s in updates: self.curs.execute(s) self.connect.commit() def suite(): l = [ unittest.makeSuite(test_Gadfly), unittest.makeSuite(test_GadflyRollback), unittest.makeSuite(test_GadflyReconnect), ] return unittest.TestSuite(l) if __name__ == '__main__': runner = unittest.TextTestRunner() runner.run(suite()) # # $Log: test_gadfly.py,v $ # Revision 1.8 2002/05/19 01:54:24 richard # - close db before removal in tests # # Revision 1.7 2002/05/11 02:59:05 richard # Added info into module docstrings. # Fixed docco of kwParsing to reflect new grammar "marshalling". # Fixed bug in gadfly.open - most likely introduced during sql loading # re-work (though looking back at the diff from back then, I can't see how it # wasn't different before, but it musta been ;) # A buncha new unit test stuff. # # Revision 1.6 2002/05/08 00:49:01 anthonybaxter # El Grande Grande reindente! Ran reindent.py over the whole thing. # Gosh, what a lot of checkins. Tests still pass with 2.1 and 2.2. # # Revision 1.5 2002/05/07 09:58:19 anthonybaxter # all tests pass again. need to make a more thorough test # suite, really. # # Revision 1.4 2002/05/07 04:39:30 anthonybaxter # split out the broken test all by it's lonesome. # # Revision 1.3 2002/05/07 04:03:14 richard # . major cleanup of test_gadfly # # Revision 1.2 2002/05/06 23:27:10 richard # . made the installation docco easier to find # . fixed a "select *" test - column ordering is different for py 2.2 # . some cleanup in gadfly/kjParseBuild.py # . made the test modules runnable (remembering that run_tests can take a # name argument to run a single module) # . fixed the module name in gadfly/kjParser.py # #