1
2
3
4
5
6
7
8
9
10
11
12
13
14 from __future__ import with_statement
15
16 import os
17 import unittest
18
19 import trac.tests.compat
20 from trac.config import ConfigurationError
21 from trac.db.api import DatabaseManager, _parse_db_str, get_column_names, \
22 with_transaction
23 from trac.db_default import schema as default_schema
24 from trac.db.schema import Column, Table
25 from trac.test import EnvironmentStub, Mock
26 from trac.util.concurrency import ThreadLocal
39
40
41 -class Error(Exception):
43
50
61
70 self.fail()
71 except Error:
72 pass
73 self.assertTrue(not db.committed and db.rolledback)
74
85 self.assertTrue(not db.committed and not db.rolledback)
86 self.assertTrue(dbs[0] is not None)
87 self.assertTrue(dbs[0] is dbs[1])
88 self.assertTrue(dbs[0].committed and not dbs[0].rolledback)
89
103 self.fail()
104 except Error:
105 self.assertTrue(not db.committed and not db.rolledback)
106 raise
107 self.fail()
108 except Error:
109 pass
110 self.assertTrue(dbs[0] is not None)
111 self.assertTrue(dbs[0] is dbs[1])
112 self.assertTrue(not dbs[0].committed and dbs[0].rolledback)
113
121 self.assertTrue(not db.committed and not db.rolledback)
122
132 self.fail()
133 except Error:
134 pass
135 self.assertTrue(not db.committed and not db.rolledback)
136
148 self.assertTrue(not db.committed and not db.rolledback)
149 self.assertTrue(dbs[0] is not None)
150 self.assertTrue(dbs[0] is dbs[1])
151 self.assertTrue(not dbs[0].committed and not dbs[0].rolledback)
152
166 self.fail()
167 self.fail()
168 except Error:
169 pass
170 self.assertTrue(dbs[0] is not None)
171 self.assertTrue(dbs[0] is dbs[1])
172 self.assertTrue(not dbs[0].committed and not dbs[0].rolledback)
173
185 self.assertTrue(not db.committed and not db.rolledback)
186 self.assertTrue(dbs[0] is not None)
187 self.assertTrue(dbs[0] is dbs[1])
188 self.assertTrue(dbs[0].committed and not dbs[0].rolledback)
189
203 self.fail()
204 self.fail()
205 except Error:
206 pass
207 self.assertTrue(dbs[0] is not None)
208 self.assertTrue(dbs[0] is dbs[1])
209 self.assertTrue(not dbs[0].committed and dbs[0].rolledback)
210
219 raise Error()
220 raise Error()
221 except AssertionError:
222 pass
223
227
229
230
231 self.assertEqual(('sqlite', {'path': 'db/trac.db'}),
232 _parse_db_str('sqlite:db/trac.db'))
233
235
236 self.assertEqual(('sqlite', {'path': '/var/db/trac.db'}),
237 _parse_db_str('sqlite:///var/db/trac.db'))
238
239 self.assertEqual(('sqlite', {'path': '/var/db/trac.db'}),
240 _parse_db_str('sqlite:/var/db/trac.db'))
241
243
244 self.assertEqual(('sqlite', {'path': 'db/trac.db',
245 'params': {'timeout': '10000'}}),
246 _parse_db_str('sqlite:db/trac.db?timeout=10000'))
247
249
250 os_name = os.name
251 try:
252 os.name = 'nt'
253 self.assertEqual(('sqlite', {'path': 'C:/project/db/trac.db'}),
254 _parse_db_str('sqlite:C|/project/db/trac.db'))
255 finally:
256 os.name = os_name
257
259 self.assertEqual(('postgres', {'host': 'localhost', 'path': '/trac'}),
260 _parse_db_str('postgres://localhost/trac'))
261
263 self.assertEqual(('postgres', {'host': 'localhost', 'port': 9431,
264 'path': '/trac'}),
265 _parse_db_str('postgres://localhost:9431/trac'))
266
268 self.assertEqual(('postgres', {'user': 'john', 'password': 'letmein',
269 'host': 'localhost', 'port': 9431,
270 'path': '/trac'}),
271 _parse_db_str('postgres://john:letmein@localhost:9431/trac'))
272
274 self.assertEqual(('postgres', {'user': 'john', 'password': ':@/',
275 'host': 'localhost', 'path': '/trac'}),
276 _parse_db_str('postgres://john:%3a%40%2f@localhost/trac'))
277
279 self.assertEqual(('mysql', {'host': 'localhost', 'path': '/trac'}),
280 _parse_db_str('mysql://localhost/trac'))
281
283 self.assertEqual(('mysql', {'user': 'john', 'password': 'letmein',
284 'host': 'localhost', 'port': 3306,
285 'path': '/trac'}),
286 _parse_db_str('mysql://john:letmein@localhost:3306/trac'))
287
290
292 self.assertRaises(ConfigurationError, _parse_db_str,
293 'postgres://localhost:42:42')
294
298
302
304 self.assertRaises(ConfigurationError, _parse_db_str,
305 'postgres://localhost/schema?name')
306
309
312
315
317 with self.env.db_transaction as db:
318 quoted = db.quote('system')
319 db("INSERT INTO " + quoted + " (name,value) VALUES (%s,%s)",
320 ('test-unicode', u'ünicöde'))
321 self.assertEqual([(u'ünicöde',)], self.env.db_query(
322 "SELECT value FROM " + quoted + " WHERE name='test-unicode'"))
323
332
334 from genshi.core import Markup
335 with self.env.db_transaction as db:
336 quoted = db.quote('system')
337 db("INSERT INTO " + quoted + " (name,value) VALUES (%s,%s)",
338 ('test-markup', Markup(u'<em>märkup</em>')))
339 self.assertEqual([(u'<em>märkup</em>',)], self.env.db_query(
340 "SELECT value FROM " + quoted + " WHERE name='test-markup'"))
341
349
351 db = self.env.get_read_db()
352 name = """%?`%s"%'%%"""
353
354 def test(db, logging=False):
355 cursor = db.cursor()
356 if logging:
357 cursor.log = self.env.log
358
359 cursor.execute('SELECT 1 AS ' + db.quote(name))
360 self.assertEqual(name, get_column_names(cursor)[0])
361 cursor.execute('SELECT %s AS ' + db.quote(name), (42,))
362 self.assertEqual(name, get_column_names(cursor)[0])
363 stmt = "UPDATE " + db.quote('system') + " SET value=%s " + \
364 "WHERE 1=(SELECT 0 AS " + db.quote(name) + ")"
365 cursor.executemany(stmt, [])
366 cursor.executemany(stmt, [('42',), ('43',)])
367
368 test(db)
369 test(db, logging=True)
370
372 @self.env.with_transaction()
373 def do_insert(db):
374 cursor = db.cursor()
375 cursor.executemany("INSERT INTO " + db.quote('system') +
376 " (name,value) VALUES (%s,1)",
377 [('blahblah',), ('BlahBlah',), ('BLAHBLAH',),
378 (u'BlähBlah',), (u'BlahBläh',)])
379
380 db = self.env.get_read_db()
381 cursor = db.cursor()
382 cursor.execute("SELECT name FROM " + db.quote('system') +
383 " WHERE name " + db.prefix_match(),
384 (db.prefix_match_value('Blah'),))
385 names = sorted(name for name, in cursor)
386 self.assertEqual('BlahBlah', names[0])
387 self.assertEqual(u'BlahBläh', names[1])
388 self.assertEqual(2, len(names))
389
399
400 @self.env.with_transaction()
401 def do_insert(db):
402 values = ['foo*bar', 'foo*bar!', 'foo?bar', 'foo?bar!',
403 'foo[bar', 'foo[bar!', 'foo]bar', 'foo]bar!',
404 'foo%bar', 'foo%bar!', 'foo_bar', 'foo_bar!',
405 'foo/bar', 'foo/bar!', 'fo*ob?ar[fo]ob%ar_fo/obar']
406 cursor = db.cursor()
407 cursor.executemany("INSERT INTO " + db.quote('system') +
408 " (name,value) VALUES (%s,1)",
409 [(value,) for value in values])
410
411 self.assertEqual(['foo*bar', 'foo*bar!'], do_query('foo*'))
412 self.assertEqual(['foo?bar', 'foo?bar!'], do_query('foo?'))
413 self.assertEqual(['foo[bar', 'foo[bar!'], do_query('foo['))
414 self.assertEqual(['foo]bar', 'foo]bar!'], do_query('foo]'))
415 self.assertEqual(['foo%bar', 'foo%bar!'], do_query('foo%'))
416 self.assertEqual(['foo_bar', 'foo_bar!'], do_query('foo_'))
417 self.assertEqual(['foo/bar', 'foo/bar!'], do_query('foo/'))
418 self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'], do_query('fo*'))
419 self.assertEqual(['fo*ob?ar[fo]ob%ar_fo/obar'],
420 do_query('fo*ob?ar[fo]ob%ar_fo/obar'))
421
437
441
457
469
482
484 """Test for regression described in comment:4:ticket:11512."""
485 with self.env.db_transaction as db:
486 db("INSERT INTO %s (%s, %s) VALUES (42, 'anonymous')"
487 % (db.quote('HOURS'), db.quote('ID'), db.quote('AUTHOR')))
488 cursor = db.cursor()
489 db.update_sequence(cursor, 'HOURS', 'ID')
490
491 with self.env.db_transaction as db:
492 cursor = db.cursor()
493 cursor.execute(
494 "INSERT INTO %s (%s) VALUES ('next-id')"
495 % (db.quote('HOURS'), db.quote('AUTHOR')))
496 last_id = db.get_last_id(cursor, 'HOURS', 'ID')
497
498 self.assertEqual(43, last_id)
499
509
518
527
528
529 if __name__ == '__main__':
530 unittest.main(defaultTest='suite')
531