Skip to content
Newer
Older
100644 705 lines (539 sloc) 25.3 KB
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
1 #!/usr/bin/python
2 # -*- coding: latin-1 -*-
3
4 usage = """\
5 usage: %prog [options] connection_string
6
7 Unit tests for SQLite using the ODBC driver from http://www.ch-werner.de/sqliteodbc
8
9 To use, pass a connection string as the parameter. The tests will create and
10 drop tables t1 and t2 as necessary. On Windows, use the 32-bit driver with
11 32-bit Python and the 64-bit driver with 64-bit Python (regardless of your
12 operating system bitness).
13
14 These run using the version from the 'build' directory, not the version
15 installed into the Python directories. You must run python setup.py build
16 before running the tests.
17
18 You can also put the connection string into a setup.cfg file in the root of the project
19 (the same one setup.py would use) like so:
20
21 [sqlitetests]
22 connection-string=Driver=SQLite3 ODBC Driver;Database=sqlite.db
23 """
24
25 import sys, os, re
26 import unittest
27 from decimal import Decimal
28 from datetime import datetime, date, time
29 from os.path import join, getsize, dirname, abspath
30 from testutils import *
31
32 _TESTSTR = '0123456789-abcdefghijklmnopqrstuvwxyz-'
33
34 def _generate_test_string(length):
35 """
36 Returns a string of `length` characters, constructed by repeating _TESTSTR as necessary.
37
38 To enhance performance, there are 3 ways data is read, based on the length of the value, so most data types are
39 tested with 3 lengths. This function helps us generate the test data.
40
41 We use a recognizable data set instead of a single character to make it less likely that "overlap" errors will
42 be hidden and to help us manually identify where a break occurs.
43 """
44 if length <= len(_TESTSTR):
45 return _TESTSTR[:length]
46
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
47 c = (length + len(_TESTSTR)-1) // len(_TESTSTR)
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
48 v = _TESTSTR * c
49 return v[:length]
50
51 class SqliteTestCase(unittest.TestCase):
52
53 SMALL_FENCEPOST_SIZES = [ 0, 1, 255, 256, 510, 511, 512, 1023, 1024, 2047, 2048, 4000 ]
54 LARGE_FENCEPOST_SIZES = [ 4095, 4096, 4097, 10 * 1024, 20 * 1024 ]
55
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
56 STR_FENCEPOSTS = [ _generate_test_string(size) for size in SMALL_FENCEPOST_SIZES ]
57 BYTE_FENCEPOSTS = [ bytes(s, 'ascii') for s in STR_FENCEPOSTS ]
58 IMAGE_FENCEPOSTS = BYTE_FENCEPOSTS + [ bytes(_generate_test_string(size), 'ascii') for size in LARGE_FENCEPOST_SIZES ]
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
59
60 def __init__(self, method_name, connection_string):
61 unittest.TestCase.__init__(self, method_name)
62 self.connection_string = connection_string
63
64 def get_sqlite_version(self):
65 """
66 Returns the major version: 8-->2000, 9-->2005, 10-->2008
67 """
68 self.cursor.execute("exec master..xp_msver 'ProductVersion'")
69 row = self.cursor.fetchone()
70 return int(row.Character_Value.split('.', 1)[0])
71
72 def setUp(self):
73 self.cnxn = pyodbc.connect(self.connection_string)
74 self.cursor = self.cnxn.cursor()
75
76 for i in range(3):
77 try:
78 self.cursor.execute("drop table t%d" % i)
79 self.cnxn.commit()
80 except:
81 pass
82
83 self.cnxn.rollback()
84
85 def tearDown(self):
86 try:
87 self.cursor.close()
88 self.cnxn.close()
89 except:
90 # If we've already closed the cursor or connection, exceptions are thrown.
91 pass
92
93 def test_multiple_bindings(self):
94 "More than one bind and select on a cursor"
95 self.cursor.execute("create table t1(n int)")
96 self.cursor.execute("insert into t1 values (?)", 1)
97 self.cursor.execute("insert into t1 values (?)", 2)
98 self.cursor.execute("insert into t1 values (?)", 3)
99 for i in range(3):
100 self.cursor.execute("select n from t1 where n < ?", 10)
101 self.cursor.execute("select n from t1 where n < 3")
102
103
104 def test_different_bindings(self):
105 self.cursor.execute("create table t1(n int)")
106 self.cursor.execute("create table t2(d datetime)")
107 self.cursor.execute("insert into t1 values (?)", 1)
108 self.cursor.execute("insert into t2 values (?)", datetime.now())
109
110 def test_datasources(self):
111 p = pyodbc.dataSources()
112 self.assert_(isinstance(p, dict))
113
114 def test_getinfo_string(self):
115 value = self.cnxn.getinfo(pyodbc.SQL_CATALOG_NAME_SEPARATOR)
116 self.assert_(isinstance(value, str))
117
118 def test_getinfo_bool(self):
119 value = self.cnxn.getinfo(pyodbc.SQL_ACCESSIBLE_TABLES)
120 self.assert_(isinstance(value, bool))
121
122 def test_getinfo_int(self):
123 value = self.cnxn.getinfo(pyodbc.SQL_DEFAULT_TXN_ISOLATION)
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
124 self.assert_(isinstance(value, int))
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
125
126 def test_getinfo_smallint(self):
127 value = self.cnxn.getinfo(pyodbc.SQL_CONCAT_NULL_BEHAVIOR)
128 self.assert_(isinstance(value, int))
129
130 def _test_strtype(self, sqltype, value, colsize=None):
131 """
132 The implementation for string, Unicode, and binary tests.
133 """
134 assert colsize is None or (value is None or colsize >= len(value))
135
136 if colsize:
137 sql = "create table t1(s %s(%s))" % (sqltype, colsize)
138 else:
139 sql = "create table t1(s %s)" % sqltype
140
141 self.cursor.execute(sql)
142 self.cursor.execute("insert into t1 values(?)", value)
143 v = self.cursor.execute("select * from t1").fetchone()[0]
144 self.assertEqual(type(v), type(value))
145
146 if value is not None:
147 self.assertEqual(len(v), len(value))
148
149 self.assertEqual(v, value)
150
151 # Reported by Andy Hochhaus in the pyodbc group: In 2.1.7 and earlier, a hardcoded length of 255 was used to
152 # determine whether a parameter was bound as a SQL_VARCHAR or SQL_LONGVARCHAR. Apparently SQL Server chokes if
153 # we bind as a SQL_LONGVARCHAR and the target column size is 8000 or less, which is considers just SQL_VARCHAR.
154 # This means binding a 256 character value would cause problems if compared with a VARCHAR column under
155 # 8001. We now use SQLGetTypeInfo to determine the time to switch.
156 #
157 # [42000] [Microsoft][SQL Server Native Client 10.0][SQL Server]The data types varchar and text are incompatible in the equal to operator.
158
159 self.cursor.execute("select * from t1 where s=?", value)
160
161
162 def _test_strliketype(self, sqltype, value, colsize=None):
163 """
164 The implementation for text, image, ntext, and binary.
165
166 These types do not support comparison operators.
167 """
168 assert colsize is None or (value is None or colsize >= len(value))
169
170 if colsize:
171 sql = "create table t1(s %s(%s))" % (sqltype, colsize)
172 else:
173 sql = "create table t1(s %s)" % sqltype
174
175 self.cursor.execute(sql)
176 self.cursor.execute("insert into t1 values(?)", value)
177 v = self.cursor.execute("select * from t1").fetchone()[0]
178 self.assertEqual(type(v), type(value))
179
180 if value is not None:
181 self.assertEqual(len(v), len(value))
182
183 self.assertEqual(v, value)
184
185 #
186 # text
187 #
188
189 def test_text_null(self):
190 self._test_strtype('text', None, 100)
191
192 # Generate a test for each fencepost size: test_text_0, etc.
193 def _maketest(value):
194 def t(self):
195 self._test_strtype('text', value, len(value))
196 return t
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
197 for value in STR_FENCEPOSTS:
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
198 locals()['test_text_%s' % len(value)] = _maketest(value)
199
200 def test_text_upperlatin(self):
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
201 self._test_strtype('varchar', 'á')
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
202
203 #
204 # blob
205 #
206
207 def test_null_blob(self):
208 self._test_strtype('blob', None, 100)
209
210 def test_large_null_blob(self):
211 # Bug 1575064
212 self._test_strtype('blob', None, 4000)
213
214 # Generate a test for each fencepost size: test_unicode_0, etc.
215 def _maketest(value):
216 def t(self):
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
217 self._test_strtype('blob', bytearray(value), len(value))
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
218 return t
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
219 for value in BYTE_FENCEPOSTS:
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
220 locals()['test_blob_%s' % len(value)] = _maketest(value)
221
222 def test_subquery_params(self):
223 """Ensure parameter markers work in a subquery"""
224 self.cursor.execute("create table t1(id integer, s varchar(20))")
225 self.cursor.execute("insert into t1 values (?,?)", 1, 'test')
226 row = self.cursor.execute("""
227 select x.id
228 from (
229 select id
230 from t1
231 where s = ?
232 and id between ? and ?
233 ) x
234 """, 'test', 1, 10).fetchone()
235 self.assertNotEqual(row, None)
236 self.assertEqual(row[0], 1)
237
238 def _exec(self):
239 self.cursor.execute(self.sql)
240
241 def test_close_cnxn(self):
242 """Make sure using a Cursor after closing its connection doesn't crash."""
243
244 self.cursor.execute("create table t1(id integer, s varchar(20))")
245 self.cursor.execute("insert into t1 values (?,?)", 1, 'test')
246 self.cursor.execute("select * from t1")
247
248 self.cnxn.close()
249
250 # Now that the connection is closed, we expect an exception. (If the code attempts to use
251 # the HSTMT, we'll get an access violation instead.)
252 self.sql = "select * from t1"
253 self.assertRaises(pyodbc.ProgrammingError, self._exec)
254
255 def test_negative_row_index(self):
256 self.cursor.execute("create table t1(s varchar(20))")
257 self.cursor.execute("insert into t1 values(?)", "1")
258 row = self.cursor.execute("select * from t1").fetchone()
259 self.assertEquals(row[0], "1")
260 self.assertEquals(row[-1], "1")
261
262 def test_version(self):
263 self.assertEquals(3, len(pyodbc.version.split('.'))) # 1.3.1 etc.
264
265 #
266 # ints and floats
267 #
268
269 def test_int(self):
270 value = 1234
271 self.cursor.execute("create table t1(n int)")
272 self.cursor.execute("insert into t1 values (?)", value)
273 result = self.cursor.execute("select n from t1").fetchone()[0]
274 self.assertEquals(result, value)
275
276 def test_negative_int(self):
277 value = -1
278 self.cursor.execute("create table t1(n int)")
279 self.cursor.execute("insert into t1 values (?)", value)
280 result = self.cursor.execute("select n from t1").fetchone()[0]
281 self.assertEquals(result, value)
282
283 def test_bigint(self):
284 input = 3000000000
285 self.cursor.execute("create table t1(d bigint)")
286 self.cursor.execute("insert into t1 values (?)", input)
287 result = self.cursor.execute("select d from t1").fetchone()[0]
288 self.assertEqual(result, input)
289
290 def test_negative_bigint(self):
291 # Issue 186: BIGINT problem on 32-bit architeture
292 input = -430000000
293 self.cursor.execute("create table t1(d bigint)")
294 self.cursor.execute("insert into t1 values (?)", input)
295 result = self.cursor.execute("select d from t1").fetchone()[0]
296 self.assertEqual(result, input)
297
298 def test_float(self):
299 value = 1234.567
300 self.cursor.execute("create table t1(n float)")
301 self.cursor.execute("insert into t1 values (?)", value)
302 result = self.cursor.execute("select n from t1").fetchone()[0]
303 self.assertEquals(result, value)
304
305 def test_negative_float(self):
306 value = -200
307 self.cursor.execute("create table t1(n float)")
308 self.cursor.execute("insert into t1 values (?)", value)
309 result = self.cursor.execute("select n from t1").fetchone()[0]
310 self.assertEqual(value, result)
311
312 #
313 # rowcount
314 #
315
316 def test_rowcount_delete(self):
317 self.assertEquals(self.cursor.rowcount, -1)
318 self.cursor.execute("create table t1(i int)")
319 count = 4
320 for i in range(count):
321 self.cursor.execute("insert into t1 values (?)", i)
322 self.cursor.execute("delete from t1")
323 self.assertEquals(self.cursor.rowcount, count)
324
325 def test_rowcount_nodata(self):
326 """
327 This represents a different code path than a delete that deleted something.
328
329 The return value is SQL_NO_DATA and code after it was causing an error. We could use SQL_NO_DATA to step over
330 the code that errors out and drop down to the same SQLRowCount code. On the other hand, we could hardcode a
331 zero return value.
332 """
333 self.cursor.execute("create table t1(i int)")
334 # This is a different code path internally.
335 self.cursor.execute("delete from t1")
336 self.assertEquals(self.cursor.rowcount, 0)
337
338 def test_rowcount_select(self):
339 """
340 Ensure Cursor.rowcount is set properly after a select statement.
341 """
342 self.cursor.execute("create table t1(i int)")
343 count = 4
344 for i in range(count):
345 self.cursor.execute("insert into t1 values (?)", i)
346 self.cursor.execute("select * from t1")
347 self.assertEquals(self.cursor.rowcount, count)
348
349 rows = self.cursor.fetchall()
350 self.assertEquals(len(rows), count)
351 self.assertEquals(self.cursor.rowcount, count)
352
353 # Fails. Not terribly important so I'm going to comment out for now and report to the ODBC driver writer.
354 # def test_rowcount_reset(self):
355 # "Ensure rowcount is reset to -1"
356 # self.cursor.execute("create table t1(i int)")
357 # count = 4
358 # for i in range(count):
359 # self.cursor.execute("insert into t1 values (?)", i)
360 # self.assertEquals(self.cursor.rowcount, 1)
361 #
362 # self.cursor.execute("create table t2(i int)")
363 # self.assertEquals(self.cursor.rowcount, -1)
364
365 #
366 # always return Cursor
367 #
368
369 # In the 2.0.x branch, Cursor.execute sometimes returned the cursor and sometimes the rowcount. This proved very
370 # confusing when things went wrong and added very little value even when things went right since users could always
371 # use: cursor.execute("...").rowcount
372
373 def test_retcursor_delete(self):
374 self.cursor.execute("create table t1(i int)")
375 self.cursor.execute("insert into t1 values (1)")
376 v = self.cursor.execute("delete from t1")
377 self.assertEquals(v, self.cursor)
378
379 def test_retcursor_nodata(self):
380 """
381 This represents a different code path than a delete that deleted something.
382
383 The return value is SQL_NO_DATA and code after it was causing an error. We could use SQL_NO_DATA to step over
384 the code that errors out and drop down to the same SQLRowCount code.
385 """
386 self.cursor.execute("create table t1(i int)")
387 # This is a different code path internally.
388 v = self.cursor.execute("delete from t1")
389 self.assertEquals(v, self.cursor)
390
391 def test_retcursor_select(self):
392 self.cursor.execute("create table t1(i int)")
393 self.cursor.execute("insert into t1 values (1)")
394 v = self.cursor.execute("select * from t1")
395 self.assertEquals(v, self.cursor)
396
397 #
398 # misc
399 #
400
401 def test_lower_case(self):
402 "Ensure pyodbc.lowercase forces returned column names to lowercase."
403
404 # Has to be set before creating the cursor, so we must recreate self.cursor.
405
406 pyodbc.lowercase = True
407 self.cursor = self.cnxn.cursor()
408
409 self.cursor.execute("create table t1(Abc int, dEf int)")
410 self.cursor.execute("select * from t1")
411
412 names = [ t[0] for t in self.cursor.description ]
413 names.sort()
414
415 self.assertEquals(names, [ "abc", "def" ])
416
417 # Put it back so other tests don't fail.
418 pyodbc.lowercase = False
419
420 def test_row_description(self):
421 """
422 Ensure Cursor.description is accessible as Row.cursor_description.
423 """
424 self.cursor = self.cnxn.cursor()
425 self.cursor.execute("create table t1(a int, b char(3))")
426 self.cnxn.commit()
427 self.cursor.execute("insert into t1 values(1, 'abc')")
428
429 row = self.cursor.execute("select * from t1").fetchone()
430
431 self.assertEquals(self.cursor.description, row.cursor_description)
432
433
434 def test_executemany(self):
435 self.cursor.execute("create table t1(a int, b varchar(10))")
436
437 params = [ (i, str(i)) for i in range(1, 6) ]
438
439 self.cursor.executemany("insert into t1(a, b) values (?,?)", params)
440
441 count = self.cursor.execute("select count(*) from t1").fetchone()[0]
442 self.assertEqual(count, len(params))
443
444 self.cursor.execute("select a, b from t1 order by a")
445 rows = self.cursor.fetchall()
446 self.assertEqual(count, len(rows))
447
448 for param, row in zip(params, rows):
449 self.assertEqual(param[0], row[0])
450 self.assertEqual(param[1], row[1])
451
452
453 def test_executemany_one(self):
454 "Pass executemany a single sequence"
455 self.cursor.execute("create table t1(a int, b varchar(10))")
456
457 params = [ (1, "test") ]
458
459 self.cursor.executemany("insert into t1(a, b) values (?,?)", params)
460
461 count = self.cursor.execute("select count(*) from t1").fetchone()[0]
462 self.assertEqual(count, len(params))
463
464 self.cursor.execute("select a, b from t1 order by a")
465 rows = self.cursor.fetchall()
466 self.assertEqual(count, len(rows))
467
468 for param, row in zip(params, rows):
469 self.assertEqual(param[0], row[0])
470 self.assertEqual(param[1], row[1])
471
472
473 def test_executemany_failure(self):
474 """
475 Ensure that an exception is raised if one query in an executemany fails.
476 """
477 self.cursor.execute("create table t1(a int, b varchar(10))")
478
479 params = [ (1, 'good'),
480 ('error', 'not an int'),
481 (3, 'good') ]
482
483 self.failUnlessRaises(pyodbc.Error, self.cursor.executemany, "insert into t1(a, b) value (?, ?)", params)
484
485
486 def test_row_slicing(self):
487 self.cursor.execute("create table t1(a int, b int, c int, d int)");
488 self.cursor.execute("insert into t1 values(1,2,3,4)")
489
490 row = self.cursor.execute("select * from t1").fetchone()
491
492 result = row[:]
493 self.failUnless(result is row)
494
495 result = row[:-1]
496 self.assertEqual(result, (1,2,3))
497
498 result = row[0:4]
499 self.failUnless(result is row)
500
501
502 def test_row_repr(self):
503 self.cursor.execute("create table t1(a int, b int, c int, d int)");
504 self.cursor.execute("insert into t1 values(1,2,3,4)")
505
506 row = self.cursor.execute("select * from t1").fetchone()
507
508 result = str(row)
509 self.assertEqual(result, "(1, 2, 3, 4)")
510
511 result = str(row[:-1])
512 self.assertEqual(result, "(1, 2, 3)")
513
514 result = str(row[:1])
515 self.assertEqual(result, "(1,)")
516
517
518 def test_view_select(self):
519 # Reported in forum: Can't select from a view? I think I do this a lot, but another test never hurts.
520
521 # Create a table (t1) with 3 rows and a view (t2) into it.
522 self.cursor.execute("create table t1(c1 int identity(1, 1), c2 varchar(50))")
523 for i in range(3):
524 self.cursor.execute("insert into t1(c2) values (?)", "string%s" % i)
525 self.cursor.execute("create view t2 as select * from t1")
526
527 # Select from the view
528 self.cursor.execute("select * from t2")
529 rows = self.cursor.fetchall()
530 self.assert_(rows is not None)
531 self.assert_(len(rows) == 3)
532
533 def test_autocommit(self):
534 self.assertEqual(self.cnxn.autocommit, False)
535
536 othercnxn = pyodbc.connect(self.connection_string, autocommit=True)
537 self.assertEqual(othercnxn.autocommit, True)
538
539 othercnxn.autocommit = False
540 self.assertEqual(othercnxn.autocommit, False)
541
542 def test_skip(self):
543 # Insert 1, 2, and 3. Fetch 1, skip 2, fetch 3.
544
545 self.cursor.execute("create table t1(id int)");
546 for i in range(1, 5):
547 self.cursor.execute("insert into t1 values(?)", i)
548 self.cursor.execute("select id from t1 order by id")
549 self.assertEqual(self.cursor.fetchone()[0], 1)
550 self.cursor.skip(2)
551 self.assertEqual(self.cursor.fetchone()[0], 4)
552
553 def test_sets_execute(self):
554 # Only lists and tuples are allowed.
555 def f():
556 self.cursor.execute("create table t1 (word varchar (100))")
557 words = set (['a'])
558 self.cursor.execute("insert into t1 (word) VALUES (?)", [words])
559
560 self.assertRaises(pyodbc.ProgrammingError, f)
561
562 def test_sets_executemany(self):
563 # Only lists and tuples are allowed.
564 def f():
565 self.cursor.execute("create table t1 (word varchar (100))")
566 words = set (['a'])
567 self.cursor.executemany("insert into t1 (word) values (?)", [words])
568
569 self.assertRaises(TypeError, f)
570
571 def test_row_execute(self):
572 "Ensure we can use a Row object as a parameter to execute"
573 self.cursor.execute("create table t1(n int, s varchar(10))")
574 self.cursor.execute("insert into t1 values (1, 'a')")
575 row = self.cursor.execute("select n, s from t1").fetchone()
576 self.assertNotEqual(row, None)
577
578 self.cursor.execute("create table t2(n int, s varchar(10))")
579 self.cursor.execute("insert into t2 values (?, ?)", row)
580
581 def test_row_executemany(self):
582 "Ensure we can use a Row object as a parameter to executemany"
583 self.cursor.execute("create table t1(n int, s varchar(10))")
584
585 for i in range(3):
586 self.cursor.execute("insert into t1 values (?, ?)", i, chr(ord('a')+i))
587
588 rows = self.cursor.execute("select n, s from t1").fetchall()
589 self.assertNotEqual(len(rows), 0)
590
591 self.cursor.execute("create table t2(n int, s varchar(10))")
592 self.cursor.executemany("insert into t2 values (?, ?)", rows)
593
594 def test_description(self):
595 "Ensure cursor.description is correct"
596
597 self.cursor.execute("create table t1(n int, s text)")
598 self.cursor.execute("insert into t1 values (1, 'abc')")
599 self.cursor.execute("select * from t1")
600
601 # (I'm not sure the precision of an int is constant across different versions, bits, so I'm hand checking the
602 # items I do know.
603
604 # int
605 t = self.cursor.description[0]
606 self.assertEqual(t[0], 'n')
607 self.assertEqual(t[1], int)
608 self.assertEqual(t[5], 0) # scale
609 self.assertEqual(t[6], True) # nullable
610
611 # text
612 t = self.cursor.description[1]
613 self.assertEqual(t[0], 's')
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
614 self.assertEqual(t[1], str)
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
615 self.assertEqual(t[5], 0) # scale
616 self.assertEqual(t[6], True) # nullable
617
618 def test_row_equal(self):
619 self.cursor.execute("create table t1(n int, s varchar(20))")
620 self.cursor.execute("insert into t1 values (1, 'test')")
621 row1 = self.cursor.execute("select n, s from t1").fetchone()
622 row2 = self.cursor.execute("select n, s from t1").fetchone()
623 b = (row1 == row2)
624 self.assertEqual(b, True)
625
626 def test_row_gtlt(self):
627 self.cursor.execute("create table t1(n int, s varchar(20))")
628 self.cursor.execute("insert into t1 values (1, 'test1')")
629 self.cursor.execute("insert into t1 values (1, 'test2')")
630 rows = self.cursor.execute("select n, s from t1 order by s").fetchall()
631 self.assert_(rows[0] < rows[1])
632 self.assert_(rows[0] <= rows[1])
633 self.assert_(rows[1] > rows[0])
634 self.assert_(rows[1] >= rows[0])
635 self.assert_(rows[0] != rows[1])
636
637 rows = list(rows)
638 rows.sort() # uses <
639
640 def test_context_manager(self):
641 with pyodbc.connect(self.connection_string) as cnxn:
642 cnxn.getinfo(pyodbc.SQL_DEFAULT_TXN_ISOLATION)
643
644 # The connection should be closed now.
645 def test():
646 cnxn.getinfo(pyodbc.SQL_DEFAULT_TXN_ISOLATION)
647 self.assertRaises(pyodbc.ProgrammingError, test)
648
649 def test_untyped_none(self):
650 # From issue 129
651 value = self.cursor.execute("select ?", None).fetchone()[0]
652 self.assertEqual(value, None)
653
654 def test_large_update_nodata(self):
655 self.cursor.execute('create table t1(a blob)')
b2dfac9 @mkleehammer Issue 178: Fixed compilation issues with 4.6.2
authored
656 hundredkb = bytearray('x'*100*1024)
bbb08f0 @mkleehammer Issue 186: Added SQLite tests
authored
657 self.cursor.execute('update t1 set a=? where 1=0', (hundredkb,))
658
659 def test_no_fetch(self):
660 # Issue 89 with FreeTDS: Multiple selects (or catalog functions that issue selects) without fetches seem to
661 # confuse the driver.
662 self.cursor.execute('select 1')
663 self.cursor.execute('select 1')
664 self.cursor.execute('select 1')
665
666 def main():
667 from optparse import OptionParser
668 parser = OptionParser(usage=usage)
669 parser.add_option("-v", "--verbose", action="count", help="Increment test verbosity (can be used multiple times)")
670 parser.add_option("-d", "--debug", action="store_true", default=False, help="Print debugging items")
671 parser.add_option("-t", "--test", help="Run only the named test")
672
673 (options, args) = parser.parse_args()
674
675 if len(args) > 1:
676 parser.error('Only one argument is allowed. Do you need quotes around the connection string?')
677
678 if not args:
679 connection_string = load_setup_connection_string('sqlitetests')
680
681 if not connection_string:
682 parser.print_help()
683 raise SystemExit()
684 else:
685 connection_string = args[0]
686
687 cnxn = pyodbc.connect(connection_string)
688 print_library_info(cnxn)
689 cnxn.close()
690
691 suite = load_tests(SqliteTestCase, options.test, connection_string)
692
693 testRunner = unittest.TextTestRunner(verbosity=options.verbose)
694 result = testRunner.run(suite)
695
696
697 if __name__ == '__main__':
698
699 # Add the build directory to the path so we're testing the latest build, not the installed version.
700
701 add_to_path()
702
703 import pyodbc
704 main()
Something went wrong with that request. Please try again.