fakesnow 0.9.19__tar.gz → 0.9.20__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fakesnow-0.9.19 → fakesnow-0.9.20}/PKG-INFO +1 -1
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/__init__.py +2 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/fakes.py +0 -3
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/transforms.py +5 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/variables.py +1 -2
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/PKG-INFO +1 -1
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/SOURCES.txt +1 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/pyproject.toml +1 -1
- fakesnow-0.9.20/tests/test_connect.py +199 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_fakes.py +6 -172
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_info_schema.py +18 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/LICENSE +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/README.md +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/__main__.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/checks.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/cli.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/expr.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/fixtures.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/global_database.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/info_schema.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/macros.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow/py.typed +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/dependency_links.txt +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/entry_points.txt +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/requires.txt +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/fakesnow.egg-info/top_level.txt +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/setup.cfg +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_checks.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_cli.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_expr.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_patch.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_sqlalchemy.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_transforms.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_users.py +0 -0
- {fakesnow-0.9.19 → fakesnow-0.9.20}/tests/test_write_pandas.py +0 -0
@@ -13,6 +13,7 @@ import snowflake.connector
|
|
13
13
|
import snowflake.connector.pandas_tools
|
14
14
|
|
15
15
|
import fakesnow.fakes as fakes
|
16
|
+
from fakesnow.global_database import create_global_database
|
16
17
|
|
17
18
|
|
18
19
|
@contextmanager
|
@@ -52,6 +53,7 @@ def patch(
|
|
52
53
|
assert not isinstance(snowflake.connector.connect, mock.MagicMock), "Snowflake connector is already patched"
|
53
54
|
|
54
55
|
duck_conn = duckdb.connect(database=":memory:")
|
56
|
+
create_global_database(duck_conn)
|
55
57
|
|
56
58
|
fake_fns = {
|
57
59
|
# every time we connect, create a new cursor (ie: connection) so we can isolate each connection's
|
@@ -32,7 +32,6 @@ import fakesnow.expr as expr
|
|
32
32
|
import fakesnow.info_schema as info_schema
|
33
33
|
import fakesnow.macros as macros
|
34
34
|
import fakesnow.transforms as transforms
|
35
|
-
from fakesnow.global_database import create_global_database
|
36
35
|
from fakesnow.variables import Variables
|
37
36
|
|
38
37
|
SCHEMA_UNSET = "schema_unset"
|
@@ -533,8 +532,6 @@ class FakeSnowflakeConnection:
|
|
533
532
|
self._paramstyle = snowflake.connector.paramstyle
|
534
533
|
self.variables = Variables()
|
535
534
|
|
536
|
-
create_global_database(duck_conn)
|
537
|
-
|
538
535
|
# create database if needed
|
539
536
|
if (
|
540
537
|
create_database
|
@@ -1402,6 +1402,11 @@ def show_keys(
|
|
1402
1402
|
|
1403
1403
|
if schema:
|
1404
1404
|
statement += f"AND schema_name = '{schema}' "
|
1405
|
+
elif scope_kind == "TABLE":
|
1406
|
+
if not table:
|
1407
|
+
raise ValueError(f"SHOW PRIMARY KEYS with {scope_kind} scope requires a table")
|
1408
|
+
|
1409
|
+
statement += f"AND table_name = '{table.name}' "
|
1405
1410
|
else:
|
1406
1411
|
raise NotImplementedError(f"SHOW PRIMARY KEYS with {scope_kind} not yet supported")
|
1407
1412
|
return sqlglot.parse_one(statement)
|
@@ -49,8 +49,7 @@ class Variables:
|
|
49
49
|
for name, value in self._variables.items():
|
50
50
|
sql = re.sub(rf"\${name}", value, sql, flags=re.IGNORECASE)
|
51
51
|
|
52
|
-
remaining_variables
|
53
|
-
if remaining_variables:
|
52
|
+
if remaining_variables := re.search(r"(?<!\$)\$\w+", sql):
|
54
53
|
raise snowflake.connector.errors.ProgrammingError(
|
55
54
|
msg=f"Session variable '{remaining_variables.group().upper()}' does not exist"
|
56
55
|
)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
[project]
|
2
2
|
name = "fakesnow"
|
3
3
|
description = "Fake Snowflake Connector for Python. Run, mock and test Snowflake DB locally."
|
4
|
-
version = "0.9.
|
4
|
+
version = "0.9.20"
|
5
5
|
readme = "README.md"
|
6
6
|
license = { file = "LICENSE" }
|
7
7
|
classifiers = ["License :: OSI Approved :: MIT License"]
|
@@ -0,0 +1,199 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import concurrent.futures
|
4
|
+
|
5
|
+
# ruff: noqa: E501
|
6
|
+
# pyright: reportOptionalMemberAccess=false
|
7
|
+
import tempfile
|
8
|
+
|
9
|
+
import pytest
|
10
|
+
import snowflake.connector
|
11
|
+
import snowflake.connector.cursor
|
12
|
+
import snowflake.connector.pandas_tools
|
13
|
+
|
14
|
+
import fakesnow
|
15
|
+
|
16
|
+
|
17
|
+
def test_connect_auto_create(_fakesnow: None):
|
18
|
+
with snowflake.connector.connect(database="db1", schema="schema1"):
|
19
|
+
# creates db1 and schema1
|
20
|
+
pass
|
21
|
+
|
22
|
+
with snowflake.connector.connect(database="db1", schema="schema1"):
|
23
|
+
# connects again and reuses db1 and schema1
|
24
|
+
pass
|
25
|
+
|
26
|
+
|
27
|
+
def test_connect_different_sessions_use_database(_fakesnow_no_auto_create: None):
|
28
|
+
# connect without default database and schema
|
29
|
+
with snowflake.connector.connect() as conn1, conn1.cursor() as cur:
|
30
|
+
# use the table's fully qualified name
|
31
|
+
cur.execute("create database marts")
|
32
|
+
cur.execute("create schema marts.jaffles")
|
33
|
+
cur.execute("create table marts.jaffles.customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
34
|
+
cur.execute("insert into marts.jaffles.customers values (1, 'Jenny', 'P')")
|
35
|
+
|
36
|
+
# use database and schema
|
37
|
+
cur.execute("use database marts")
|
38
|
+
cur.execute("use schema jaffles")
|
39
|
+
cur.execute("insert into customers values (2, 'Jasper', 'M')")
|
40
|
+
|
41
|
+
# in a separate connection, connect using the database and schema from above
|
42
|
+
with snowflake.connector.connect(database="marts", schema="jaffles") as conn2, conn2.cursor() as cur:
|
43
|
+
cur.execute("select id, first_name, last_name from customers")
|
44
|
+
assert cur.fetchall() == [(1, "Jenny", "P"), (2, "Jasper", "M")]
|
45
|
+
|
46
|
+
|
47
|
+
def test_connect_concurrently(_fakesnow: None) -> None:
|
48
|
+
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
|
49
|
+
future_a = executor.submit(snowflake.connector.connect)
|
50
|
+
future_b = executor.submit(snowflake.connector.connect)
|
51
|
+
|
52
|
+
futures = [future_a, future_b]
|
53
|
+
|
54
|
+
for future in concurrent.futures.as_completed(futures):
|
55
|
+
# exceptions if any will be raised here. we want to avoid
|
56
|
+
# duckdb.duckdb.TransactionException: TransactionContext Error: Catalog write-write conflict
|
57
|
+
_ = future.result()
|
58
|
+
|
59
|
+
|
60
|
+
def test_connect_db_path_can_create_database() -> None:
|
61
|
+
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path, fakesnow.patch(db_path=db_path):
|
62
|
+
cursor = snowflake.connector.connect().cursor()
|
63
|
+
cursor.execute("CREATE DATABASE db2")
|
64
|
+
|
65
|
+
|
66
|
+
def test_connect_db_path_reuse():
|
67
|
+
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path:
|
68
|
+
with (
|
69
|
+
fakesnow.patch(db_path=db_path),
|
70
|
+
snowflake.connector.connect(database="db1", schema="schema1") as conn,
|
71
|
+
conn.cursor() as cur,
|
72
|
+
):
|
73
|
+
# creates db1.schema1.example
|
74
|
+
cur.execute("create table example (x int)")
|
75
|
+
cur.execute("insert into example values (420)")
|
76
|
+
|
77
|
+
# reconnect
|
78
|
+
with (
|
79
|
+
fakesnow.patch(db_path=db_path),
|
80
|
+
snowflake.connector.connect(database="db1", schema="schema1") as conn,
|
81
|
+
conn.cursor() as cur,
|
82
|
+
):
|
83
|
+
assert cur.execute("select * from example").fetchall() == [(420,)]
|
84
|
+
|
85
|
+
|
86
|
+
def test_connect_without_database(_fakesnow_no_auto_create: None):
|
87
|
+
with snowflake.connector.connect() as conn, conn.cursor() as cur:
|
88
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
89
|
+
cur.execute("select * from customers")
|
90
|
+
|
91
|
+
# actual snowflake error message is:
|
92
|
+
#
|
93
|
+
# 002003 (42S02): SQL compilation error:
|
94
|
+
# Object 'CUSTOMERS' does not exist or not authorized.
|
95
|
+
# assert (
|
96
|
+
# "002003 (42S02): Catalog Error: Table with name customers does not exist!"
|
97
|
+
# in str(excinfo.value)
|
98
|
+
# )
|
99
|
+
|
100
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
101
|
+
cur.execute("select * from jaffles.customers")
|
102
|
+
|
103
|
+
assert (
|
104
|
+
"090105 (22000): Cannot perform SELECT. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
105
|
+
in str(excinfo.value)
|
106
|
+
)
|
107
|
+
|
108
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
109
|
+
cur.execute("create schema jaffles")
|
110
|
+
|
111
|
+
assert (
|
112
|
+
"090105 (22000): Cannot perform CREATE SCHEMA. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
113
|
+
in str(excinfo.value)
|
114
|
+
)
|
115
|
+
|
116
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
117
|
+
cur.execute("use schema jaffles")
|
118
|
+
|
119
|
+
# assert (
|
120
|
+
# "002043 (02000): SQL compilation error:\nObject does not exist, or operation cannot be performed."
|
121
|
+
# in str(excinfo.value)
|
122
|
+
# )
|
123
|
+
|
124
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
125
|
+
cur.execute("create table customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
126
|
+
|
127
|
+
assert (
|
128
|
+
"090105 (22000): Cannot perform CREATE TABLE. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
129
|
+
in str(excinfo.value)
|
130
|
+
)
|
131
|
+
|
132
|
+
# test description works without database
|
133
|
+
assert cur.execute("SELECT 1").fetchall() == [(1,)]
|
134
|
+
assert cur.description
|
135
|
+
|
136
|
+
|
137
|
+
def test_connect_without_schema(_fakesnow: None):
|
138
|
+
# database will be created but not schema
|
139
|
+
with snowflake.connector.connect(database="marts") as conn, conn.cursor() as cur:
|
140
|
+
assert not conn.schema
|
141
|
+
|
142
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
143
|
+
cur.execute("select * from customers")
|
144
|
+
|
145
|
+
# actual snowflake error message is:
|
146
|
+
#
|
147
|
+
# 002003 (42S02): SQL compilation error:
|
148
|
+
# Object 'CUSTOMERS' does not exist or not authorized.
|
149
|
+
# assert (
|
150
|
+
# "002003 (42S02): Catalog Error: Table with name customers does not exist!"
|
151
|
+
# in str(excinfo.value)
|
152
|
+
# )
|
153
|
+
|
154
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
155
|
+
cur.execute("create table customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
156
|
+
|
157
|
+
assert (
|
158
|
+
"090106 (22000): Cannot perform CREATE TABLE. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name."
|
159
|
+
in str(excinfo.value)
|
160
|
+
)
|
161
|
+
|
162
|
+
# test description works without schema
|
163
|
+
assert cur.execute("SELECT 1").fetchall() == [(1,)]
|
164
|
+
assert cur.description
|
165
|
+
|
166
|
+
conn.execute_string("CREATE SCHEMA schema1; USE SCHEMA schema1;")
|
167
|
+
assert conn.schema == "SCHEMA1"
|
168
|
+
|
169
|
+
|
170
|
+
def test_connect_with_non_existent_db_or_schema(_fakesnow_no_auto_create: None):
|
171
|
+
# can connect with db that doesn't exist
|
172
|
+
with snowflake.connector.connect(database="marts") as conn, conn.cursor() as cur:
|
173
|
+
# but no valid database set
|
174
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
175
|
+
cur.execute("create table foobar (i int)")
|
176
|
+
|
177
|
+
assert (
|
178
|
+
"090105 (22000): Cannot perform CREATE TABLE. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
179
|
+
in str(excinfo.value)
|
180
|
+
)
|
181
|
+
|
182
|
+
# database still present on connection
|
183
|
+
assert conn.database == "MARTS"
|
184
|
+
|
185
|
+
cur.execute("CREATE database marts")
|
186
|
+
|
187
|
+
# can connect with schema that doesn't exist
|
188
|
+
with snowflake.connector.connect(database="marts", schema="jaffles") as conn, conn.cursor() as cur:
|
189
|
+
# but no valid schema set
|
190
|
+
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
191
|
+
cur.execute("create table foobar (i int)")
|
192
|
+
|
193
|
+
assert (
|
194
|
+
"090106 (22000): Cannot perform CREATE TABLE. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name."
|
195
|
+
in str(excinfo.value)
|
196
|
+
)
|
197
|
+
|
198
|
+
# schema still present on connection
|
199
|
+
assert conn.schema == "JAFFLES"
|
@@ -172,178 +172,6 @@ def test_close_cur(conn: snowflake.connector.SnowflakeConnection, cur: snowflake
|
|
172
172
|
assert cur.close() is True
|
173
173
|
|
174
174
|
|
175
|
-
def test_connect_auto_create(_fakesnow: None):
|
176
|
-
with snowflake.connector.connect(database="db1", schema="schema1"):
|
177
|
-
# creates db1 and schema1
|
178
|
-
pass
|
179
|
-
|
180
|
-
with snowflake.connector.connect(database="db1", schema="schema1"):
|
181
|
-
# connects again and reuses db1 and schema1
|
182
|
-
pass
|
183
|
-
|
184
|
-
|
185
|
-
def test_connect_different_sessions_use_database(_fakesnow_no_auto_create: None):
|
186
|
-
# connect without default database and schema
|
187
|
-
with snowflake.connector.connect() as conn1, conn1.cursor() as cur:
|
188
|
-
# use the table's fully qualified name
|
189
|
-
cur.execute("create database marts")
|
190
|
-
cur.execute("create schema marts.jaffles")
|
191
|
-
cur.execute("create table marts.jaffles.customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
192
|
-
cur.execute("insert into marts.jaffles.customers values (1, 'Jenny', 'P')")
|
193
|
-
|
194
|
-
# use database and schema
|
195
|
-
cur.execute("use database marts")
|
196
|
-
cur.execute("use schema jaffles")
|
197
|
-
cur.execute("insert into customers values (2, 'Jasper', 'M')")
|
198
|
-
|
199
|
-
# in a separate connection, connect using the database and schema from above
|
200
|
-
with snowflake.connector.connect(database="marts", schema="jaffles") as conn2, conn2.cursor() as cur:
|
201
|
-
cur.execute("select id, first_name, last_name from customers")
|
202
|
-
assert cur.fetchall() == [(1, "Jenny", "P"), (2, "Jasper", "M")]
|
203
|
-
|
204
|
-
|
205
|
-
def test_connect_reuse_db():
|
206
|
-
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path:
|
207
|
-
with (
|
208
|
-
fakesnow.patch(db_path=db_path),
|
209
|
-
snowflake.connector.connect(database="db1", schema="schema1") as conn,
|
210
|
-
conn.cursor() as cur,
|
211
|
-
):
|
212
|
-
# creates db1.schema1.example
|
213
|
-
cur.execute("create table example (x int)")
|
214
|
-
cur.execute("insert into example values (420)")
|
215
|
-
|
216
|
-
# reconnect
|
217
|
-
with (
|
218
|
-
fakesnow.patch(db_path=db_path),
|
219
|
-
snowflake.connector.connect(database="db1", schema="schema1") as conn,
|
220
|
-
conn.cursor() as cur,
|
221
|
-
):
|
222
|
-
assert cur.execute("select * from example").fetchall() == [(420,)]
|
223
|
-
|
224
|
-
|
225
|
-
def test_connect_db_path_can_create_database() -> None:
|
226
|
-
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path, fakesnow.patch(db_path=db_path):
|
227
|
-
cursor = snowflake.connector.connect().cursor()
|
228
|
-
cursor.execute("CREATE DATABASE db2")
|
229
|
-
|
230
|
-
|
231
|
-
def test_connect_without_database(_fakesnow_no_auto_create: None):
|
232
|
-
with snowflake.connector.connect() as conn, conn.cursor() as cur:
|
233
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
234
|
-
cur.execute("select * from customers")
|
235
|
-
|
236
|
-
# actual snowflake error message is:
|
237
|
-
#
|
238
|
-
# 002003 (42S02): SQL compilation error:
|
239
|
-
# Object 'CUSTOMERS' does not exist or not authorized.
|
240
|
-
# assert (
|
241
|
-
# "002003 (42S02): Catalog Error: Table with name customers does not exist!"
|
242
|
-
# in str(excinfo.value)
|
243
|
-
# )
|
244
|
-
|
245
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
246
|
-
cur.execute("select * from jaffles.customers")
|
247
|
-
|
248
|
-
assert (
|
249
|
-
"090105 (22000): Cannot perform SELECT. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
250
|
-
in str(excinfo.value)
|
251
|
-
)
|
252
|
-
|
253
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
254
|
-
cur.execute("create schema jaffles")
|
255
|
-
|
256
|
-
assert (
|
257
|
-
"090105 (22000): Cannot perform CREATE SCHEMA. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
258
|
-
in str(excinfo.value)
|
259
|
-
)
|
260
|
-
|
261
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
262
|
-
cur.execute("use schema jaffles")
|
263
|
-
|
264
|
-
# assert (
|
265
|
-
# "002043 (02000): SQL compilation error:\nObject does not exist, or operation cannot be performed."
|
266
|
-
# in str(excinfo.value)
|
267
|
-
# )
|
268
|
-
|
269
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
270
|
-
cur.execute("create table customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
271
|
-
|
272
|
-
assert (
|
273
|
-
"090105 (22000): Cannot perform CREATE TABLE. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
274
|
-
in str(excinfo.value)
|
275
|
-
)
|
276
|
-
|
277
|
-
# test description works without database
|
278
|
-
assert cur.execute("SELECT 1").fetchall() == [(1,)]
|
279
|
-
assert cur.description
|
280
|
-
|
281
|
-
|
282
|
-
def test_connect_without_schema(_fakesnow: None):
|
283
|
-
# database will be created but not schema
|
284
|
-
with snowflake.connector.connect(database="marts") as conn, conn.cursor() as cur:
|
285
|
-
assert not conn.schema
|
286
|
-
|
287
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
288
|
-
cur.execute("select * from customers")
|
289
|
-
|
290
|
-
# actual snowflake error message is:
|
291
|
-
#
|
292
|
-
# 002003 (42S02): SQL compilation error:
|
293
|
-
# Object 'CUSTOMERS' does not exist or not authorized.
|
294
|
-
# assert (
|
295
|
-
# "002003 (42S02): Catalog Error: Table with name customers does not exist!"
|
296
|
-
# in str(excinfo.value)
|
297
|
-
# )
|
298
|
-
|
299
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
300
|
-
cur.execute("create table customers (ID int, FIRST_NAME varchar, LAST_NAME varchar)")
|
301
|
-
|
302
|
-
assert (
|
303
|
-
"090106 (22000): Cannot perform CREATE TABLE. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name."
|
304
|
-
in str(excinfo.value)
|
305
|
-
)
|
306
|
-
|
307
|
-
# test description works without schema
|
308
|
-
assert cur.execute("SELECT 1").fetchall() == [(1,)]
|
309
|
-
assert cur.description
|
310
|
-
|
311
|
-
conn.execute_string("CREATE SCHEMA schema1; USE SCHEMA schema1;")
|
312
|
-
assert conn.schema == "SCHEMA1"
|
313
|
-
|
314
|
-
|
315
|
-
def test_connect_with_non_existent_db_or_schema(_fakesnow_no_auto_create: None):
|
316
|
-
# can connect with db that doesn't exist
|
317
|
-
with snowflake.connector.connect(database="marts") as conn, conn.cursor() as cur:
|
318
|
-
# but no valid database set
|
319
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
320
|
-
cur.execute("create table foobar (i int)")
|
321
|
-
|
322
|
-
assert (
|
323
|
-
"090105 (22000): Cannot perform CREATE TABLE. This session does not have a current database. Call 'USE DATABASE', or use a qualified name."
|
324
|
-
in str(excinfo.value)
|
325
|
-
)
|
326
|
-
|
327
|
-
# database still present on connection
|
328
|
-
assert conn.database == "MARTS"
|
329
|
-
|
330
|
-
cur.execute("CREATE database marts")
|
331
|
-
|
332
|
-
# can connect with schema that doesn't exist
|
333
|
-
with snowflake.connector.connect(database="marts", schema="jaffles") as conn, conn.cursor() as cur:
|
334
|
-
# but no valid schema set
|
335
|
-
with pytest.raises(snowflake.connector.errors.ProgrammingError) as excinfo:
|
336
|
-
cur.execute("create table foobar (i int)")
|
337
|
-
|
338
|
-
assert (
|
339
|
-
"090106 (22000): Cannot perform CREATE TABLE. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name."
|
340
|
-
in str(excinfo.value)
|
341
|
-
)
|
342
|
-
|
343
|
-
# schema still present on connection
|
344
|
-
assert conn.schema == "JAFFLES"
|
345
|
-
|
346
|
-
|
347
175
|
def test_create_database_respects_if_not_exists() -> None:
|
348
176
|
with tempfile.TemporaryDirectory(prefix="fakesnow-test") as db_path, fakesnow.patch(db_path=db_path):
|
349
177
|
cursor = snowflake.connector.connect().cursor()
|
@@ -1401,6 +1229,12 @@ def test_sfqid(cur: snowflake.connector.cursor.SnowflakeCursor):
|
|
1401
1229
|
assert cur.sfqid == "fakesnow"
|
1402
1230
|
|
1403
1231
|
|
1232
|
+
def test_string_constant(cur: snowflake.connector.cursor.SnowflakeCursor):
|
1233
|
+
assert cur.execute("""
|
1234
|
+
select $$hello
|
1235
|
+
world$$""").fetchall() == [("hello\nworld",)]
|
1236
|
+
|
1237
|
+
|
1404
1238
|
def test_tags_noop(cur: snowflake.connector.cursor.SnowflakeCursor):
|
1405
1239
|
cur.execute("CREATE TABLE table1 (id int)")
|
1406
1240
|
cur.execute("ALTER TABLE table1 SET TAG foo='bar'")
|
@@ -193,3 +193,21 @@ def test_info_schema_views_with_views(conn: snowflake.connector.SnowflakeConnect
|
|
193
193
|
"comment": None,
|
194
194
|
}
|
195
195
|
]
|
196
|
+
|
197
|
+
|
198
|
+
def test_info_schema_show_primary_keys_from_table(cur: snowflake.connector.cursor.SnowflakeCursor) -> None:
|
199
|
+
cur.execute(
|
200
|
+
"""
|
201
|
+
CREATE TABLE test_table (
|
202
|
+
ID varchar,
|
203
|
+
VERSION varchar,
|
204
|
+
PRIMARY KEY (ID, VERSION)
|
205
|
+
)
|
206
|
+
"""
|
207
|
+
)
|
208
|
+
|
209
|
+
cur.execute("SHOW PRIMARY KEYS IN test_table")
|
210
|
+
pk_result = cur.fetchall()
|
211
|
+
|
212
|
+
pk_columns = [result[4] for result in pk_result]
|
213
|
+
assert pk_columns == ["ID", "VERSION"]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|