Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions sqlglot/dialects/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,22 @@ class Parser(parser.Parser):
"TIMESTAMP_FROM_PARTS": _build_timestamp_from_parts,
"TIMESTAMPNTZFROMPARTS": _build_timestamp_from_parts,
"TIMESTAMP_NTZ_FROM_PARTS": _build_timestamp_from_parts,
"TRY_DECRYPT": lambda args: exp.Decrypt(
this=seq_get(args, 0),
passphrase=seq_get(args, 1),
aad=seq_get(args, 2),
encryption_method=seq_get(args, 3),
safe=True,
),
"TRY_DECRYPT_RAW": lambda args: exp.DecryptRaw(
this=seq_get(args, 0),
key=seq_get(args, 1),
iv=seq_get(args, 2),
aad=seq_get(args, 3),
encryption_method=seq_get(args, 4),
aead=seq_get(args, 5),
safe=True,
),
"TRY_PARSE_JSON": lambda args: exp.ParseJSON(this=seq_get(args, 0), safe=True),
"TRY_TO_BINARY": lambda args: exp.ToBinary(
this=seq_get(args, 0), format=seq_get(args, 1), safe=True
Expand Down Expand Up @@ -1453,6 +1469,23 @@ class Generator(generator.Generator):
exp.DatetimeAdd: date_delta_sql("TIMESTAMPADD"),
exp.DatetimeDiff: timestampdiff_sql,
exp.DateStrToDate: datestrtodate_sql,
exp.Decrypt: lambda self, e: self.func(
f"{'TRY_' if e.args.get('safe') else ''}DECRYPT",
e.this,
e.args.get("passphrase"),
e.args.get("aad"),
e.args.get("encryption_method"),
e.args.get("aead"),
),
exp.DecryptRaw: lambda self, e: self.func(
f"{'TRY_' if e.args.get('safe') else ''}DECRYPT_RAW",
e.this,
e.args.get("key"),
e.args.get("iv"),
e.args.get("aad"),
e.args.get("encryption_method"),
e.args.get("aead"),
),
exp.DayOfMonth: rename_func("DAYOFMONTH"),
exp.DayOfWeek: rename_func("DAYOFWEEK"),
exp.DayOfWeekIso: rename_func("DAYOFWEEKISO"),
Expand Down
34 changes: 34 additions & 0 deletions sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6732,6 +6732,30 @@ class DecodeCase(Func):
is_var_len_args = True


# https://docs.snowflake.com/en/sql-reference/functions/decrypt
class Decrypt(Func):
arg_types = {
"this": True,
"passphrase": True,
"aad": False,
"encryption_method": False,
"safe": False,
}


# https://docs.snowflake.com/en/sql-reference/functions/decrypt_raw
class DecryptRaw(Func):
arg_types = {
"this": True,
"key": True,
"iv": True,
"aad": False,
"encryption_method": False,
"aead": False,
"safe": False,
}


class DenseRank(AggFunc):
arg_types = {"expressions": False}
is_var_len_args = True
Expand All @@ -6745,6 +6769,16 @@ class Encode(Func):
arg_types = {"this": True, "charset": True}


# https://docs.snowflake.com/en/sql-reference/functions/encrypt
class Encrypt(Func):
arg_types = {"this": True, "passphrase": True, "aad": False, "encryption_method": False}


# https://docs.snowflake.com/en/sql-reference/functions/encrypt_raw
class EncryptRaw(Func):
arg_types = {"this": True, "key": True, "iv": True, "aad": False, "encryption_method": False}


class EqualNull(Func):
arg_types = {"this": True, "expression": True}

Expand Down
4 changes: 4 additions & 0 deletions sqlglot/typing/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,10 @@ def _annotate_str_to_time(self: TypeAnnotator, expression: exp.StrToTime) -> exp
exp.BitmapOrAgg,
exp.Compress,
exp.DecompressBinary,
exp.Decrypt,
exp.DecryptRaw,
exp.Encrypt,
exp.EncryptRaw,
exp.HexString,
exp.MD5Digest,
exp.SHA1Digest,
Expand Down
33 changes: 33 additions & 0 deletions tests/dialects/test_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -4445,6 +4445,39 @@ def test_ceil(self):
},
)

def test_encryption_functions(self):
# ENCRYPT
self.validate_identity("ENCRYPT(value, 'passphrase')")
self.validate_identity("ENCRYPT(value, 'passphrase', 'aad')")
self.validate_identity("ENCRYPT(value, 'passphrase', 'aad', 'AES-GCM')")

# ENCRYPT_RAW
self.validate_identity("ENCRYPT_RAW(value, key, iv)")
self.validate_identity("ENCRYPT_RAW(value, key, iv, aad)")
self.validate_identity("ENCRYPT_RAW(value, key, iv, aad, 'AES-GCM')")

# DECRYPT
self.validate_identity("DECRYPT(encrypted, 'passphrase')")
self.validate_identity("DECRYPT(encrypted, 'passphrase', 'aad')")
self.validate_identity("DECRYPT(encrypted, 'passphrase', 'aad', 'AES-GCM')")

# DECRYPT_RAW
self.validate_identity("DECRYPT_RAW(encrypted, key, iv)")
self.validate_identity("DECRYPT_RAW(encrypted, key, iv, aad)")
self.validate_identity("DECRYPT_RAW(encrypted, key, iv, aad, 'AES-GCM')")
self.validate_identity("DECRYPT_RAW(encrypted, key, iv, aad, 'AES-GCM', aead)")

# TRY_DECRYPT (parses as Decrypt with safe=True)
self.validate_identity("TRY_DECRYPT(encrypted, 'passphrase')")
self.validate_identity("TRY_DECRYPT(encrypted, 'passphrase', 'aad')")
self.validate_identity("TRY_DECRYPT(encrypted, 'passphrase', 'aad', 'AES-GCM')")

# TRY_DECRYPT_RAW (parses as DecryptRaw with safe=True)
self.validate_identity("TRY_DECRYPT_RAW(encrypted, key, iv)")
self.validate_identity("TRY_DECRYPT_RAW(encrypted, key, iv, aad)")
self.validate_identity("TRY_DECRYPT_RAW(encrypted, key, iv, aad, 'AES-GCM')")
self.validate_identity("TRY_DECRYPT_RAW(encrypted, key, iv, aad, 'AES-GCM', aead)")

def test_update_statement(self):
self.validate_identity("UPDATE test SET t = 1 FROM t1")
self.validate_identity("UPDATE test SET t = 1 FROM t2 JOIN t3 ON t2.id = t3.id")
Expand Down
80 changes: 80 additions & 0 deletions tests/fixtures/optimizer/annotate_functions.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4712,6 +4712,86 @@ NUMBER(38, 15);
VARIANCE_POP(1::NUMBER(30, 5));
NUMBER(38, 12);

# dialect: snowflake
ENCRYPT(tbl.str_col, 'passphrase');
BINARY;

# dialect: snowflake
ENCRYPT(tbl.str_col, 'passphrase', 'aad');
BINARY;

# dialect: snowflake
ENCRYPT(tbl.str_col, 'passphrase', 'aad', 'AES-GCM');
BINARY;

# dialect: snowflake
ENCRYPT_RAW(tbl.str_col, tbl.key_col, tbl.iv_col);
BINARY;

# dialect: snowflake
ENCRYPT_RAW(tbl.str_col, tbl.key_col, tbl.iv_col, tbl.aad_col);
BINARY;

# dialect: snowflake
ENCRYPT_RAW(tbl.str_col, tbl.key_col, tbl.iv_col, tbl.aad_col, 'AES-GCM');
BINARY;

# dialect: snowflake
DECRYPT(tbl.encrypted_col, 'passphrase');
BINARY;

# dialect: snowflake
DECRYPT(tbl.encrypted_col, 'passphrase', 'aad');
BINARY;

# dialect: snowflake
DECRYPT(tbl.encrypted_col, 'passphrase', 'aad', 'AES-GCM');
BINARY;

# dialect: snowflake
DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col);
BINARY;

# dialect: snowflake
DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col);
BINARY;

# dialect: snowflake
DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col, 'AES-GCM');
BINARY;

# dialect: snowflake
DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col, 'AES-GCM', HEX_DECODE_BINARY('ff'));
BINARY;

# dialect: snowflake
TRY_DECRYPT(tbl.encrypted_col, 'passphrase');
BINARY;

# dialect: snowflake
TRY_DECRYPT(tbl.encrypted_col, 'passphrase', 'aad');
BINARY;

# dialect: snowflake
TRY_DECRYPT(tbl.encrypted_col, 'passphrase', 'aad', 'AES-GCM');
BINARY;

# dialect: snowflake
TRY_DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col);
BINARY;

# dialect: snowflake
TRY_DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col);
BINARY;

# dialect: snowflake
TRY_DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col, 'AES-GCM');
BINARY;

# dialect: snowflake
TRY_DECRYPT_RAW(tbl.encrypted_col, tbl.key_col, tbl.iv_col, tbl.aad_col, 'AES-GCM', HEX_DECODE_BINARY('ff'));
BINARY;

--------------------------------------
-- T-SQL
--------------------------------------
Expand Down