File: test_fabric.py

package info (click to toggle)
sqlglot 28.5.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 14,672 kB
  • sloc: python: 84,517; sql: 22,534; makefile: 48
file content (134 lines) | stat: -rw-r--r-- 6,263 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
from tests.dialects.test_dialect import Validator


class TestFabric(Validator):
    dialect = "fabric"
    maxDiff = None

    def test_type_mappings(self):
        """Test that types are correctly mapped to their alternatives"""
        self.validate_identity("CAST(x AS BOOLEAN)", "CAST(x AS BIT)")
        self.validate_identity("CAST(x AS DATE)", "CAST(x AS DATE)")
        self.validate_identity("CAST(x AS DATETIME)", "CAST(x AS DATETIME2(6))")
        self.validate_identity("CAST(x AS DECIMAL)", "CAST(x AS DECIMAL)")
        self.validate_identity("CAST(x AS DOUBLE)", "CAST(x AS FLOAT)")
        self.validate_identity("CAST(x AS IMAGE)", "CAST(x AS VARBINARY)")
        self.validate_identity("CAST(x AS INT)", "CAST(x AS INT)")
        self.validate_identity("CAST(x AS JSON)", "CAST(x AS VARCHAR)")
        self.validate_identity("CAST(x AS MONEY)", "CAST(x AS DECIMAL)")
        self.validate_identity("CAST(x AS NCHAR)", "CAST(x AS CHAR)")
        self.validate_identity("CAST(x AS NVARCHAR)", "CAST(x AS VARCHAR)")
        self.validate_identity("CAST(x AS ROWVERSION)", "CAST(x AS ROWVERSION)")
        self.validate_identity("CAST(x AS SMALLDATETIME)", "CAST(x AS DATETIME2(6))")
        self.validate_identity("CAST(x AS SMALLMONEY)", "CAST(x AS DECIMAL)")
        self.validate_identity("CAST(x AS TEXT)", "CAST(x AS VARCHAR(MAX))")
        self.validate_identity("CAST(x AS TIMESTAMP)", "CAST(x AS DATETIME2(6))")
        self.validate_identity("CAST(x AS TIMESTAMPNTZ)", "CAST(x AS DATETIME2(6))")
        self.validate_identity("CAST(x AS TINYINT)", "CAST(x AS SMALLINT)")
        self.validate_identity("CAST(x AS UTINYINT)", "CAST(x AS SMALLINT)")
        self.validate_identity("CAST(x AS UUID)", "CAST(x AS UNIQUEIDENTIFIER)")
        self.validate_identity("CAST(x AS VARIANT)", "CAST(x AS SQL_VARIANT)")
        self.validate_identity("CAST(x AS XML)", "CAST(x AS VARCHAR)")

    def test_precision_capping(self):
        """Test that TIME, DATETIME2 & DATETIMEOFFSET precision is capped at 6 digits"""
        # Default precision should be 6
        self.validate_identity("CAST(x AS TIME)", "CAST(x AS TIME(6))")
        self.validate_identity("CAST(x AS DATETIME2)", "CAST(x AS DATETIME2(6))")

        # Precision <= 6 should be preserved
        self.validate_identity("CAST(x AS TIME(3))", "CAST(x AS TIME(3))")
        self.validate_identity("CAST(x AS DATETIME2(3))", "CAST(x AS DATETIME2(3))")

        self.validate_identity("CAST(x AS TIME(6))", "CAST(x AS TIME(6))")
        self.validate_identity("CAST(x AS DATETIME2(6))", "CAST(x AS DATETIME2(6))")

        # Precision > 6 should be capped at 6
        self.validate_identity("CAST(x AS TIME(7))", "CAST(x AS TIME(6))")
        self.validate_identity("CAST(x AS DATETIME2(7))", "CAST(x AS DATETIME2(6))")

        self.validate_identity("CAST(x AS TIME(9))", "CAST(x AS TIME(6))")
        self.validate_identity("CAST(x AS DATETIME2(9))", "CAST(x AS DATETIME2(6))")

    def test_timestamptz_without_at_time_zone(self):
        # TIMESTAMPTZ should be cast to TIMESTAMP when not in an AT TIME ZONE
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ)",
            "CAST(x AS DATETIME2(6))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(3))",
            "CAST(x AS DATETIME2(3))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(6))",
            "CAST(x AS DATETIME2(6))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(9))",
            "CAST(x AS DATETIME2(6))",
        )

    def test_timestamptz_with_at_time_zone(self):
        # TIMESTAMPTZ should be DATETIMEOFFSET when in an AT TIME ZONE expression and then cast to TIMESTAMP
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ) AT TIME ZONE 'Pacific Standard Time'",
            "CAST(CAST(x AS DATETIMEOFFSET(6)) AT TIME ZONE 'Pacific Standard Time' AS DATETIME2(6))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(3)) AT TIME ZONE 'Pacific Standard Time'",
            "CAST(CAST(x AS DATETIMEOFFSET(3)) AT TIME ZONE 'Pacific Standard Time' AS DATETIME2(3))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(6)) AT TIME ZONE 'Pacific Standard Time'",
            "CAST(CAST(x AS DATETIMEOFFSET(6)) AT TIME ZONE 'Pacific Standard Time' AS DATETIME2(6))",
        )
        self.validate_identity(
            "CAST(x AS TIMESTAMPTZ(9)) AT TIME ZONE 'Pacific Standard Time'",
            "CAST(CAST(x AS DATETIMEOFFSET(6)) AT TIME ZONE 'Pacific Standard Time' AS DATETIME2(6))",
        )

    def test_unix_to_time(self):
        """Test UnixToTime transformation to DATEADD with microseconds"""

        self.validate_identity(
            "UNIX_TO_TIME(column)",
            "DATEADD(MICROSECONDS, CAST(ROUND(column * 1e6, 0) AS BIGINT), CAST('1970-01-01' AS DATETIME2(6)))",
        )

    def test_varchar_precision_inference(self):
        # Test VARCHAR without precision conversion to VARCHAR(1)
        self.validate_identity(
            "CREATE TABLE t (col VARCHAR)",
            "CREATE TABLE t (col VARCHAR(1))",
        )

        # Test VARCHAR with existing precision should remain unchanged
        self.validate_identity("CREATE TABLE t (col VARCHAR(50))")

        # Test CHAR without precision conversion to CHAR(1)
        self.validate_identity(
            "CREATE TABLE t (col CHAR)",
            "CREATE TABLE t (col CHAR(1))",
        )

        # Test CHAR with existing precision should remain unchanged
        self.validate_identity("CREATE TABLE t (col CHAR(10))")

        # Test cross-dialect conversion: non-TSQL VARCHAR -> TSQL VARCHAR(MAX)
        self.validate_all(
            "CREATE TABLE t (col VARCHAR(MAX))",
            read={
                "postgres": "CREATE TABLE t (col VARCHAR)",
                "tsql": "CREATE TABLE t (col VARCHAR(MAX))",
            },
        )

        # Test cross-dialect conversion: non-TSQL CHAR -> TSQL CHAR(MAX)
        self.validate_all(
            "CREATE TABLE t (col CHAR(MAX))",
            read={
                "postgres": "CREATE TABLE t (col CHAR)",
                "tsql": "CREATE TABLE t (col CHAR(MAX))",
            },
        )