Skip to content

Commit 36ed241

Browse files
sfc-gh-stakedasfc-gh-abhatnagar
authored andcommitted
SNOW-143457 import sqlalchemy
1 parent a96026d commit 36ed241

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

__init__.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
from . import base
88
from . import snowdialect
99
from .custom_commands import (
10-
MergeInto, CSVFormatter, JSONFormatter, PARQUETFormatter, CopyIntoStorage, AWSBucket, AzureContainer
10+
MergeInto,
11+
CSVFormatter,
12+
JSONFormatter,
13+
PARQUETFormatter,
14+
CopyIntoStorage,
15+
AWSBucket,
16+
AzureContainer,
17+
ExternalStage
1118
)
1219
from .util import _url as URL
1320
from .version import VERSION
@@ -95,5 +102,6 @@
95102
'PARQUETFormatter',
96103
'CopyIntoStorage',
97104
'AWSBucket',
98-
'AzureContainer'
105+
'AzureContainer',
106+
'ExternalStage',
99107
)

base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ def visit_copy_formatter(self, formatter, **kw):
224224
value))
225225
for name, value in options_list])) if formatter.options else "")
226226

227+
def visit_external_stage(self, stage, **kw):
228+
return "@{}{}{}".format(stage.namespace, stage.name, stage.path)
229+
227230
def visit_aws_bucket(self, aws_bucket, **kw):
228231
credentials_list = list(aws_bucket.credentials_used.items())
229232
if kw.get('deterministic', False):

custom_commands.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,27 @@ def snappy_compression(self, comp):
289289
return self
290290

291291

292+
class ExternalStage(ClauseElement):
293+
"""External Stage descriptor"""
294+
__visit_name__ = "external_stage"
295+
296+
@staticmethod
297+
def prepare_namespace(namespace):
298+
return "{}.".format(namespace) if not namespace.endswith(".") else namespace
299+
300+
@staticmethod
301+
def prepare_path(path):
302+
return "/{}".format(path) if not path.startswith("/") else path
303+
304+
def __init__(self, name, path=None, namespace=None):
305+
self.name = name
306+
self.path = self.prepare_path(path) if path else ""
307+
self.namespace = self.prepare_namespace(namespace) if namespace else ""
308+
309+
def __repr__(self):
310+
return "@{}{}{}".format(self.namespace, self.name, self.path)
311+
312+
292313
class AWSBucket(ClauseElement):
293314
"""AWS S3 bucket descriptor"""
294315
__visit_name__ = 'aws_bucket'

test/test_copy.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,27 @@
99
AzureContainer,
1010
CopyIntoStorage,
1111
CSVFormatter,
12+
ExternalStage,
1213
JSONFormatter,
1314
PARQUETFormatter,
1415
)
1516
from sqlalchemy import Column, Integer, MetaData, Sequence, String, Table
1617
from sqlalchemy.sql import select
1718

1819

20+
def test_external_stage(sql_compiler):
21+
assert ExternalStage.prepare_namespace("something") == "something."
22+
assert ExternalStage.prepare_path("prefix") == "/prefix"
23+
24+
# All arguments are handled
25+
assert (
26+
sql_compiler(ExternalStage(name="name", path="prefix/path", namespace="namespace")) == "@namespace.name/prefix/path"
27+
)
28+
29+
# defaults don't ruin things
30+
assert sql_compiler(ExternalStage(name="name", path=None, namespace=None)) == "@name"
31+
32+
1933
def test_copy_into_location(engine_testaccount, sql_compiler):
2034
meta = MetaData()
2135
conn = engine_testaccount.connect()
@@ -71,6 +85,12 @@ def test_copy_into_location(engine_testaccount, sql_compiler):
7185
"FIELD_DELIMITER=',') ENCRYPTION="
7286
"(KMS_KEY_ID='1234abcd-12ab-34cd-56ef-1234567890ab' TYPE='AWS_SSE_KMS')")
7387

88+
copy_stmt_6 = CopyIntoStorage(from_=food_items, into=ExternalStage(name="stage_name"), formatter=CSVFormatter())
89+
assert sql_compiler(copy_stmt_6) == "COPY INTO @stage_name FROM python_tests_foods FILE_FORMAT=(TYPE=csv)"
90+
91+
copy_stmt_7 = CopyIntoStorage(from_=food_items, into=ExternalStage(name="stage_name", path="prefix/file", namespace="name"), formatter=CSVFormatter())
92+
assert sql_compiler(copy_stmt_7) == "COPY INTO @name.stage_name/prefix/file FROM python_tests_foods FILE_FORMAT=(TYPE=csv)"
93+
7494
# NOTE Other than expect known compiled text, submit it to RegressionTests environment and expect them to fail, but
7595
# because of the right reasons
7696
try:

0 commit comments

Comments
 (0)