/Lib/sqlite3/test/types.py

http://unladen-swallow.googlecode.com/ · Python · 385 lines · 308 code · 38 blank · 39 comment · 9 complexity · 039744380ef9cbe0a049c27d5393e597 MD5 · raw file

  1. #-*- coding: ISO-8859-1 -*-
  2. # pysqlite2/test/types.py: tests for type conversion and detection
  3. #
  4. # Copyright (C) 2005-2007 Gerhard Häring <gh@ghaering.de>
  5. #
  6. # This file is part of pysqlite.
  7. #
  8. # This software is provided 'as-is', without any express or implied
  9. # warranty. In no event will the authors be held liable for any damages
  10. # arising from the use of this software.
  11. #
  12. # Permission is granted to anyone to use this software for any purpose,
  13. # including commercial applications, and to alter it and redistribute it
  14. # freely, subject to the following restrictions:
  15. #
  16. # 1. The origin of this software must not be misrepresented; you must not
  17. # claim that you wrote the original software. If you use this software
  18. # in a product, an acknowledgment in the product documentation would be
  19. # appreciated but is not required.
  20. # 2. Altered source versions must be plainly marked as such, and must not be
  21. # misrepresented as being the original software.
  22. # 3. This notice may not be removed or altered from any source distribution.
  23. import zlib, datetime
  24. import unittest
  25. import sqlite3 as sqlite
  26. class SqliteTypeTests(unittest.TestCase):
  27. def setUp(self):
  28. self.con = sqlite.connect(":memory:")
  29. self.cur = self.con.cursor()
  30. self.cur.execute("create table test(i integer, s varchar, f number, b blob)")
  31. def tearDown(self):
  32. self.cur.close()
  33. self.con.close()
  34. def CheckString(self):
  35. self.cur.execute("insert into test(s) values (?)", (u"Österreich",))
  36. self.cur.execute("select s from test")
  37. row = self.cur.fetchone()
  38. self.failUnlessEqual(row[0], u"Österreich")
  39. def CheckSmallInt(self):
  40. self.cur.execute("insert into test(i) values (?)", (42,))
  41. self.cur.execute("select i from test")
  42. row = self.cur.fetchone()
  43. self.failUnlessEqual(row[0], 42)
  44. def CheckLargeInt(self):
  45. num = 2**40
  46. self.cur.execute("insert into test(i) values (?)", (num,))
  47. self.cur.execute("select i from test")
  48. row = self.cur.fetchone()
  49. self.failUnlessEqual(row[0], num)
  50. def CheckFloat(self):
  51. val = 3.14
  52. self.cur.execute("insert into test(f) values (?)", (val,))
  53. self.cur.execute("select f from test")
  54. row = self.cur.fetchone()
  55. self.failUnlessEqual(row[0], val)
  56. def CheckBlob(self):
  57. val = buffer("Guglhupf")
  58. self.cur.execute("insert into test(b) values (?)", (val,))
  59. self.cur.execute("select b from test")
  60. row = self.cur.fetchone()
  61. self.failUnlessEqual(row[0], val)
  62. def CheckUnicodeExecute(self):
  63. self.cur.execute(u"select 'Österreich'")
  64. row = self.cur.fetchone()
  65. self.failUnlessEqual(row[0], u"Österreich")
  66. class DeclTypesTests(unittest.TestCase):
  67. class Foo:
  68. def __init__(self, _val):
  69. self.val = _val
  70. def __cmp__(self, other):
  71. if not isinstance(other, DeclTypesTests.Foo):
  72. raise ValueError
  73. if self.val == other.val:
  74. return 0
  75. else:
  76. return 1
  77. def __conform__(self, protocol):
  78. if protocol is sqlite.PrepareProtocol:
  79. return self.val
  80. else:
  81. return None
  82. def __str__(self):
  83. return "<%s>" % self.val
  84. def setUp(self):
  85. self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
  86. self.cur = self.con.cursor()
  87. self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob, n1 number, n2 number(5))")
  88. # override float, make them always return the same number
  89. sqlite.converters["FLOAT"] = lambda x: 47.2
  90. # and implement two custom ones
  91. sqlite.converters["BOOL"] = lambda x: bool(int(x))
  92. sqlite.converters["FOO"] = DeclTypesTests.Foo
  93. sqlite.converters["WRONG"] = lambda x: "WRONG"
  94. sqlite.converters["NUMBER"] = float
  95. def tearDown(self):
  96. del sqlite.converters["FLOAT"]
  97. del sqlite.converters["BOOL"]
  98. del sqlite.converters["FOO"]
  99. del sqlite.converters["NUMBER"]
  100. self.cur.close()
  101. self.con.close()
  102. def CheckString(self):
  103. # default
  104. self.cur.execute("insert into test(s) values (?)", ("foo",))
  105. self.cur.execute('select s as "s [WRONG]" from test')
  106. row = self.cur.fetchone()
  107. self.failUnlessEqual(row[0], "foo")
  108. def CheckSmallInt(self):
  109. # default
  110. self.cur.execute("insert into test(i) values (?)", (42,))
  111. self.cur.execute("select i from test")
  112. row = self.cur.fetchone()
  113. self.failUnlessEqual(row[0], 42)
  114. def CheckLargeInt(self):
  115. # default
  116. num = 2**40
  117. self.cur.execute("insert into test(i) values (?)", (num,))
  118. self.cur.execute("select i from test")
  119. row = self.cur.fetchone()
  120. self.failUnlessEqual(row[0], num)
  121. def CheckFloat(self):
  122. # custom
  123. val = 3.14
  124. self.cur.execute("insert into test(f) values (?)", (val,))
  125. self.cur.execute("select f from test")
  126. row = self.cur.fetchone()
  127. self.failUnlessEqual(row[0], 47.2)
  128. def CheckBool(self):
  129. # custom
  130. self.cur.execute("insert into test(b) values (?)", (False,))
  131. self.cur.execute("select b from test")
  132. row = self.cur.fetchone()
  133. self.failUnlessEqual(row[0], False)
  134. self.cur.execute("delete from test")
  135. self.cur.execute("insert into test(b) values (?)", (True,))
  136. self.cur.execute("select b from test")
  137. row = self.cur.fetchone()
  138. self.failUnlessEqual(row[0], True)
  139. def CheckUnicode(self):
  140. # default
  141. val = u"\xd6sterreich"
  142. self.cur.execute("insert into test(u) values (?)", (val,))
  143. self.cur.execute("select u from test")
  144. row = self.cur.fetchone()
  145. self.failUnlessEqual(row[0], val)
  146. def CheckFoo(self):
  147. val = DeclTypesTests.Foo("bla")
  148. self.cur.execute("insert into test(foo) values (?)", (val,))
  149. self.cur.execute("select foo from test")
  150. row = self.cur.fetchone()
  151. self.failUnlessEqual(row[0], val)
  152. def CheckUnsupportedSeq(self):
  153. class Bar: pass
  154. val = Bar()
  155. try:
  156. self.cur.execute("insert into test(f) values (?)", (val,))
  157. self.fail("should have raised an InterfaceError")
  158. except sqlite.InterfaceError:
  159. pass
  160. except:
  161. self.fail("should have raised an InterfaceError")
  162. def CheckUnsupportedDict(self):
  163. class Bar: pass
  164. val = Bar()
  165. try:
  166. self.cur.execute("insert into test(f) values (:val)", {"val": val})
  167. self.fail("should have raised an InterfaceError")
  168. except sqlite.InterfaceError:
  169. pass
  170. except:
  171. self.fail("should have raised an InterfaceError")
  172. def CheckBlob(self):
  173. # default
  174. val = buffer("Guglhupf")
  175. self.cur.execute("insert into test(bin) values (?)", (val,))
  176. self.cur.execute("select bin from test")
  177. row = self.cur.fetchone()
  178. self.failUnlessEqual(row[0], val)
  179. def CheckNumber1(self):
  180. self.cur.execute("insert into test(n1) values (5)")
  181. value = self.cur.execute("select n1 from test").fetchone()[0]
  182. # if the converter is not used, it's an int instead of a float
  183. self.failUnlessEqual(type(value), float)
  184. def CheckNumber2(self):
  185. """Checks wether converter names are cut off at '(' characters"""
  186. self.cur.execute("insert into test(n2) values (5)")
  187. value = self.cur.execute("select n2 from test").fetchone()[0]
  188. # if the converter is not used, it's an int instead of a float
  189. self.failUnlessEqual(type(value), float)
  190. class ColNamesTests(unittest.TestCase):
  191. def setUp(self):
  192. self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
  193. self.cur = self.con.cursor()
  194. self.cur.execute("create table test(x foo)")
  195. sqlite.converters["FOO"] = lambda x: "[%s]" % x
  196. sqlite.converters["BAR"] = lambda x: "<%s>" % x
  197. sqlite.converters["EXC"] = lambda x: 5/0
  198. sqlite.converters["B1B1"] = lambda x: "MARKER"
  199. def tearDown(self):
  200. del sqlite.converters["FOO"]
  201. del sqlite.converters["BAR"]
  202. del sqlite.converters["EXC"]
  203. del sqlite.converters["B1B1"]
  204. self.cur.close()
  205. self.con.close()
  206. def CheckDeclTypeNotUsed(self):
  207. """
  208. Assures that the declared type is not used when PARSE_DECLTYPES
  209. is not set.
  210. """
  211. self.cur.execute("insert into test(x) values (?)", ("xxx",))
  212. self.cur.execute("select x from test")
  213. val = self.cur.fetchone()[0]
  214. self.failUnlessEqual(val, "xxx")
  215. def CheckNone(self):
  216. self.cur.execute("insert into test(x) values (?)", (None,))
  217. self.cur.execute("select x from test")
  218. val = self.cur.fetchone()[0]
  219. self.failUnlessEqual(val, None)
  220. def CheckColName(self):
  221. self.cur.execute("insert into test(x) values (?)", ("xxx",))
  222. self.cur.execute('select x as "x [bar]" from test')
  223. val = self.cur.fetchone()[0]
  224. self.failUnlessEqual(val, "<xxx>")
  225. # Check if the stripping of colnames works. Everything after the first
  226. # whitespace should be stripped.
  227. self.failUnlessEqual(self.cur.description[0][0], "x")
  228. def CheckCaseInConverterName(self):
  229. self.cur.execute("""select 'other' as "x [b1b1]\"""")
  230. val = self.cur.fetchone()[0]
  231. self.failUnlessEqual(val, "MARKER")
  232. def CheckCursorDescriptionNoRow(self):
  233. """
  234. cursor.description should at least provide the column name(s), even if
  235. no row returned.
  236. """
  237. self.cur.execute("select * from test where 0 = 1")
  238. self.assert_(self.cur.description[0][0] == "x")
  239. class ObjectAdaptationTests(unittest.TestCase):
  240. def cast(obj):
  241. return float(obj)
  242. cast = staticmethod(cast)
  243. def setUp(self):
  244. self.con = sqlite.connect(":memory:")
  245. try:
  246. del sqlite.adapters[int]
  247. except:
  248. pass
  249. sqlite.register_adapter(int, ObjectAdaptationTests.cast)
  250. self.cur = self.con.cursor()
  251. def tearDown(self):
  252. del sqlite.adapters[(int, sqlite.PrepareProtocol)]
  253. self.cur.close()
  254. self.con.close()
  255. def CheckCasterIsUsed(self):
  256. self.cur.execute("select ?", (4,))
  257. val = self.cur.fetchone()[0]
  258. self.failUnlessEqual(type(val), float)
  259. class BinaryConverterTests(unittest.TestCase):
  260. def convert(s):
  261. return zlib.decompress(s)
  262. convert = staticmethod(convert)
  263. def setUp(self):
  264. self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
  265. sqlite.register_converter("bin", BinaryConverterTests.convert)
  266. def tearDown(self):
  267. self.con.close()
  268. def CheckBinaryInputForConverter(self):
  269. testdata = "abcdefg" * 10
  270. result = self.con.execute('select ? as "x [bin]"', (buffer(zlib.compress(testdata)),)).fetchone()[0]
  271. self.failUnlessEqual(testdata, result)
  272. class DateTimeTests(unittest.TestCase):
  273. def setUp(self):
  274. self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
  275. self.cur = self.con.cursor()
  276. self.cur.execute("create table test(d date, ts timestamp)")
  277. def tearDown(self):
  278. self.cur.close()
  279. self.con.close()
  280. def CheckSqliteDate(self):
  281. d = sqlite.Date(2004, 2, 14)
  282. self.cur.execute("insert into test(d) values (?)", (d,))
  283. self.cur.execute("select d from test")
  284. d2 = self.cur.fetchone()[0]
  285. self.failUnlessEqual(d, d2)
  286. def CheckSqliteTimestamp(self):
  287. ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0)
  288. self.cur.execute("insert into test(ts) values (?)", (ts,))
  289. self.cur.execute("select ts from test")
  290. ts2 = self.cur.fetchone()[0]
  291. self.failUnlessEqual(ts, ts2)
  292. def CheckSqlTimestamp(self):
  293. # The date functions are only available in SQLite version 3.1 or later
  294. if sqlite.sqlite_version_info < (3, 1):
  295. return
  296. # SQLite's current_timestamp uses UTC time, while datetime.datetime.now() uses local time.
  297. now = datetime.datetime.now()
  298. self.cur.execute("insert into test(ts) values (current_timestamp)")
  299. self.cur.execute("select ts from test")
  300. ts = self.cur.fetchone()[0]
  301. self.failUnlessEqual(type(ts), datetime.datetime)
  302. self.failUnlessEqual(ts.year, now.year)
  303. def CheckDateTimeSubSeconds(self):
  304. ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 500000)
  305. self.cur.execute("insert into test(ts) values (?)", (ts,))
  306. self.cur.execute("select ts from test")
  307. ts2 = self.cur.fetchone()[0]
  308. self.failUnlessEqual(ts, ts2)
  309. def CheckDateTimeSubSecondsFloatingPoint(self):
  310. ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241)
  311. self.cur.execute("insert into test(ts) values (?)", (ts,))
  312. self.cur.execute("select ts from test")
  313. ts2 = self.cur.fetchone()[0]
  314. self.failUnlessEqual(ts, ts2)
  315. def suite():
  316. sqlite_type_suite = unittest.makeSuite(SqliteTypeTests, "Check")
  317. decltypes_type_suite = unittest.makeSuite(DeclTypesTests, "Check")
  318. colnames_type_suite = unittest.makeSuite(ColNamesTests, "Check")
  319. adaptation_suite = unittest.makeSuite(ObjectAdaptationTests, "Check")
  320. bin_suite = unittest.makeSuite(BinaryConverterTests, "Check")
  321. date_suite = unittest.makeSuite(DateTimeTests, "Check")
  322. return unittest.TestSuite((sqlite_type_suite, decltypes_type_suite, colnames_type_suite, adaptation_suite, bin_suite, date_suite))
  323. def test():
  324. runner = unittest.TextTestRunner()
  325. runner.run(suite())
  326. if __name__ == "__main__":
  327. test()