Skip to content

Commit

Permalink
feat: describe view information_schema.*
Browse files Browse the repository at this point in the history
  • Loading branch information
tekumara committed Aug 9, 2024
1 parent b874fc1 commit facc390
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 5 deletions.
1 change: 0 additions & 1 deletion fakesnow/fakes.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,6 @@ def describe(self, command: str, *args: Any, **kwargs: Any) -> list[ResultMetada
def description(self) -> list[ResultMetadata]:
# use a separate cursor to avoid consuming the result set on this cursor
with self._conn.cursor() as cur:
# self._duck_conn.execute(sql, params)
expression = sqlglot.parse_one(f"DESCRIBE {self._last_sql}", read="duckdb")
cur._execute(expression, self._last_params) # noqa: SLF001
meta = FakeSnowflakeCursor._describe_as_result_metadata(cur.fetchall())
Expand Down
1 change: 1 addition & 0 deletions fakesnow/info_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
"""
)


# replicates https://docs.snowflake.com/sql-reference/info-schema/databases
SQL_CREATE_INFORMATION_SCHEMA_DATABASES_VIEW = Template(
"""
Expand Down
21 changes: 20 additions & 1 deletion fakesnow/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,25 @@ def create_database(expression: exp.Expression, db_path: Path | None = None) ->
"""
)

SQL_DESCRIBE_INFO_SCHEMA = Template(
"""
SELECT
column_name AS "name",
column_type as "type",
'COLUMN' AS "kind",
CASE WHEN "null" = 'YES' THEN 'Y' ELSE 'N' END AS "null?",
NULL::VARCHAR AS "default",
'N' AS "primary key",
'N' AS "unique key",
NULL::VARCHAR AS "check",
NULL::VARCHAR AS "expression",
NULL::VARCHAR AS "comment",
NULL::VARCHAR AS "policy name",
NULL::JSON AS "privacy domain",
FROM (DESCRIBE information_schema.${view})
"""
)


def describe_table(
expression: exp.Expression, current_database: str | None = None, current_schema: str | None = None
Expand All @@ -191,7 +210,7 @@ def describe_table(

if schema and schema.upper() == "INFORMATION_SCHEMA":
# information schema views don't exist in _fs_columns_snowflake
return expression
return sqlglot.parse_one(SQL_DESCRIBE_INFO_SCHEMA.substitute(view=table.name), read="duckdb")

return sqlglot.parse_one(
SQL_DESCRIBE_TABLE.substitute(catalog=catalog, schema=schema, table=table.name),
Expand Down
40 changes: 37 additions & 3 deletions tests/test_info_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,45 @@ def test_info_schema_columns_describe(cur: snowflake.connector.cursor.SnowflakeC

assert cur.description == expected_metadata


def test_describe_view_columns(dcur: snowflake.connector.cursor.DictCursor):
cols = [
"name",
"type",
"kind",
"null?",
"default",
"primary key",
"unique key",
"check",
"expression",
"comment",
"policy name",
"privacy domain",
]
dcur.execute("describe view information_schema.columns")
result: list[dict] = dcur.fetchall() # type: ignore
assert list(result[0].keys()) == cols
names = [r["name"] for r in result]
# should contain snowflake-specific columns (from _FS_COLUMNS_SNOWFLAKE)
cur.execute("describe view information_schema.columns")
result = cur.fetchall()
names = [name for (name, *_) in result]
assert "comment" in names
# fmt: off
assert dcur.description[:-1] == [
ResultMetadata(name='name', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='type', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='kind', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='null?', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='default', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='primary key', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='unique key', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='check', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='expression', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='comment', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
ResultMetadata(name='policy name', type_code=2, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True),
# TODO: ignore the following, see https://github.com/tekumara/fakesnow/issues/26
# ResultMetadata(name='privacy domain', type_code=9, display_size=None, internal_size=16777216, precision=None, scale=None, is_nullable=True)
]
# fmt: on


def test_info_schema_columns_numeric(cur: snowflake.connector.cursor.SnowflakeCursor):
Expand Down

0 comments on commit facc390

Please sign in to comment.