1
1
#
2
2
# Copyright (c) 2012-2022 Snowflake Computing Inc. All rights reserved.
3
3
#
4
-
4
+ import decimal
5
+ import json
5
6
import os
6
7
import random
7
8
import re
8
9
import string
9
10
import time
11
+ from datetime import date , datetime
10
12
from unittest .mock import patch
11
13
12
14
import pytest
15
+ import pytz
13
16
from sqlalchemy import (
14
17
REAL ,
15
18
Boolean ,
44
47
45
48
THIS_DIR = os .path .dirname (os .path .realpath (__file__ ))
46
49
50
+ PST_TZ = "America/Los_Angeles"
51
+ JST_TZ = "Asia/Tokyo"
52
+
47
53
48
54
def _create_users_addresses_tables (
49
55
engine_testaccount , metadata , fk = None , pk = None , uq = None
@@ -1609,16 +1615,14 @@ def test_empty_comments(engine_testaccount):
1609
1615
def test_column_type_schema (engine_testaccount ):
1610
1616
with engine_testaccount .connect () as conn :
1611
1617
table_name = random_string (5 )
1618
+ # column type FIXED not supported, triggers SQL compilation error: Unsupported data type 'FIXED'.
1612
1619
conn .exec_driver_sql (
1613
1620
f"""\
1614
1621
CREATE TEMP TABLE { table_name } (
1615
1622
C1 BIGINT, C2 BINARY, C3 BOOLEAN, C4 CHAR, C5 CHARACTER, C6 DATE, C7 DATETIME, C8 DEC,
1616
- C9 DECIMAL, C10 DOUBLE,
1617
- -- C11 FIXED, # SQL compilation error: Unsupported data type 'FIXED'.
1618
- C12 FLOAT, C13 INT, C14 INTEGER, C15 NUMBER, C16 REAL, C17 BYTEINT, C18 SMALLINT,
1619
- C19 STRING, C20 TEXT, C21 TIME, C22 TIMESTAMP, C23 TIMESTAMP_TZ, C24 TIMESTAMP_LTZ,
1620
- C25 TIMESTAMP_NTZ, C26 TINYINT, C27 VARBINARY, C28 VARCHAR, C29 VARIANT,
1621
- C30 OBJECT, C31 ARRAY, C32 GEOGRAPHY
1623
+ C9 DECIMAL, C10 DOUBLE, C11 FLOAT, C12 INT, C13 INTEGER, C14 NUMBER, C15 REAL, C16 BYTEINT,
1624
+ C17 SMALLINT, C18 STRING, C19 TEXT, C20 TIME, C21 TIMESTAMP, C22 TIMESTAMP_TZ, C23 TIMESTAMP_LTZ,
1625
+ C24 TIMESTAMP_NTZ, C25 TINYINT, C26 VARBINARY, C27 VARCHAR, C28 VARIANT, C29 OBJECT, C30 ARRAY, C31 GEOGRAPHY
1622
1626
)
1623
1627
"""
1624
1628
)
@@ -1630,3 +1634,132 @@ def test_column_type_schema(engine_testaccount):
1630
1634
assert (
1631
1635
len (columns ) == len (ischema_names_baseline ) - 1
1632
1636
) # -1 because FIXED is not supported
1637
+
1638
+
1639
+ def test_result_type_and_value (engine_testaccount ):
1640
+ with engine_testaccount .connect () as conn :
1641
+ table_name = random_string (5 )
1642
+ conn .exec_driver_sql (
1643
+ f"""\
1644
+ CREATE TEMP TABLE { table_name } (
1645
+ C1 BIGINT, C2 BINARY, C3 BOOLEAN, C4 CHAR, C5 CHARACTER, C6 DATE, C7 DATETIME, C8 DEC(12,3),
1646
+ C9 DECIMAL(12,3), C10 DOUBLE, C11 FLOAT, C12 INT, C13 INTEGER, C14 NUMBER, C15 REAL, C16 BYTEINT,
1647
+ C17 SMALLINT, C18 STRING, C19 TEXT, C20 TIME, C21 TIMESTAMP, C22 TIMESTAMP_TZ, C23 TIMESTAMP_LTZ,
1648
+ C24 TIMESTAMP_NTZ, C25 TINYINT, C26 VARBINARY, C27 VARCHAR, C28 VARIANT, C29 OBJECT, C30 ARRAY, C31 GEOGRAPHY
1649
+ )
1650
+ """
1651
+ )
1652
+ table_reflected = Table (
1653
+ table_name , MetaData (), autoload = True , autoload_with = conn
1654
+ )
1655
+ current_date = date .today ()
1656
+ current_utctime = datetime .utcnow ()
1657
+ current_localtime = pytz .utc .localize (current_utctime , is_dst = False ).astimezone (
1658
+ pytz .timezone (PST_TZ )
1659
+ )
1660
+ current_localtime_without_tz = datetime .now ()
1661
+ current_localtime_with_other_tz = pytz .utc .localize (
1662
+ current_localtime_without_tz , is_dst = False
1663
+ ).astimezone (pytz .timezone (JST_TZ ))
1664
+ TIME_VALUE = current_utctime .time ()
1665
+ DECIMAL_VALUE = decimal .Decimal ("123456789.123" )
1666
+ MAX_INT_VALUE = 99999999999999999999999999999999999999
1667
+ MIN_INT_VALUE = - 99999999999999999999999999999999999999
1668
+ FLOAT_VALUE = 123456789.123
1669
+ STRING_VALUE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1670
+ BINARY_VALUE = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1671
+ CHAR_VALUE = "A"
1672
+ GEOGRAPHY_VALUE = "POINT(-122.35 37.55)"
1673
+ GEOGRAPHY_RESULT_VALUE = '{"coordinates": [-122.35,37.55],"type": "Point"}'
1674
+
1675
+ ins = table_reflected .insert ().values (
1676
+ c1 = MAX_INT_VALUE , # BIGINT
1677
+ c2 = BINARY_VALUE , # BINARY
1678
+ c3 = True , # BOOLEAN
1679
+ c4 = CHAR_VALUE , # CHAR
1680
+ c5 = CHAR_VALUE , # CHARACTER
1681
+ c6 = current_date , # DATE
1682
+ c7 = current_localtime_without_tz , # DATETIME
1683
+ c8 = DECIMAL_VALUE , # DEC(12,3)
1684
+ c9 = DECIMAL_VALUE , # DECIMAL(12,3)
1685
+ c10 = FLOAT_VALUE , # DOUBLE
1686
+ c11 = FLOAT_VALUE , # FLOAT
1687
+ c12 = MIN_INT_VALUE , # INT
1688
+ c13 = MAX_INT_VALUE , # INTEGER
1689
+ c14 = MIN_INT_VALUE , # NUMBER
1690
+ c15 = FLOAT_VALUE , # REAL
1691
+ c16 = MAX_INT_VALUE , # BYTEINT
1692
+ c17 = MIN_INT_VALUE , # SMALLINT
1693
+ c18 = STRING_VALUE , # STRING
1694
+ c19 = STRING_VALUE , # TEXT
1695
+ c20 = TIME_VALUE , # TIME
1696
+ c21 = current_utctime , # TIMESTAMP
1697
+ c22 = current_localtime_with_other_tz , # TIMESTAMP_TZ
1698
+ c23 = current_localtime , # TIMESTAMP_LTZ
1699
+ c24 = current_utctime , # TIMESTAMP_NTZ
1700
+ c25 = MAX_INT_VALUE , # TINYINT
1701
+ c26 = BINARY_VALUE , # VARBINARY
1702
+ c27 = STRING_VALUE , # VARCHAR
1703
+ c28 = None , # VARIANT, currently snowflake-sqlalchemy/connector does not support binding variant
1704
+ c29 = None , # OBJECT, currently snowflake-sqlalchemy/connector does not support binding variant
1705
+ c30 = None , # ARRAY, currently snowflake-sqlalchemy/connector does not support binding variant
1706
+ c31 = GEOGRAPHY_VALUE , # GEOGRAPHY
1707
+ )
1708
+ conn .execute (ins )
1709
+
1710
+ results = conn .execute (select (table_reflected )).fetchall ()
1711
+ assert len (results ) == 1
1712
+ result = results [0 ]
1713
+ assert (
1714
+ result [0 ] == MAX_INT_VALUE
1715
+ and result [1 ] == BINARY_VALUE
1716
+ and result [2 ] is True
1717
+ and result [3 ] == CHAR_VALUE
1718
+ and result [4 ] == CHAR_VALUE
1719
+ and result [5 ] == current_date
1720
+ and result [6 ] == current_localtime_without_tz
1721
+ and result [7 ] == DECIMAL_VALUE
1722
+ and result [8 ] == DECIMAL_VALUE
1723
+ and result [9 ] == FLOAT_VALUE
1724
+ and result [10 ] == FLOAT_VALUE
1725
+ and result [11 ] == MIN_INT_VALUE
1726
+ and result [12 ] == MAX_INT_VALUE
1727
+ and result [13 ] == MIN_INT_VALUE
1728
+ and result [14 ] == FLOAT_VALUE
1729
+ and result [15 ] == MAX_INT_VALUE
1730
+ and result [16 ] == MIN_INT_VALUE
1731
+ and result [17 ] == STRING_VALUE
1732
+ and result [18 ] == STRING_VALUE
1733
+ and result [19 ] == TIME_VALUE
1734
+ and result [20 ] == current_utctime
1735
+ and result [21 ] == current_localtime_with_other_tz
1736
+ and result [22 ] == current_localtime
1737
+ and result [23 ] == current_utctime
1738
+ and result [24 ] == MAX_INT_VALUE
1739
+ and result [25 ] == BINARY_VALUE
1740
+ and result [26 ] == STRING_VALUE
1741
+ and result [27 ] is None
1742
+ and result [28 ] is None
1743
+ and result [29 ] is None
1744
+ and json .loads (result [30 ]) == json .loads (GEOGRAPHY_RESULT_VALUE )
1745
+ )
1746
+
1747
+ sql = f"""
1748
+ INSERT INTO { table_name } (c28, c29, c30)
1749
+ SELECT PARSE_JSON('{{"vk1":100, "vk2":200, "vk3":300}}'),
1750
+ OBJECT_CONSTRUCT('vk1', 100, 'vk2', 200, 'vk3', 300),
1751
+ PARSE_JSON('[
1752
+ {{"k":1, "v":"str1"}},
1753
+ {{"k":2, "v":"str2"}},
1754
+ {{"k":3, "v":"str3"}}]'
1755
+ )"""
1756
+ conn .exec_driver_sql (sql )
1757
+ results = conn .execute (select (table_reflected )).fetchall ()
1758
+ assert len (results ) == 2
1759
+ data = json .loads (results [- 1 ][27 ])
1760
+ assert json .loads (results [- 1 ][28 ]) == data
1761
+ assert data ["vk1" ] == 100
1762
+ assert data ["vk3" ] == 300
1763
+ assert data is not None
1764
+ data = json .loads (results [- 1 ][29 ])
1765
+ assert data [1 ]["k" ] == 2
0 commit comments