1111
1212from __future__ import annotations
1313
14- import datetime as dt
14+ import datetime
1515import os
1616import threading
1717import time
@@ -1712,7 +1712,7 @@ def setUpClass(cls):
17121712 c .query ("drop table if exists test cascade" )
17131713 c .query ("create table test ("
17141714 "i2 smallint, i4 integer, i8 bigint,"
1715- "b boolean, dt date, ti time,"
1715+ "b boolean, dt date, ti time, ts timestamp, td interval, "
17161716 "d numeric, f4 real, f8 double precision, m money,"
17171717 "c char(1), v4 varchar(4), c4 char(4), t text)" )
17181718 # Check whether the test database uses SQL_ASCII - this means
@@ -1746,13 +1746,17 @@ def tearDown(self):
17461746 self .c .close ()
17471747
17481748 data : Sequence [tuple ] = [
1749- (- 1 , - 1 , - 1 , True , '1492-10-12' , '08:30:00' ,
1749+ (- 1 , - 1 , - 1 , True ,
1750+ '1492-10-12' , '08:30:00' , '1492-10-12 08:30:00' , '-3 days' ,
17501751 - 1.2345 , - 1.75 , - 1.875 , '-1.25' , '-' , 'r?' , '!u' , 'xyz' ),
1751- (0 , 0 , 0 , False , '1607-04-14' , '09:00:00' ,
1752+ (0 , 0 , 0 , False ,
1753+ '1607-04-14' , '09:00:00' , '1607-04-14 09:00:00' , '7 days' ,
17521754 0.0 , 0.0 , 0.0 , '0.0' , ' ' , '0123' , '4567' , '890' ),
1753- (1 , 1 , 1 , True , '1801-03-04' , '03:45:00' ,
1755+ (1 , 1 , 1 , True ,
1756+ '1801-03-04' , '03:45:00' , '1801-03-04 03:45:00' , '3 mons' ,
17541757 1.23456 , 1.75 , 1.875 , '1.25' , 'x' , 'bc' , 'cdef' , 'g' ),
1755- (2 , 2 , 2 , False , '1903-12-17' , '11:22:00' ,
1758+ (2 , 2 , 2 , False ,
1759+ '1903-12-17' , '11:22:00' , '1903-12-17 11:22:00' , '1 year' ,
17561760 2.345678 , 2.25 , 2.125 , '2.75' , 'y' , 'q' , 'ijk' , 'mnop\n stux!' )]
17571761
17581762 @classmethod
@@ -1784,29 +1788,37 @@ def get_back(self, encoding='utf-8'):
17841788 if row [5 ] is not None : # time
17851789 self .assertIsInstance (row [5 ], str )
17861790 self .assertTrue (row [5 ].replace (':' , '' ).isdigit ())
1787- if row [6 ] is not None : # numeric
1788- self .assertIsInstance (row [6 ], Decimal )
1789- row [6 ] = float (row [6 ])
1790- if row [7 ] is not None : # real
1791- self .assertIsInstance (row [7 ], float )
1792- if row [8 ] is not None : # double precision
1793- self .assertIsInstance (row [8 ], float )
1791+ if row [6 ] is not None : # timestamp
1792+ self .assertIsInstance (row [6 ], str )
1793+ parts = row [6 ].split (' ' )
1794+ self .assertEqual (len (parts ), 2 )
1795+ self .assertTrue (parts [0 ].replace ('-' , '' ).isdigit ())
1796+ self .assertTrue (parts [1 ].replace (':' , '' ).isdigit ())
1797+ if row [7 ] is not None : # interval
1798+ self .assertIsInstance (row [7 ], str )
1799+ if row [8 ] is not None : # numeric
1800+ self .assertIsInstance (row [8 ], Decimal )
17941801 row [8 ] = float (row [8 ])
1795- if row [9 ] is not None : # money
1796- self .assertIsInstance (row [9 ], Decimal )
1797- row [9 ] = str (float (row [9 ]))
1798- if row [10 ] is not None : # char(1)
1799- self .assertIsInstance (row [10 ], str )
1800- self .assertEqual (self .db_len (row [10 ], encoding ), 1 )
1801- if row [11 ] is not None : # varchar(4)
1802- self .assertIsInstance (row [11 ], str )
1803- self .assertLessEqual (self .db_len (row [11 ], encoding ), 4 )
1804- if row [12 ] is not None : # char(4)
1802+ if row [9 ] is not None : # real
1803+ self .assertIsInstance (row [9 ], float )
1804+ if row [10 ] is not None : # double precision
1805+ self .assertIsInstance (row [10 ], float )
1806+ row [10 ] = float (row [10 ])
1807+ if row [11 ] is not None : # money
1808+ self .assertIsInstance (row [11 ], Decimal )
1809+ row [11 ] = str (float (row [11 ]))
1810+ if row [12 ] is not None : # char(1)
18051811 self .assertIsInstance (row [12 ], str )
1806- self .assertEqual (self .db_len (row [12 ], encoding ), 4 )
1807- row [12 ] = row [12 ].rstrip ()
1808- if row [13 ] is not None : # text
1812+ self .assertEqual (self .db_len (row [12 ], encoding ), 1 )
1813+ if row [13 ] is not None : # varchar(4)
18091814 self .assertIsInstance (row [13 ], str )
1815+ self .assertLessEqual (self .db_len (row [13 ], encoding ), 4 )
1816+ if row [14 ] is not None : # char(4)
1817+ self .assertIsInstance (row [14 ], str )
1818+ self .assertEqual (self .db_len (row [14 ], encoding ), 4 )
1819+ row [14 ] = row [14 ].rstrip ()
1820+ if row [15 ] is not None : # text
1821+ self .assertIsInstance (row [15 ], str )
18101822 row = tuple (row )
18111823 data .append (row )
18121824 return data
@@ -1889,7 +1901,7 @@ def test_inserttable_multiple_calls(self):
18891901 self .assertEqual (r , num_rows )
18901902
18911903 def test_inserttable_null_values (self ):
1892- data = [(None ,) * 14 ] * 100
1904+ data = [(None ,) * 16 ] * 100
18931905 self .c .inserttable ('test' , data )
18941906 self .assertEqual (self .get_back (), data )
18951907
@@ -1899,22 +1911,25 @@ def test_inserttable_no_column(self):
18991911 self .assertEqual (self .get_back (), [])
19001912
19011913 def test_inserttable_datetime_adapt (self ):
1902- data = [(dt .date (1999 ,1 ,2 ), dt .time (11 ,12 ,13 ))]
1903- self .c .inserttable ('test' , data , ['dt' , 'ti' ])
1904- self .assertEqual ([i [4 :6 ] for i in self .get_back ()],
1905- [tuple (str (j ) for j in i ) for i in data ])
1914+ data = [(datetime .date (1999 , 1 , 2 ), datetime .time (11 , 12 , 13 ),
1915+ datetime .datetime (1999 , 1 , 2 , 11 , 12 , 13 ),
1916+ datetime .timedelta (days = 123 ))]
1917+ self .c .inserttable ('test' , data , ['dt' , 'ti' , 'ts' , 'td' ])
1918+ back = [row [4 :8 ] for row in self .get_back ()]
1919+ self .assertEqual (back , [(
1920+ '1999-01-02' , '11:12:13' , '1999-01-02 11:12:13' , '123 days' )])
19061921
19071922 def test_inserttable_only_one_column (self ):
19081923 data : list [tuple ] = [(42 ,)] * 50
19091924 self .c .inserttable ('test' , data , ['i4' ])
1910- data = [tuple ([42 if i == 1 else None for i in range (14 )])] * 50
1925+ data = [tuple ([42 if i == 1 else None for i in range (16 )])] * 50
19111926 self .assertEqual (self .get_back (), data )
19121927
19131928 def test_inserttable_only_two_columns (self ):
19141929 data : list [tuple ] = [(bool (i % 2 ), i * .5 ) for i in range (20 )]
19151930 self .c .inserttable ('test' , data , ('b' , 'f4' ))
19161931 # noinspection PyTypeChecker
1917- data = [(None ,) * 3 + (bool (i % 2 ),) + (None ,) * 3 + (i * .5 ,)
1932+ data = [(None ,) * 3 + (bool (i % 2 ),) + (None ,) * 5 + (i * .5 ,)
19181933 + (None ,) * 6 for i in range (20 )]
19191934 self .assertEqual (self .get_back (), data )
19201935
@@ -1985,9 +2000,9 @@ def test_inserttable_with_out_of_range_data(self):
19852000 ValueError , self .c .inserttable , 'test' , [[33000 ]], ['i2' ])
19862001
19872002 def test_inserttable_max_values (self ):
1988- data = [(2 ** 15 - 1 , 2 ** 31 - 1 , 2 ** 31 - 1 ,
1989- True , '2999-12-31' , '11:59:59' , 1e99 ,
1990- 1.0 + 1.0 / 32 , 1.0 + 1.0 / 32 , None ,
2003+ data = [(2 ** 15 - 1 , 2 ** 31 - 1 , 2 ** 31 - 1 , True ,
2004+ '2999-12-31' , '11:59:59' , '2999-12-31 23:59:59' , '9999 years' ,
2005+ 1e99 , 1.0 + 1.0 / 32 , 1.0 + 1.0 / 32 , None ,
19912006 "1" , "1234" , "1234" , "1234" * 100 )]
19922007 self .c .inserttable ('test' , data )
19932008 self .assertEqual (self .get_back (), data )
@@ -2000,7 +2015,8 @@ def test_inserttable_byte_values(self):
20002015 # non-ascii chars do not fit in char(1) when there is no encoding
20012016 c = '€' if self .has_encoding else '$'
20022017 row_unicode = (
2003- 0 , 0 , 0 , False , '1970-01-01' , '00:00:00' ,
2018+ 0 , 0 , 0 , False ,
2019+ '1970-01-01' , '00:00:00' , '1970-01-01 00:00:00' , '00:00:00' ,
20042020 0.0 , 0.0 , 0.0 , '0.0' ,
20052021 c , 'bäd' , 'bäd' , "käse сыр pont-l'évêque" )
20062022 row_bytes = tuple (
@@ -2019,7 +2035,8 @@ def test_inserttable_unicode_utf8(self):
20192035 # non-ascii chars do not fit in char(1) when there is no encoding
20202036 c = '€' if self .has_encoding else '$'
20212037 row_unicode = (
2022- 0 , 0 , 0 , False , '1970-01-01' , '00:00:00' ,
2038+ 0 , 0 , 0 , False ,
2039+ '1970-01-01' , '00:00:00' , '1970-01-01 00:00:00' , '00:00:00' ,
20232040 0.0 , 0.0 , 0.0 , '0.0' ,
20242041 c , 'bäd' , 'bäd' , "käse сыр pont-l'évêque" )
20252042 data = [row_unicode ] * 2
@@ -2035,7 +2052,8 @@ def test_inserttable_unicode_latin1(self):
20352052 # non-ascii chars do not fit in char(1) when there is no encoding
20362053 c = '€' if self .has_encoding else '$'
20372054 row_unicode : tuple = (
2038- 0 , 0 , 0 , False , '1970-01-01' , '00:00:00' ,
2055+ 0 , 0 , 0 , False ,
2056+ '1970-01-01' , '00:00:00' , '1970-01-01 00:00:00' , '00:00:00' ,
20392057 0.0 , 0.0 , 0.0 , '0.0' ,
20402058 c , 'bäd' , 'bäd' , "for käse and pont-l'évêque pay in €" )
20412059 data = [row_unicode ]
@@ -2058,7 +2076,8 @@ def test_inserttable_unicode_latin9(self):
20582076 # non-ascii chars do not fit in char(1) when there is no encoding
20592077 c = '€' if self .has_encoding else '$'
20602078 row_unicode = (
2061- 0 , 0 , 0 , False , '1970-01-01' , '00:00:00' ,
2079+ 0 , 0 , 0 , False ,
2080+ '1970-01-01' , '00:00:00' , '1970-01-01 00:00:00' , '00:00:00' ,
20622081 0.0 , 0.0 , 0.0 , '0.0' ,
20632082 c , 'bäd' , 'bäd' , "for käse and pont-l'évêque pay in €" )
20642083 data = [row_unicode ] * 2
@@ -2070,7 +2089,8 @@ def test_inserttable_no_encoding(self):
20702089 # non-ascii chars do not fit in char(1) when there is no encoding
20712090 c = '€' if self .has_encoding else '$'
20722091 row_unicode = (
2073- 0 , 0 , 0 , False , '1970-01-01' , '00:00:00' ,
2092+ 0 , 0 , 0 , False ,
2093+ '1970-01-01' , '00:00:00' , '1970-01-01 00:00:00' , '00:00:00' ,
20742094 0.0 , 0.0 , 0.0 , '0.0' ,
20752095 c , 'bäd' , 'bäd' , "for käse and pont-l'évêque pay in €" )
20762096 data = [row_unicode ]
@@ -2080,12 +2100,12 @@ def test_inserttable_no_encoding(self):
20802100 def test_inserttable_from_query (self ):
20812101 data = self .c .query (
20822102 "select 2::int2 as i2, 4::int4 as i4, 8::int8 as i8, true as b,"
2083- "null as dt, null as ti, null as d,"
2103+ "null as dt, null as ti, null as ts, null as td, null as d,"
20842104 "4.5::float as float4, 8.5::float8 as f8,"
20852105 "null as m, 'c' as c, 'v4' as v4, null as c4, 'text' as text" )
20862106 self .c .inserttable ('test' , data )
20872107 self .assertEqual (self .get_back (), [
2088- (2 , 4 , 8 , True , None , None , None , 4.5 , 8.5 ,
2108+ (2 , 4 , 8 , True , None , None , None , None , None , 4.5 , 8.5 ,
20892109 None , 'c' , 'v4' , None , 'text' )])
20902110
20912111 def test_inserttable_special_chars (self ):
0 commit comments