PageRenderTime 62ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/gluon/tests/test_dal.py

https://github.com/eddgt/web2py
Python | 1520 lines | 1506 code | 3 blank | 11 comment | 4 complexity | 6cabfcbc6f6379028a4bd3fad33c6b4f MD5 | raw file
Possible License(s): BSD-2-Clause, AGPL-3.0, LGPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. Unit tests for gluon.dal
  5. """
  6. import sys
  7. import os
  8. import glob
  9. import unittest
  10. import datetime
  11. try:
  12. import cStringIO as StringIO
  13. except:
  14. from io import StringIO
  15. def fix_sys_path():
  16. """
  17. logic to have always the correct sys.path
  18. '', web2py/gluon, web2py/site-packages, web2py/ ...
  19. """
  20. def add_path_first(path):
  21. sys.path = [path] + [p for p in sys.path if (
  22. not p == path and not p == (path + '/'))]
  23. path = os.path.dirname(os.path.abspath(__file__))
  24. if not os.path.isfile(os.path.join(path,'web2py.py')):
  25. i = 0
  26. while i<10:
  27. i += 1
  28. if os.path.exists(os.path.join(path,'web2py.py')):
  29. break
  30. path = os.path.abspath(os.path.join(path, '..'))
  31. paths = [path,
  32. os.path.abspath(os.path.join(path, 'site-packages')),
  33. os.path.abspath(os.path.join(path, 'gluon')),
  34. '']
  35. [add_path_first(path) for path in paths]
  36. fix_sys_path()
  37. #for travis-ci
  38. DEFAULT_URI = os.environ.get('DB', 'sqlite:memory')
  39. print 'Testing against %s engine (%s)' % (DEFAULT_URI.partition(':')[0], DEFAULT_URI)
  40. from dal import DAL, Field, Table, SQLALL
  41. ALLOWED_DATATYPES = [
  42. 'string',
  43. 'text',
  44. 'integer',
  45. 'boolean',
  46. 'double',
  47. 'blob',
  48. 'date',
  49. 'time',
  50. 'datetime',
  51. 'upload',
  52. 'password',
  53. 'json',
  54. ]
  55. def setUpModule():
  56. pass
  57. def tearDownModule():
  58. if os.path.isfile('sql.log'):
  59. os.unlink('sql.log')
  60. for a in glob.glob('*.table'):
  61. os.unlink(a)
  62. class TestFields(unittest.TestCase):
  63. def testFieldName(self):
  64. # Check that Fields cannot start with underscores
  65. self.assertRaises(SyntaxError, Field, '_abc', 'string')
  66. # Check that Fields cannot contain punctuation other than underscores
  67. self.assertRaises(SyntaxError, Field, 'a.bc', 'string')
  68. # Check that Fields cannot be a name of a method or property of Table
  69. for x in ['drop', 'on', 'truncate']:
  70. self.assertRaises(SyntaxError, Field, x, 'string')
  71. # Check that Fields allows underscores in the body of a field name.
  72. self.assert_(Field('a_bc', 'string'),
  73. "Field isn't allowing underscores in fieldnames. It should.")
  74. def testFieldTypes(self):
  75. # Check that string, and password default length is 512
  76. for typ in ['string', 'password']:
  77. self.assert_(Field('abc', typ).length == 512,
  78. "Default length for type '%s' is not 512 or 255" % typ)
  79. # Check that upload default length is 512
  80. self.assert_(Field('abc', 'upload').length == 512,
  81. "Default length for type 'upload' is not 512")
  82. # Check that Tables passed in the type creates a reference
  83. self.assert_(Field('abc', Table(None, 'temp')).type
  84. == 'reference temp',
  85. 'Passing an Table does not result in a reference type.')
  86. def testFieldLabels(self):
  87. # Check that a label is successfully built from the supplied fieldname
  88. self.assert_(Field('abc', 'string').label == 'Abc',
  89. 'Label built is incorrect')
  90. self.assert_(Field('abc_def', 'string').label == 'Abc Def',
  91. 'Label built is incorrect')
  92. def testFieldFormatters(self): # Formatter should be called Validator
  93. # Test the default formatters
  94. for typ in ALLOWED_DATATYPES:
  95. f = Field('abc', typ)
  96. if typ not in ['date', 'time', 'datetime']:
  97. isinstance(f.formatter('test'), str)
  98. else:
  99. isinstance(f.formatter(datetime.datetime.now()), str)
  100. def testRun(self):
  101. db = DAL(DEFAULT_URI, check_reserved=['all'])
  102. for ft in ['string', 'text', 'password', 'upload', 'blob']:
  103. db.define_table('tt', Field('aa', ft, default=''))
  104. self.assertEqual(db.tt.insert(aa='x'), 1)
  105. self.assertEqual(db().select(db.tt.aa)[0].aa, 'x')
  106. db.tt.drop()
  107. db.define_table('tt', Field('aa', 'integer', default=1))
  108. self.assertEqual(db.tt.insert(aa=3), 1)
  109. self.assertEqual(db().select(db.tt.aa)[0].aa, 3)
  110. db.tt.drop()
  111. db.define_table('tt', Field('aa', 'double', default=1))
  112. self.assertEqual(db.tt.insert(aa=3.1), 1)
  113. self.assertEqual(db().select(db.tt.aa)[0].aa, 3.1)
  114. db.tt.drop()
  115. db.define_table('tt', Field('aa', 'boolean', default=True))
  116. self.assertEqual(db.tt.insert(aa=True), 1)
  117. self.assertEqual(db().select(db.tt.aa)[0].aa, True)
  118. db.tt.drop()
  119. db.define_table('tt', Field('aa', 'json', default={}))
  120. self.assertEqual(db.tt.insert(aa={}), 1)
  121. self.assertEqual(db().select(db.tt.aa)[0].aa, {})
  122. db.tt.drop()
  123. db.define_table('tt', Field('aa', 'date',
  124. default=datetime.date.today()))
  125. t0 = datetime.date.today()
  126. self.assertEqual(db.tt.insert(aa=t0), 1)
  127. self.assertEqual(db().select(db.tt.aa)[0].aa, t0)
  128. db.tt.drop()
  129. db.define_table('tt', Field('aa', 'datetime',
  130. default=datetime.datetime.today()))
  131. t0 = datetime.datetime(
  132. 1971,
  133. 12,
  134. 21,
  135. 10,
  136. 30,
  137. 55,
  138. 0,
  139. )
  140. self.assertEqual(db.tt.insert(aa=t0), 1)
  141. self.assertEqual(db().select(db.tt.aa)[0].aa, t0)
  142. ## Row APIs
  143. row = db().select(db.tt.aa)[0]
  144. self.assertEqual(db.tt[1].aa,t0)
  145. self.assertEqual(db.tt['aa'],db.tt.aa)
  146. self.assertEqual(db.tt(1).aa,t0)
  147. self.assertTrue(db.tt(1,aa=None)==None)
  148. self.assertFalse(db.tt(1,aa=t0)==None)
  149. self.assertEqual(row.aa,t0)
  150. self.assertEqual(row['aa'],t0)
  151. self.assertEqual(row['tt.aa'],t0)
  152. self.assertEqual(row('tt.aa'),t0)
  153. ## Lazy and Virtual fields
  154. db.tt.b = Field.Virtual(lambda row: row.tt.aa)
  155. db.tt.c = Field.Lazy(lambda row: row.tt.aa)
  156. row = db().select(db.tt.aa)[0]
  157. self.assertEqual(row.b,t0)
  158. self.assertEqual(row.c(),t0)
  159. db.tt.drop()
  160. db.define_table('tt', Field('aa', 'time', default='11:30'))
  161. t0 = datetime.time(10, 30, 55)
  162. self.assertEqual(db.tt.insert(aa=t0), 1)
  163. self.assertEqual(db().select(db.tt.aa)[0].aa, t0)
  164. db.tt.drop()
  165. class TestTables(unittest.TestCase):
  166. def testTableNames(self):
  167. # Check that Tables cannot start with underscores
  168. self.assertRaises(SyntaxError, Table, None, '_abc')
  169. # Check that Tables cannot contain punctuation other than underscores
  170. self.assertRaises(SyntaxError, Table, None, 'a.bc')
  171. # Check that Tables cannot be a name of a method or property of DAL
  172. for x in ['define_table', 'tables', 'as_dict']:
  173. self.assertRaises(SyntaxError, Table, None, x)
  174. # Check that Table allows underscores in the body of a field name.
  175. self.assert_(Table(None, 'a_bc'),
  176. "Table isn't allowing underscores in tablename. It should.")
  177. class TestAll(unittest.TestCase):
  178. def setUp(self):
  179. self.pt = Table(None,'PseudoTable',Field('name'),Field('birthdate'))
  180. def testSQLALL(self):
  181. ans = 'PseudoTable.id, PseudoTable.name, PseudoTable.birthdate'
  182. self.assertEqual(str(SQLALL(self.pt)), ans)
  183. class TestTable(unittest.TestCase):
  184. def testTableCreation(self):
  185. # Check for error when not passing type other than Field or Table
  186. self.assertRaises(SyntaxError, Table, None, 'test', None)
  187. persons = Table(None, 'persons',
  188. Field('firstname','string'),
  189. Field('lastname', 'string'))
  190. # Does it have the correct fields?
  191. self.assert_(set(persons.fields).issuperset(set(['firstname',
  192. 'lastname'])))
  193. # ALL is set correctly
  194. self.assert_('persons.firstname, persons.lastname'
  195. in str(persons.ALL))
  196. def testTableAlias(self):
  197. db = DAL(DEFAULT_URI, check_reserved=['all'])
  198. persons = Table(db, 'persons', Field('firstname',
  199. 'string'), Field('lastname', 'string'))
  200. aliens = persons.with_alias('aliens')
  201. # Are the different table instances with the same fields
  202. self.assert_(persons is not aliens)
  203. self.assert_(set(persons.fields) == set(aliens.fields))
  204. def testTableInheritance(self):
  205. persons = Table(None, 'persons', Field('firstname',
  206. 'string'), Field('lastname', 'string'))
  207. customers = Table(None, 'customers',
  208. Field('items_purchased', 'integer'),
  209. persons)
  210. self.assert_(set(customers.fields).issuperset(set(
  211. ['items_purchased', 'firstname', 'lastname'])))
  212. class TestInsert(unittest.TestCase):
  213. def testRun(self):
  214. db = DAL(DEFAULT_URI, check_reserved=['all'])
  215. db.define_table('tt', Field('aa'))
  216. self.assertEqual(db.tt.insert(aa='1'), 1)
  217. self.assertEqual(db.tt.insert(aa='1'), 2)
  218. self.assertEqual(db.tt.insert(aa='1'), 3)
  219. self.assertEqual(db(db.tt.aa == '1').count(), 3)
  220. self.assertEqual(db(db.tt.aa == '2').isempty(), True)
  221. self.assertEqual(db(db.tt.aa == '1').update(aa='2'), 3)
  222. self.assertEqual(db(db.tt.aa == '2').count(), 3)
  223. self.assertEqual(db(db.tt.aa == '2').isempty(), False)
  224. self.assertEqual(db(db.tt.aa == '2').delete(), 3)
  225. self.assertEqual(db(db.tt.aa == '2').isempty(), True)
  226. db.tt.drop()
  227. class TestSelect(unittest.TestCase):
  228. def testRun(self):
  229. db = DAL(DEFAULT_URI, check_reserved=['all'])
  230. db.define_table('tt', Field('aa'))
  231. self.assertEqual(db.tt.insert(aa='1'), 1)
  232. self.assertEqual(db.tt.insert(aa='2'), 2)
  233. self.assertEqual(db.tt.insert(aa='3'), 3)
  234. self.assertEqual(db(db.tt.id > 0).count(), 3)
  235. self.assertEqual(db(db.tt.id > 0).select(orderby=~db.tt.aa
  236. | db.tt.id)[0].aa, '3')
  237. self.assertEqual(len(db(db.tt.id > 0).select(limitby=(1, 2))), 1)
  238. self.assertEqual(db(db.tt.id > 0).select(limitby=(1, 2))[0].aa,
  239. '2')
  240. self.assertEqual(len(db().select(db.tt.ALL)), 3)
  241. self.assertEqual(db(db.tt.aa == None).count(), 0)
  242. self.assertEqual(db(db.tt.aa != None).count(), 3)
  243. self.assertEqual(db(db.tt.aa > '1').count(), 2)
  244. self.assertEqual(db(db.tt.aa >= '1').count(), 3)
  245. self.assertEqual(db(db.tt.aa == '1').count(), 1)
  246. self.assertEqual(db(db.tt.aa != '1').count(), 2)
  247. self.assertEqual(db(db.tt.aa < '3').count(), 2)
  248. self.assertEqual(db(db.tt.aa <= '3').count(), 3)
  249. self.assertEqual(db(db.tt.aa > '1')(db.tt.aa < '3').count(), 1)
  250. self.assertEqual(db((db.tt.aa > '1') & (db.tt.aa < '3')).count(), 1)
  251. self.assertEqual(db((db.tt.aa > '1') | (db.tt.aa < '3')).count(), 3)
  252. self.assertEqual(db((db.tt.aa > '1') & ~(db.tt.aa > '2')).count(), 1)
  253. self.assertEqual(db(~(db.tt.aa > '1') & (db.tt.aa > '2')).count(), 0)
  254. db.tt.drop()
  255. class TestAddMethod(unittest.TestCase):
  256. def testRun(self):
  257. db = DAL(DEFAULT_URI, check_reserved=['all'])
  258. db.define_table('tt', Field('aa'))
  259. @db.tt.add_method.all
  260. def select_all(table,orderby=None):
  261. return table._db(table).select(orderby=orderby)
  262. self.assertEqual(db.tt.insert(aa='1'), 1)
  263. self.assertEqual(db.tt.insert(aa='2'), 2)
  264. self.assertEqual(db.tt.insert(aa='3'), 3)
  265. self.assertEqual(len(db.tt.all()), 3)
  266. db.tt.drop()
  267. class TestBelongs(unittest.TestCase):
  268. def testRun(self):
  269. db = DAL(DEFAULT_URI, check_reserved=['all'])
  270. db.define_table('tt', Field('aa'))
  271. self.assertEqual(db.tt.insert(aa='1'), 1)
  272. self.assertEqual(db.tt.insert(aa='2'), 2)
  273. self.assertEqual(db.tt.insert(aa='3'), 3)
  274. self.assertEqual(db(db.tt.aa.belongs(('1', '3'))).count(),
  275. 2)
  276. self.assertEqual(db(db.tt.aa.belongs(db(db.tt.id
  277. > 2)._select(db.tt.aa))).count(), 1)
  278. self.assertEqual(db(db.tt.aa.belongs(db(db.tt.aa.belongs(('1',
  279. '3')))._select(db.tt.aa))).count(), 2)
  280. self.assertEqual(db(db.tt.aa.belongs(db(db.tt.aa.belongs(db
  281. (db.tt.aa.belongs(('1', '3')))._select(db.tt.aa)))._select(
  282. db.tt.aa))).count(),
  283. 2)
  284. db.tt.drop()
  285. class TestContains(unittest.TestCase):
  286. def testRun(self):
  287. db = DAL(DEFAULT_URI, check_reserved=['all'])
  288. db.define_table('tt', Field('aa', 'list:string'), Field('bb','string'))
  289. self.assertEqual(db.tt.insert(aa=['aaa','bbb'],bb='aaa'), 1)
  290. self.assertEqual(db.tt.insert(aa=['bbb','ddd'],bb='abb'), 2)
  291. self.assertEqual(db.tt.insert(aa=['eee','aaa'],bb='acc'), 3)
  292. self.assertEqual(db(db.tt.aa.contains('aaa')).count(), 2)
  293. self.assertEqual(db(db.tt.aa.contains('bbb')).count(), 2)
  294. self.assertEqual(db(db.tt.aa.contains('aa')).count(), 0)
  295. self.assertEqual(db(db.tt.bb.contains('a')).count(), 3)
  296. self.assertEqual(db(db.tt.bb.contains('b')).count(), 1)
  297. self.assertEqual(db(db.tt.bb.contains('d')).count(), 0)
  298. self.assertEqual(db(db.tt.aa.contains(db.tt.bb)).count(), 1)
  299. db.tt.drop()
  300. class TestLike(unittest.TestCase):
  301. def testRun(self):
  302. db = DAL(DEFAULT_URI, check_reserved=['all'])
  303. db.define_table('tt', Field('aa'))
  304. self.assertEqual(db.tt.insert(aa='abc'), 1)
  305. self.assertEqual(db(db.tt.aa.like('a%')).count(), 1)
  306. self.assertEqual(db(db.tt.aa.like('%b%')).count(), 1)
  307. self.assertEqual(db(db.tt.aa.like('%c')).count(), 1)
  308. self.assertEqual(db(db.tt.aa.like('%d%')).count(), 0)
  309. self.assertEqual(db(db.tt.aa.lower().like('A%')).count(), 1)
  310. self.assertEqual(db(db.tt.aa.lower().like('%B%')).count(),
  311. 1)
  312. self.assertEqual(db(db.tt.aa.lower().like('%C')).count(), 1)
  313. self.assertEqual(db(db.tt.aa.upper().like('A%')).count(), 1)
  314. self.assertEqual(db(db.tt.aa.upper().like('%B%')).count(),
  315. 1)
  316. self.assertEqual(db(db.tt.aa.upper().like('%C')).count(), 1)
  317. db.tt.drop()
  318. db.define_table('tt', Field('aa', 'integer'))
  319. self.assertEqual(db.tt.insert(aa=1111111111), 1)
  320. self.assertEqual(db(db.tt.aa.like('1%')).count(), 1)
  321. self.assertEqual(db(db.tt.aa.like('2%')).count(), 0)
  322. db.tt.drop()
  323. class TestDatetime(unittest.TestCase):
  324. def testRun(self):
  325. db = DAL(DEFAULT_URI, check_reserved=['all'])
  326. db.define_table('tt', Field('aa', 'datetime'))
  327. self.assertEqual(db.tt.insert(aa=datetime.datetime(1971, 12, 21,
  328. 11, 30)), 1)
  329. self.assertEqual(db.tt.insert(aa=datetime.datetime(1971, 11, 21,
  330. 10, 30)), 2)
  331. self.assertEqual(db.tt.insert(aa=datetime.datetime(1970, 12, 21,
  332. 9, 30)), 3)
  333. self.assertEqual(db(db.tt.aa == datetime.datetime(1971, 12,
  334. 21, 11, 30)).count(), 1)
  335. self.assertEqual(db(db.tt.aa.year() == 1971).count(), 2)
  336. self.assertEqual(db(db.tt.aa.month() == 12).count(), 2)
  337. self.assertEqual(db(db.tt.aa.day() == 21).count(), 3)
  338. self.assertEqual(db(db.tt.aa.hour() == 11).count(), 1)
  339. self.assertEqual(db(db.tt.aa.minutes() == 30).count(), 3)
  340. self.assertEqual(db(db.tt.aa.seconds() == 0).count(), 3)
  341. self.assertEqual(db(db.tt.aa.epoch()<365*24*3600).count(),1)
  342. db.tt.drop()
  343. class TestExpressions(unittest.TestCase):
  344. def testRun(self):
  345. db = DAL(DEFAULT_URI, check_reserved=['all'])
  346. db.define_table('tt', Field('aa', 'integer'))
  347. self.assertEqual(db.tt.insert(aa=1), 1)
  348. self.assertEqual(db.tt.insert(aa=2), 2)
  349. self.assertEqual(db.tt.insert(aa=3), 3)
  350. self.assertEqual(db(db.tt.aa == 3).update(aa=db.tt.aa + 1), 1)
  351. self.assertEqual(db(db.tt.aa == 4).count(), 1)
  352. self.assertEqual(db(db.tt.aa == -2).count(), 0)
  353. sum = (db.tt.aa + 1).sum()
  354. self.assertEqual(db(db.tt.aa == 2).select(sum).first()[sum], 3)
  355. self.assertEqual(db(db.tt.aa == -2).select(sum).first()[sum], None)
  356. db.tt.drop()
  357. class TestJoin(unittest.TestCase):
  358. def testRun(self):
  359. db = DAL(DEFAULT_URI, check_reserved=['all'])
  360. db.define_table('t1', Field('aa'))
  361. db.define_table('t2', Field('aa'), Field('b', db.t1))
  362. i1 = db.t1.insert(aa='1')
  363. i2 = db.t1.insert(aa='2')
  364. i3 = db.t1.insert(aa='3')
  365. db.t2.insert(aa='4', b=i1)
  366. db.t2.insert(aa='5', b=i2)
  367. db.t2.insert(aa='6', b=i2)
  368. self.assertEqual(len(db(db.t1.id
  369. == db.t2.b).select(orderby=db.t1.aa
  370. | db.t2.aa)), 3)
  371. self.assertEqual(db(db.t1.id == db.t2.b).select(orderby=db.t1.aa
  372. | db.t2.aa)[2].t1.aa, '2')
  373. self.assertEqual(db(db.t1.id == db.t2.b).select(orderby=db.t1.aa
  374. | db.t2.aa)[2].t2.aa, '6')
  375. self.assertEqual(len(db().select(db.t1.ALL, db.t2.ALL,
  376. left=db.t2.on(db.t1.id == db.t2.b),
  377. orderby=db.t1.aa | db.t2.aa)), 4)
  378. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  379. left=db.t2.on(db.t1.id == db.t2.b),
  380. orderby=db.t1.aa | db.t2.aa)[2].t1.aa, '2')
  381. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  382. left=db.t2.on(db.t1.id == db.t2.b),
  383. orderby=db.t1.aa | db.t2.aa)[2].t2.aa, '6')
  384. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  385. left=db.t2.on(db.t1.id == db.t2.b),
  386. orderby=db.t1.aa | db.t2.aa)[3].t1.aa, '3')
  387. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  388. left=db.t2.on(db.t1.id == db.t2.b),
  389. orderby=db.t1.aa | db.t2.aa)[3].t2.aa, None)
  390. self.assertEqual(len(db().select(db.t1.aa, db.t2.id.count(),
  391. left=db.t2.on(db.t1.id == db.t2.b),
  392. orderby=db.t1.aa, groupby=db.t1.aa)),
  393. 3)
  394. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  395. left=db.t2.on(db.t1.id == db.t2.b),
  396. orderby=db.t1.aa,
  397. groupby=db.t1.aa)[0]._extra[db.t2.id.count()],
  398. 1)
  399. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  400. left=db.t2.on(db.t1.id == db.t2.b),
  401. orderby=db.t1.aa,
  402. groupby=db.t1.aa)[1]._extra[db.t2.id.count()],
  403. 2)
  404. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  405. left=db.t2.on(db.t1.id == db.t2.b),
  406. orderby=db.t1.aa,
  407. groupby=db.t1.aa)[2]._extra[db.t2.id.count()],
  408. 0)
  409. db.t2.drop()
  410. db.t1.drop()
  411. db.define_table('person',Field('name'))
  412. id = db.person.insert(name="max")
  413. self.assertEqual(id.name,'max')
  414. db.define_table('dog',Field('name'),Field('ownerperson','reference person'))
  415. db.dog.insert(name='skipper',ownerperson=1)
  416. row = db(db.person.id==db.dog.ownerperson).select().first()
  417. self.assertEqual(row[db.person.name],'max')
  418. self.assertEqual(row['person.name'],'max')
  419. db.dog.drop()
  420. self.assertEqual(len(db.person._referenced_by),0)
  421. db.person.drop()
  422. class TestMinMaxSumAvg(unittest.TestCase):
  423. def testRun(self):
  424. db = DAL(DEFAULT_URI, check_reserved=['all'])
  425. db.define_table('tt', Field('aa', 'integer'))
  426. self.assertEqual(db.tt.insert(aa=1), 1)
  427. self.assertEqual(db.tt.insert(aa=2), 2)
  428. self.assertEqual(db.tt.insert(aa=3), 3)
  429. s = db.tt.aa.min()
  430. self.assertEqual(db(db.tt.id > 0).select(s)[0]._extra[s], 1)
  431. self.assertEqual(db(db.tt.id > 0).select(s).first()[s], 1)
  432. self.assertEqual(db().select(s).first()[s], 1)
  433. s = db.tt.aa.max()
  434. self.assertEqual(db().select(s).first()[s], 3)
  435. s = db.tt.aa.sum()
  436. self.assertEqual(db().select(s).first()[s], 6)
  437. s = db.tt.aa.count()
  438. self.assertEqual(db().select(s).first()[s], 3)
  439. s = db.tt.aa.avg()
  440. self.assertEqual(db().select(s).first()[s], 2)
  441. db.tt.drop()
  442. class TestCache(unittest.TestCase):
  443. def testRun(self):
  444. from cache import CacheInRam
  445. cache = CacheInRam()
  446. db = DAL(DEFAULT_URI, check_reserved=['all'])
  447. db.define_table('tt', Field('aa'))
  448. db.tt.insert(aa='1')
  449. r0 = db().select(db.tt.ALL)
  450. r1 = db().select(db.tt.ALL, cache=(cache, 1000))
  451. self.assertEqual(len(r0),len(r1))
  452. r2 = db().select(db.tt.ALL, cache=(cache, 1000))
  453. self.assertEqual(len(r0),len(r2))
  454. r3 = db().select(db.tt.ALL, cache=(cache, 1000), cacheable=True)
  455. self.assertEqual(len(r0),len(r3))
  456. r4 = db().select(db.tt.ALL, cache=(cache, 1000), cacheable=True)
  457. self.assertEqual(len(r0),len(r4))
  458. db.tt.drop()
  459. class TestMigrations(unittest.TestCase):
  460. def testRun(self):
  461. db = DAL(DEFAULT_URI, check_reserved=['all'])
  462. db.define_table('tt', Field('aa'), migrate='.storage.table')
  463. db.commit()
  464. db.close()
  465. db = DAL(DEFAULT_URI, check_reserved=['all'])
  466. db.define_table('tt', Field('aa'), Field('b'),
  467. migrate='.storage.table')
  468. db.commit()
  469. db.close()
  470. db = DAL(DEFAULT_URI, check_reserved=['all'])
  471. db.define_table('tt', Field('aa'), Field('b', 'text'),
  472. migrate='.storage.table')
  473. db.commit()
  474. db.close()
  475. db = DAL(DEFAULT_URI, check_reserved=['all'])
  476. db.define_table('tt', Field('aa'), migrate='.storage.table')
  477. db.tt.drop()
  478. db.commit()
  479. db.close()
  480. def tearDown(self):
  481. if os.path.exists('.storage.db'):
  482. os.unlink('.storage.db')
  483. if os.path.exists('.storage.table'):
  484. os.unlink('.storage.table')
  485. class TestReference(unittest.TestCase):
  486. def testRun(self):
  487. db = DAL(DEFAULT_URI, check_reserved=['all'])
  488. if DEFAULT_URI.startswith('mssql'):
  489. #multiple cascade gotcha
  490. for key in ['reference','reference FK']:
  491. db._adapter.types[key]=db._adapter.types[key].replace(
  492. '%(on_delete_action)s','NO ACTION')
  493. db.define_table('tt', Field('name'), Field('aa','reference tt'))
  494. db.commit()
  495. x = db.tt.insert(name='max')
  496. assert x.id == 1
  497. assert x['id'] == 1
  498. x.aa = x
  499. assert x.aa == 1
  500. x.update_record()
  501. y = db.tt[1]
  502. assert y.aa == 1
  503. assert y.aa.aa.aa.aa.aa.aa.name == 'max'
  504. z=db.tt.insert(name='xxx', aa = y)
  505. assert z.aa == y.id
  506. db.tt.drop()
  507. db.commit()
  508. class TestClientLevelOps(unittest.TestCase):
  509. def testRun(self):
  510. db = DAL(DEFAULT_URI, check_reserved=['all'])
  511. db.define_table('tt', Field('aa'))
  512. db.commit()
  513. db.tt.insert(aa="test")
  514. rows1 = db(db.tt.id>0).select()
  515. rows2 = db(db.tt.id>0).select()
  516. rows3 = rows1 & rows2
  517. assert len(rows3) == 2
  518. rows4 = rows1 | rows2
  519. assert len(rows4) == 1
  520. rows5 = rows1.find(lambda row: row.aa=="test")
  521. assert len(rows5) == 1
  522. rows6 = rows2.exclude(lambda row: row.aa=="test")
  523. assert len(rows6) == 1
  524. rows7 = rows5.sort(lambda row: row.aa)
  525. assert len(rows7) == 1
  526. db.tt.drop()
  527. db.commit()
  528. class TestVirtualFields(unittest.TestCase):
  529. def testRun(self):
  530. db = DAL(DEFAULT_URI, check_reserved=['all'])
  531. db.define_table('tt', Field('aa'))
  532. db.commit()
  533. db.tt.insert(aa="test")
  534. class Compute:
  535. def a_upper(row): return row.tt.aa.upper()
  536. db.tt.virtualfields.append(Compute())
  537. assert db(db.tt.id>0).select().first().a_upper == 'TEST'
  538. db.tt.drop()
  539. db.commit()
  540. class TestComputedFields(unittest.TestCase):
  541. def testRun(self):
  542. db = DAL(DEFAULT_URI, check_reserved=['all'])
  543. db.define_table('tt',
  544. Field('aa'),
  545. Field('bb',default='x'),
  546. Field('cc',compute=lambda r: r.aa+r.bb))
  547. db.commit()
  548. id = db.tt.insert(aa="z")
  549. self.assertEqual(db.tt[id].cc,'zx')
  550. db.tt.drop()
  551. db.commit()
  552. # test checking that a compute field can refer to earlier-defined computed fields
  553. db.define_table('tt',
  554. Field('aa'),
  555. Field('bb',default='x'),
  556. Field('cc',compute=lambda r: r.aa+r.bb),
  557. Field('dd',compute=lambda r: r.bb + r.cc))
  558. db.commit()
  559. id = db.tt.insert(aa="z")
  560. self.assertEqual(db.tt[id].dd,'xzx')
  561. db.tt.drop()
  562. db.commit()
  563. class TestCommonFilters(unittest.TestCase):
  564. def testRun(self):
  565. db = DAL(DEFAULT_URI, check_reserved=['all'])
  566. db.define_table('t1', Field('aa'))
  567. db.define_table('t2', Field('aa'), Field('b', db.t1))
  568. i1 = db.t1.insert(aa='1')
  569. i2 = db.t1.insert(aa='2')
  570. i3 = db.t1.insert(aa='3')
  571. db.t2.insert(aa='4', b=i1)
  572. db.t2.insert(aa='5', b=i2)
  573. db.t2.insert(aa='6', b=i2)
  574. db.t1._common_filter = lambda q: db.t1.aa>1
  575. self.assertEqual(db(db.t1).count(),2)
  576. self.assertEqual(db(db.t1).count(),2)
  577. q = db.t2.b==db.t1.id
  578. self.assertEqual(db(q).count(),2)
  579. self.assertEqual(db(q).count(),2)
  580. self.assertEqual(len(db(db.t1).select(left=db.t2.on(q))),3)
  581. db.t2._common_filter = lambda q: db.t2.aa<6
  582. self.assertEqual(db(q).count(),1)
  583. self.assertEqual(db(q).count(),1)
  584. self.assertEqual(len(db(db.t1).select(left=db.t2.on(q))),2)
  585. db.t2.drop()
  586. db.t1.drop()
  587. class TestImportExportFields(unittest.TestCase):
  588. def testRun(self):
  589. db = DAL(DEFAULT_URI, check_reserved=['all'])
  590. db.define_table('person', Field('name'))
  591. db.define_table('pet',Field('friend',db.person),Field('name'))
  592. for n in range(2):
  593. db(db.pet).delete()
  594. db(db.person).delete()
  595. for k in range(10):
  596. id = db.person.insert(name=str(k))
  597. db.pet.insert(friend=id,name=str(k))
  598. db.commit()
  599. stream = StringIO.StringIO()
  600. db.export_to_csv_file(stream)
  601. db(db.pet).delete()
  602. db(db.person).delete()
  603. stream = StringIO.StringIO(stream.getvalue())
  604. db.import_from_csv_file(stream)
  605. assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==10
  606. db.pet.drop()
  607. db.person.drop()
  608. db.commit()
  609. class TestImportExportUuidFields(unittest.TestCase):
  610. def testRun(self):
  611. db = DAL(DEFAULT_URI, check_reserved=['all'])
  612. db.define_table('person', Field('name'),Field('uuid'))
  613. db.define_table('pet',Field('friend',db.person),Field('name'))
  614. for n in range(2):
  615. db(db.pet).delete()
  616. db(db.person).delete()
  617. for k in range(10):
  618. id = db.person.insert(name=str(k),uuid=str(k))
  619. db.pet.insert(friend=id,name=str(k))
  620. db.commit()
  621. stream = StringIO.StringIO()
  622. db.export_to_csv_file(stream)
  623. stream = StringIO.StringIO(stream.getvalue())
  624. db.import_from_csv_file(stream)
  625. assert db(db.person).count()==10
  626. assert db(db.person.id==db.pet.friend)(db.person.name==db.pet.name).count()==20
  627. db.pet.drop()
  628. db.person.drop()
  629. db.commit()
  630. class TestDALDictImportExport(unittest.TestCase):
  631. def testRun(self):
  632. db = DAL(DEFAULT_URI, check_reserved=['all'])
  633. db.define_table('person', Field('name', default="Michael"),Field('uuid'))
  634. db.define_table('pet',Field('friend',db.person),Field('name'))
  635. dbdict = db.as_dict(flat=True, sanitize=False)
  636. assert isinstance(dbdict, dict)
  637. uri = dbdict["uri"]
  638. assert isinstance(uri, basestring) and uri
  639. assert len(dbdict["tables"]) == 2
  640. assert len(dbdict["tables"][0]["fields"]) == 3
  641. assert dbdict["tables"][0]["fields"][1]["type"] == db.person.name.type
  642. assert dbdict["tables"][0]["fields"][1]["default"] == db.person.name.default
  643. db2 = DAL(**dbdict)
  644. assert len(db.tables) == len(db2.tables)
  645. assert hasattr(db2, "pet") and isinstance(db2.pet, Table)
  646. assert hasattr(db2.pet, "friend") and isinstance(db2.pet.friend, Field)
  647. db.pet.drop()
  648. db.commit()
  649. db2.commit()
  650. have_serializers = True
  651. try:
  652. import serializers
  653. dbjson = db.as_json(sanitize=False)
  654. assert isinstance(dbjson, basestring) and len(dbjson) > 0
  655. unicode_keys = True
  656. if sys.version < "2.6.5":
  657. unicode_keys = False
  658. db3 = DAL(**serializers.loads_json(dbjson,
  659. unicode_keys=unicode_keys))
  660. assert hasattr(db3, "person") and hasattr(db3.person, "uuid") and\
  661. db3.person.uuid.type == db.person.uuid.type
  662. db3.person.drop()
  663. db3.commit()
  664. except ImportError:
  665. pass
  666. mpfc = "Monty Python's Flying Circus"
  667. dbdict4 = {"uri": DEFAULT_URI,
  668. "tables":[{"tablename": "tvshow",
  669. "fields": [{"fieldname": "name",
  670. "default":mpfc},
  671. {"fieldname": "rating",
  672. "type":"double"}]},
  673. {"tablename": "staff",
  674. "fields": [{"fieldname": "name",
  675. "default":"Michael"},
  676. {"fieldname": "food",
  677. "default":"Spam"},
  678. {"fieldname": "tvshow",
  679. "type": "reference tvshow"}]}]}
  680. db4 = DAL(**dbdict4)
  681. assert "staff" in db4.tables
  682. assert "name" in db4.staff
  683. assert db4.tvshow.rating.type == "double"
  684. assert (db4.tvshow.insert(), db4.tvshow.insert(name="Loriot"),
  685. db4.tvshow.insert(name="Il Mattatore")) == (1, 2, 3)
  686. assert db4(db4.tvshow).select().first().id == 1
  687. assert db4(db4.tvshow).select().first().name == mpfc
  688. db4.staff.drop()
  689. db4.tvshow.drop()
  690. db4.commit()
  691. dbdict5 = {"uri": DEFAULT_URI}
  692. db5 = DAL(**dbdict5)
  693. assert db5.tables in ([], None)
  694. assert not (str(db5) in ("", None))
  695. dbdict6 = {"uri": DEFAULT_URI,
  696. "tables":[{"tablename": "staff"},
  697. {"tablename": "tvshow",
  698. "fields": [{"fieldname": "name"},
  699. {"fieldname": "rating", "type":"double"}
  700. ]
  701. }]
  702. }
  703. db6 = DAL(**dbdict6)
  704. assert len(db6["staff"].fields) == 1
  705. assert "name" in db6["tvshow"].fields
  706. assert db6.staff.insert() is not None
  707. assert db6(db6.staff).select().first().id == 1
  708. db6.staff.drop()
  709. db6.tvshow.drop()
  710. db6.commit()
  711. class TestValidateAndInsert(unittest.TestCase):
  712. def testRun(self):
  713. import datetime
  714. from gluon.validators import IS_INT_IN_RANGE
  715. db = DAL(DEFAULT_URI, check_reserved=['all'])
  716. db.define_table('val_and_insert',
  717. Field('aa'),
  718. Field('bb', 'integer',
  719. requires=IS_INT_IN_RANGE(1,5))
  720. )
  721. rtn = db.val_and_insert.validate_and_insert(aa='test1', bb=2)
  722. self.assertEqual(rtn.id, 1)
  723. #errors should be empty
  724. self.assertEqual(len(rtn.errors.keys()), 0)
  725. #this insert won't pass
  726. rtn = db.val_and_insert.validate_and_insert(bb="a")
  727. #the returned id should be None
  728. self.assertEqual(rtn.id, None)
  729. #an error message should be in rtn.errors.bb
  730. self.assertNotEqual(rtn.errors.bb, None)
  731. #cleanup table
  732. db.val_and_insert.drop()
  733. class TestSelectAsDict(unittest.TestCase):
  734. def testSelect(self):
  735. db = DAL(DEFAULT_URI, check_reserved=['all'])
  736. db.define_table(
  737. 'a_table',
  738. Field('b_field'),
  739. Field('a_field'),
  740. )
  741. db.a_table.insert(a_field="aa1", b_field="bb1")
  742. rtn = db.executesql("SELECT id, b_field, a_field FROM a_table", as_dict=True)
  743. self.assertEqual(rtn[0]['b_field'], 'bb1')
  744. rtn = db.executesql("SELECT id, b_field, a_field FROM a_table", as_ordered_dict=True)
  745. self.assertEqual(rtn[0]['b_field'], 'bb1')
  746. self.assertEqual(rtn[0].keys(), ['id', 'b_field', 'a_field'])
  747. db.a_table.drop()
  748. class TestRNameTable(unittest.TestCase):
  749. #tests for highly experimental rname attribute
  750. def testSelect(self):
  751. db = DAL(DEFAULT_URI, check_reserved=['all'])
  752. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'a very complicated tablename'
  753. db.define_table(
  754. 'easy_name',
  755. Field('a_field'),
  756. rname=rname
  757. )
  758. rtn = db.easy_name.insert(a_field='a')
  759. self.assertEqual(rtn.id, 1)
  760. rtn = db(db.easy_name.a_field == 'a').select()
  761. self.assertEqual(len(rtn), 1)
  762. self.assertEqual(rtn[0].id, 1)
  763. self.assertEqual(rtn[0].a_field, 'a')
  764. db.easy_name.insert(a_field='b')
  765. rtn = db(db.easy_name.id > 0).delete()
  766. self.assertEqual(rtn, 2)
  767. rtn = db(db.easy_name.id > 0).count()
  768. self.assertEqual(rtn, 0)
  769. db.easy_name.insert(a_field='a')
  770. db.easy_name.insert(a_field='b')
  771. rtn = db(db.easy_name.id > 0).count()
  772. self.assertEqual(rtn, 2)
  773. rtn = db(db.easy_name.a_field == 'a').update(a_field='c')
  774. rtn = db(db.easy_name.a_field == 'c').count()
  775. self.assertEqual(rtn, 1)
  776. rtn = db(db.easy_name.a_field != 'c').count()
  777. self.assertEqual(rtn, 1)
  778. avg = db.easy_name.id.avg()
  779. rtn = db(db.easy_name.id > 0).select(avg)
  780. self.assertEqual(rtn[0][avg], 3)
  781. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'this is the person table'
  782. db.define_table(
  783. 'person',
  784. Field('name', default="Michael"),
  785. Field('uuid'),
  786. rname=rname
  787. )
  788. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'this is the pet table'
  789. db.define_table(
  790. 'pet',
  791. Field('friend','reference person'),
  792. Field('name'),
  793. rname=rname
  794. )
  795. michael = db.person.insert() #default insert
  796. john = db.person.insert(name='John')
  797. luke = db.person.insert(name='Luke')
  798. #michael owns Phippo
  799. phippo = db.pet.insert(friend=michael, name="Phippo")
  800. #john owns Dunstin and Gertie
  801. dunstin = db.pet.insert(friend=john, name="Dunstin")
  802. gertie = db.pet.insert(friend=john, name="Gertie")
  803. rtn = db(db.person.id == db.pet.friend).select(orderby=db.person.id|db.pet.id)
  804. self.assertEqual(len(rtn), 3)
  805. self.assertEqual(rtn[0].person.id, michael)
  806. self.assertEqual(rtn[0].person.name, 'Michael')
  807. self.assertEqual(rtn[0].pet.id, phippo)
  808. self.assertEqual(rtn[0].pet.name, 'Phippo')
  809. self.assertEqual(rtn[1].person.id, john)
  810. self.assertEqual(rtn[1].person.name, 'John')
  811. self.assertEqual(rtn[1].pet.name, 'Dunstin')
  812. self.assertEqual(rtn[2].pet.name, 'Gertie')
  813. #fetch owners, eventually with pet
  814. #main point is retrieving Luke with no pets
  815. rtn = db(db.person.id > 0).select(
  816. orderby=db.person.id|db.pet.id,
  817. left=db.pet.on(db.person.id == db.pet.friend)
  818. )
  819. self.assertEqual(rtn[0].person.id, michael)
  820. self.assertEqual(rtn[0].person.name, 'Michael')
  821. self.assertEqual(rtn[0].pet.id, phippo)
  822. self.assertEqual(rtn[0].pet.name, 'Phippo')
  823. self.assertEqual(rtn[3].person.name, 'Luke')
  824. self.assertEqual(rtn[3].person.id, luke)
  825. self.assertEqual(rtn[3].pet.name, None)
  826. #lets test a subquery
  827. subq = db(db.pet.name == "Gertie")._select(db.pet.friend)
  828. rtn = db(db.person.id.belongs(subq)).select()
  829. self.assertEqual(rtn[0].id, 2)
  830. self.assertEqual(rtn[0]('person.name'), 'John')
  831. #as dict
  832. rtn = db(db.person.id > 0).select().as_dict()
  833. self.assertEqual(rtn[1]['name'], 'Michael')
  834. #as list
  835. rtn = db(db.person.id > 0).select().as_list()
  836. self.assertEqual(rtn[0]['name'], 'Michael')
  837. #isempty
  838. rtn = db(db.person.id > 0).isempty()
  839. self.assertEqual(rtn, False)
  840. #join argument
  841. rtn = db(db.person).select(orderby=db.person.id|db.pet.id,
  842. join=db.pet.on(db.person.id==db.pet.friend))
  843. self.assertEqual(len(rtn), 3)
  844. self.assertEqual(rtn[0].person.id, michael)
  845. self.assertEqual(rtn[0].person.name, 'Michael')
  846. self.assertEqual(rtn[0].pet.id, phippo)
  847. self.assertEqual(rtn[0].pet.name, 'Phippo')
  848. self.assertEqual(rtn[1].person.id, john)
  849. self.assertEqual(rtn[1].person.name, 'John')
  850. self.assertEqual(rtn[1].pet.name, 'Dunstin')
  851. self.assertEqual(rtn[2].pet.name, 'Gertie')
  852. #aliases
  853. if DEFAULT_URI.startswith('mssql'):
  854. #multiple cascade gotcha
  855. for key in ['reference','reference FK']:
  856. db._adapter.types[key]=db._adapter.types[key].replace(
  857. '%(on_delete_action)s','NO ACTION')
  858. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'the cubs'
  859. db.define_table('pet_farm',
  860. Field('name'),
  861. Field('father','reference pet_farm'),
  862. Field('mother','reference pet_farm'),
  863. rname=rname
  864. )
  865. minali = db.pet_farm.insert(name='Minali')
  866. osbert = db.pet_farm.insert(name='Osbert')
  867. #they had a cub
  868. selina = db.pet_farm.insert(name='Selina', father=osbert, mother=minali)
  869. father = db.pet_farm.with_alias('father')
  870. mother = db.pet_farm.with_alias('mother')
  871. #fetch pets with relatives
  872. rtn = db().select(
  873. db.pet_farm.name, father.name, mother.name,
  874. left=[
  875. father.on(father.id == db.pet_farm.father),
  876. mother.on(mother.id == db.pet_farm.mother)
  877. ],
  878. orderby=db.pet_farm.id
  879. )
  880. self.assertEqual(len(rtn), 3)
  881. self.assertEqual(rtn[0].pet_farm.name, 'Minali')
  882. self.assertEqual(rtn[0].father.name, None)
  883. self.assertEqual(rtn[0].mother.name, None)
  884. self.assertEqual(rtn[1].pet_farm.name, 'Osbert')
  885. self.assertEqual(rtn[2].pet_farm.name, 'Selina')
  886. self.assertEqual(rtn[2].father.name, 'Osbert')
  887. self.assertEqual(rtn[2].mother.name, 'Minali')
  888. #clean up
  889. db.pet_farm.drop()
  890. db.pet.drop()
  891. db.person.drop()
  892. db.easy_name.drop()
  893. def testJoin(self):
  894. db = DAL(DEFAULT_URI, check_reserved=['all'])
  895. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'this is table t1'
  896. rname2 = db._adapter.__class__.QUOTE_TEMPLATE % 'this is table t2'
  897. db.define_table('t1', Field('aa'), rname=rname)
  898. db.define_table('t2', Field('aa'), Field('b', db.t1), rname=rname2)
  899. i1 = db.t1.insert(aa='1')
  900. i2 = db.t1.insert(aa='2')
  901. i3 = db.t1.insert(aa='3')
  902. db.t2.insert(aa='4', b=i1)
  903. db.t2.insert(aa='5', b=i2)
  904. db.t2.insert(aa='6', b=i2)
  905. self.assertEqual(len(db(db.t1.id
  906. == db.t2.b).select(orderby=db.t1.aa
  907. | db.t2.aa)), 3)
  908. self.assertEqual(db(db.t1.id == db.t2.b).select(orderby=db.t1.aa
  909. | db.t2.aa)[2].t1.aa, '2')
  910. self.assertEqual(db(db.t1.id == db.t2.b).select(orderby=db.t1.aa
  911. | db.t2.aa)[2].t2.aa, '6')
  912. self.assertEqual(len(db().select(db.t1.ALL, db.t2.ALL,
  913. left=db.t2.on(db.t1.id == db.t2.b),
  914. orderby=db.t1.aa | db.t2.aa)), 4)
  915. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  916. left=db.t2.on(db.t1.id == db.t2.b),
  917. orderby=db.t1.aa | db.t2.aa)[2].t1.aa, '2')
  918. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  919. left=db.t2.on(db.t1.id == db.t2.b),
  920. orderby=db.t1.aa | db.t2.aa)[2].t2.aa, '6')
  921. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  922. left=db.t2.on(db.t1.id == db.t2.b),
  923. orderby=db.t1.aa | db.t2.aa)[3].t1.aa, '3')
  924. self.assertEqual(db().select(db.t1.ALL, db.t2.ALL,
  925. left=db.t2.on(db.t1.id == db.t2.b),
  926. orderby=db.t1.aa | db.t2.aa)[3].t2.aa, None)
  927. self.assertEqual(len(db().select(db.t1.aa, db.t2.id.count(),
  928. left=db.t2.on(db.t1.id == db.t2.b),
  929. orderby=db.t1.aa, groupby=db.t1.aa)),
  930. 3)
  931. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  932. left=db.t2.on(db.t1.id == db.t2.b),
  933. orderby=db.t1.aa,
  934. groupby=db.t1.aa)[0]._extra[db.t2.id.count()],
  935. 1)
  936. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  937. left=db.t2.on(db.t1.id == db.t2.b),
  938. orderby=db.t1.aa,
  939. groupby=db.t1.aa)[1]._extra[db.t2.id.count()],
  940. 2)
  941. self.assertEqual(db().select(db.t1.aa, db.t2.id.count(),
  942. left=db.t2.on(db.t1.id == db.t2.b),
  943. orderby=db.t1.aa,
  944. groupby=db.t1.aa)[2]._extra[db.t2.id.count()],
  945. 0)
  946. db.t2.drop()
  947. db.t1.drop()
  948. db.define_table('person',Field('name'), rname=rname)
  949. id = db.person.insert(name="max")
  950. self.assertEqual(id.name,'max')
  951. db.define_table('dog',Field('name'),Field('ownerperson','reference person'), rname=rname2)
  952. db.dog.insert(name='skipper',ownerperson=1)
  953. row = db(db.person.id==db.dog.ownerperson).select().first()
  954. self.assertEqual(row[db.person.name],'max')
  955. self.assertEqual(row['person.name'],'max')
  956. db.dog.drop()
  957. self.assertEqual(len(db.person._referenced_by),0)
  958. db.person.drop()
  959. class TestRNameFields(unittest.TestCase):
  960. # tests for highly experimental rname attribute
  961. def testSelect(self):
  962. db = DAL(DEFAULT_URI, check_reserved=['all'])
  963. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'a very complicated fieldname'
  964. rname2 = db._adapter.__class__.QUOTE_TEMPLATE % 'rrating from 1 to 10'
  965. db.define_table(
  966. 'easy_name',
  967. Field('a_field', rname=rname),
  968. Field('rating', 'integer', rname=rname2, default=2)
  969. )
  970. rtn = db.easy_name.insert(a_field='a')
  971. self.assertEqual(rtn.id, 1)
  972. rtn = db(db.easy_name.a_field == 'a').select()
  973. self.assertEqual(len(rtn), 1)
  974. self.assertEqual(rtn[0].id, 1)
  975. self.assertEqual(rtn[0].a_field, 'a')
  976. db.easy_name.insert(a_field='b')
  977. rtn = db(db.easy_name.id > 0).delete()
  978. self.assertEqual(rtn, 2)
  979. rtn = db(db.easy_name.id > 0).count()
  980. self.assertEqual(rtn, 0)
  981. db.easy_name.insert(a_field='a')
  982. db.easy_name.insert(a_field='b')
  983. rtn = db(db.easy_name.id > 0).count()
  984. self.assertEqual(rtn, 2)
  985. rtn = db(db.easy_name.a_field == 'a').update(a_field='c')
  986. rtn = db(db.easy_name.a_field == 'c').count()
  987. self.assertEqual(rtn, 1)
  988. rtn = db(db.easy_name.a_field != 'c').count()
  989. self.assertEqual(rtn, 1)
  990. avg = db.easy_name.id.avg()
  991. rtn = db(db.easy_name.id > 0).select(avg)
  992. self.assertEqual(rtn[0][avg], 3)
  993. avg = db.easy_name.rating.avg()
  994. rtn = db(db.easy_name.id > 0).select(avg)
  995. self.assertEqual(rtn[0][avg], 2)
  996. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'this is the person name'
  997. db.define_table(
  998. 'person',
  999. Field('name', default="Michael", rname=rname),
  1000. Field('uuid')
  1001. )
  1002. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'this is the pet name'
  1003. db.define_table(
  1004. 'pet',
  1005. Field('friend','reference person'),
  1006. Field('name', rname=rname)
  1007. )
  1008. michael = db.person.insert() #default insert
  1009. john = db.person.insert(name='John')
  1010. luke = db.person.insert(name='Luke')
  1011. #michael owns Phippo
  1012. phippo = db.pet.insert(friend=michael, name="Phippo")
  1013. #john owns Dunstin and Gertie
  1014. dunstin = db.pet.insert(friend=john, name="Dunstin")
  1015. gertie = db.pet.insert(friend=john, name="Gertie")
  1016. rtn = db(db.person.id == db.pet.friend).select(orderby=db.person.id|db.pet.id)
  1017. self.assertEqual(len(rtn), 3)
  1018. self.assertEqual(rtn[0].person.id, michael)
  1019. self.assertEqual(rtn[0].person.name, 'Michael')
  1020. self.assertEqual(rtn[0].pet.id, phippo)
  1021. self.assertEqual(rtn[0].pet.name, 'Phippo')
  1022. self.assertEqual(rtn[1].person.id, john)
  1023. self.assertEqual(rtn[1].person.name, 'John')
  1024. self.assertEqual(rtn[1].pet.name, 'Dunstin')
  1025. self.assertEqual(rtn[2].pet.name, 'Gertie')
  1026. #fetch owners, eventually with pet
  1027. #main point is retrieving Luke with no pets
  1028. rtn = db(db.person.id > 0).select(
  1029. orderby=db.person.id|db.pet.id,
  1030. left=db.pet.on(db.person.id == db.pet.friend)
  1031. )
  1032. self.assertEqual(rtn[0].person.id, michael)
  1033. self.assertEqual(rtn[0].person.name, 'Michael')
  1034. self.assertEqual(rtn[0].pet.id, phippo)
  1035. self.assertEqual(rtn[0].pet.name, 'Phippo')
  1036. self.assertEqual(rtn[3].person.name, 'Luke')
  1037. self.assertEqual(rtn[3].person.id, luke)
  1038. self.assertEqual(rtn[3].pet.name, None)
  1039. #lets test a subquery
  1040. subq = db(db.pet.name == "Gertie")._select(db.pet.friend)
  1041. rtn = db(db.person.id.belongs(subq)).select()
  1042. self.assertEqual(rtn[0].id, 2)
  1043. self.assertEqual(rtn[0]('person.name'), 'John')
  1044. #as dict
  1045. rtn = db(db.person.id > 0).select().as_dict()
  1046. self.assertEqual(rtn[1]['name'], 'Michael')
  1047. #as list
  1048. rtn = db(db.person.id > 0).select().as_list()
  1049. self.assertEqual(rtn[0]['name'], 'Michael')
  1050. #isempty
  1051. rtn = db(db.person.id > 0).isempty()
  1052. self.assertEqual(rtn, False)
  1053. #join argument
  1054. rtn = db(db.person).select(orderby=db.person.id|db.pet.id,
  1055. join=db.pet.on(db.person.id==db.pet.friend))
  1056. self.assertEqual(len(rtn), 3)
  1057. self.assertEqual(rtn[0].person.id, michael)
  1058. self.assertEqual(rtn[0].person.name, 'Michael')
  1059. self.assertEqual(rtn[0].pet.id, phippo)
  1060. self.assertEqual(rtn[0].pet.name, 'Phippo')
  1061. self.assertEqual(rtn[1].person.id, john)
  1062. self.assertEqual(rtn[1].person.name, 'John')
  1063. self.assertEqual(rtn[1].pet.name, 'Dunstin')
  1064. self.assertEqual(rtn[2].pet.name, 'Gertie')
  1065. #aliases
  1066. rname = db._adapter.__class__.QUOTE_TEMPLATE % 'the cub name'
  1067. if DEFAULT_URI.startswith('mssql'):
  1068. #multiple cascade gotcha
  1069. for key in ['reference','reference FK']:
  1070. db._adapter.types[key]=db._adapter.types[key].replace(
  1071. '%(on_delete_action)s','NO ACTION')
  1072. db.define_table('pet_farm',
  1073. Field('name', rname=rname),
  1074. Field('father','reference pet_farm'),
  1075. Field('mother','reference pet_farm'),
  1076. )
  1077. minali = db.pet_farm.insert(name='Minali')
  1078. osbert = db.pet_farm.insert(name='Osbert')
  1079. #they had a cub
  1080. selina = db.pet_farm.insert(name='Selina', father=osbert, mother=minali)
  1081. father = db.pet_farm.with_alias('father')
  1082. mother = db.pet_farm.with_alias('mother')
  1083. #fetch pets with relatives
  1084. rtn = db().select(
  1085. db.pet_farm.name, father.name, mother.name,
  1086. left=[
  1087. father.on(father.id == db.pet_farm.father),
  1088. mother.on(mother.id == db.pet_farm.mother)
  1089. ],
  1090. orderby=db.pet_farm.id
  1091. )
  1092. self.assertEqual(len(rtn), 3)
  1093. self.assertEqual(rtn[0].pet_farm.name, 'Minali')
  1094. self.assertEqual(rtn[0].father.name, None)
  1095. self.assertEqual(rtn[0].mother.name, None)
  1096. self.assertEqual(rtn[1].pet_farm.name, 'Osbert')
  1097. self.assertEqual(rtn[2].pet_farm.name, 'Selina')
  1098. self.assertEqual(rtn[2].father.n

Large files files are truncated, but you can click here to view the full file