22# Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
33#
44
5- from ctypes import ArgumentError
65import re
7- from typing import List , Optional , Union , TYPE_CHECKING
8-
9- from snowflake .snowpark ._internal .analyzer .analyzer_utils import unquote_if_quoted
10- from snowflake .snowpark .exceptions import SnowparkSQLException , NotFoundError
6+ from typing import List , Optional , Union
117
128try :
9+ from snowflake .core import Root # type: ignore
1310 from snowflake .core .database import Database # type: ignore
14- from snowflake .core .database . _generated . models import Database as ModelDatabase # type: ignore
11+ from snowflake .core .exceptions import NotFoundError
1512 from snowflake .core .procedure import Procedure
1613 from snowflake .core .schema import Schema # type: ignore
17- from snowflake .core .schema ._generated .models import Schema as ModelSchema # type: ignore
1814 from snowflake .core .table import Table , TableColumn
1915 from snowflake .core .user_defined_function import UserDefinedFunction
2016 from snowflake .core .view import View
2319 "Missing optional dependency: 'snowflake.core'."
2420 ) from e # pragma: no cover
2521
26- from snowflake .snowpark ._internal .type_utils import (
27- convert_sp_to_sf_type ,
28- type_string_to_type_object ,
29- )
22+
23+ import snowflake .snowpark
24+ from snowflake .snowpark ._internal .type_utils import convert_sp_to_sf_type
3025from snowflake .snowpark .functions import lit , parse_json
3126from snowflake .snowpark .types import DataType
3227
33- if TYPE_CHECKING :
34- from snowflake .snowpark .session import Session
35-
3628
3729class Catalog :
3830 """The Catalog class provides methods to interact with and manage the Snowflake objects.
3931 It allows users to list, get, and drop various database objects such as databases, schemas, tables,
4032 views, functions, etc.
4133 """
4234
43- def __init__ (self , session : "Session" ) -> None :
35+ def __init__ (self , session : "snowflake.snowpark.session. Session" ) -> None : # type: ignore
4436 self ._session = session
37+ self ._root = Root (session )
4538 self ._python_regex_udf = None
4639
4740 def _parse_database (
4841 self ,
49- database : object ,
42+ database : Optional [ Union [ str , Database ]] ,
5043 model_obj : Optional [
5144 Union [str , Schema , Table , View , Procedure , UserDefinedFunction ]
5245 ] = None ,
@@ -73,7 +66,7 @@ def _parse_database(
7366
7467 def _parse_schema (
7568 self ,
76- schema : object ,
69+ schema : Optional [ Union [ str , Schema ]] ,
7770 model_obj : Optional [
7871 Union [str , Table , View , Procedure , UserDefinedFunction ]
7972 ] = None ,
@@ -173,28 +166,11 @@ def list_databases(
173166 pattern: the python regex pattern of name to match. Defaults to None.
174167 like: the sql style pattern for name to match. Default to None.
175168 """
176- like_str = f"LIKE '{ like } '" if like else ""
177- df = self ._session .sql (f"SHOW AS RESOURCE DATABASES { like_str } " )
169+ iter = self ._root .databases .iter (like = like )
178170 if pattern :
179- # initialize udf
180- self ._initialize_regex_udf ()
181- assert self ._python_regex_udf is not None # pyright
182-
183- # The result of SHOW AS RESOURCE query is a json string which contains
184- # key 'name' to store the name of the object. We parse json for the returned
185- # result and apply the filter on name.
186- df = df .filter (
187- self ._python_regex_udf (
188- lit (pattern ), parse_json ('"As Resource"' )["name" ]
189- )
190- )
171+ iter = filter (lambda x : re .match (pattern , x .name ), iter )
191172
192- return list (
193- map (
194- lambda row : Database ._from_model (ModelDatabase .from_json (str (row [0 ]))),
195- df .collect (),
196- )
197- )
173+ return list (iter )
198174
199175 def list_schemas (
200176 self ,
@@ -212,28 +188,10 @@ def list_schemas(
212188 like: the sql style pattern for name to match. Default to None.
213189 """
214190 db_name = self ._parse_database (database )
215- like_str = f"LIKE '{ like } '" if like else ""
216- df = self ._session .sql (f"SHOW AS RESOURCE SCHEMAS { like_str } IN { db_name } " )
191+ iter = self ._root .databases [db_name ].schemas .iter (like = like )
217192 if pattern :
218- # initialize udf
219- self ._initialize_regex_udf ()
220- assert self ._python_regex_udf is not None # pyright
221-
222- # The result of SHOW AS RESOURCE query is a json string which contains
223- # key 'name' to store the name of the object. We parse json for the returned
224- # result and apply the filter on name.
225- df = df .filter (
226- self ._python_regex_udf (
227- lit (pattern ), parse_json ('"As Resource"' )["name" ]
228- )
229- )
230-
231- return list (
232- map (
233- lambda row : Schema ._from_model (ModelSchema .from_json (str (row [0 ]))),
234- df .collect (),
235- )
236- )
193+ iter = filter (lambda x : re .match (pattern , x .name ), iter )
194+ return list (iter )
237195
238196 def list_tables (
239197 self ,
@@ -371,27 +329,14 @@ def get_current_schema(self) -> Optional[str]:
371329
372330 def get_database (self , database : str ) -> Database :
373331 """Name of the database to get"""
374- try :
375- return self .list_databases (like = unquote_if_quoted (database ))[0 ]
376- except IndexError :
377- raise NotFoundError (f"Database with name { database } could not be found" )
332+ return self ._root .databases [database ].fetch ()
378333
379334 def get_schema (
380335 self , schema : str , * , database : Optional [Union [str , Database ]] = None
381336 ) -> Schema :
382337 """Name of the schema to get."""
383338 db_name = self ._parse_database (database )
384- try :
385- return self .list_schemas (database = db_name , like = unquote_if_quoted (schema ))[
386- 0
387- ]
388- except (
389- IndexError , # schema with this name doesn't exist
390- SnowparkSQLException , # database in which we are looking doesn't exist
391- ):
392- raise NotFoundError (
393- f"Schema with name { schema } could not be found in database '{ db_name } '"
394- )
339+ return self ._root .databases [db_name ].schemas [schema ].fetch ()
395340
396341 def get_table (
397342 self ,
@@ -410,16 +355,12 @@ def get_table(
410355 """
411356 db_name = self ._parse_database (database )
412357 schema_name = self ._parse_schema (schema )
413- try :
414- return self .listTables (
415- database = db_name ,
416- schema = schema_name ,
417- like = unquote_if_quoted (table_name ),
418- )[0 ]
419- except IndexError :
420- raise NotFoundError (
421- f"Table with name { table_name } could not be found in schema '{ db_name } .{ schema_name } '"
422- )
358+ return (
359+ self ._root .databases [db_name ]
360+ .schemas [schema_name ]
361+ .tables [table_name ]
362+ .fetch ()
363+ )
423364
424365 def get_view (
425366 self ,
@@ -438,16 +379,9 @@ def get_view(
438379 """
439380 db_name = self ._parse_database (database )
440381 schema_name = self ._parse_schema (schema )
441- try :
442- return self .list_views (
443- database = db_name ,
444- schema = schema_name ,
445- like = unquote_if_quoted (view_name ),
446- )[0 ]
447- except IndexError :
448- raise NotFoundError (
449- f"View with name { view_name } could not be found in schema '{ db_name } .{ schema_name } '"
450- )
382+ return (
383+ self ._root .databases [db_name ].schemas [schema_name ].views [view_name ].fetch ()
384+ )
451385
452386 def get_procedure (
453387 self ,
@@ -469,19 +403,12 @@ def get_procedure(
469403 db_name = self ._parse_database (database )
470404 schema_name = self ._parse_schema (schema )
471405 procedure_id = self ._parse_function_or_procedure (procedure_name , arg_types )
472-
473- try :
474- procedures = self ._session .sql (
475- f"DESCRIBE AS RESOURCE PROCEDURE { db_name } .{ schema_name } .{ procedure_id } "
476- ).collect ()
477- return Procedure .from_json (str (procedures [0 ][0 ]))
478- except (
479- IndexError , # when sql returned no results
480- SnowparkSQLException , # when database, or schema doesn't exist
481- ):
482- raise NotFoundError (
483- f"Procedure with name { procedure_name } and arguments { arg_types } could not be found in schema '{ db_name } .{ schema_name } '"
484- )
406+ return (
407+ self ._root .databases [db_name ]
408+ .schemas [schema_name ]
409+ .procedures [procedure_id ]
410+ .fetch ()
411+ )
485412
486413 def get_user_defined_function (
487414 self ,
@@ -504,19 +431,12 @@ def get_user_defined_function(
504431 db_name = self ._parse_database (database )
505432 schema_name = self ._parse_schema (schema )
506433 function_id = self ._parse_function_or_procedure (udf_name , arg_types )
507-
508- try :
509- procedures = self ._session .sql (
510- f"DESCRIBE AS RESOURCE FUNCTION { db_name } .{ schema_name } .{ function_id } "
511- ).collect ()
512- return UserDefinedFunction .from_json (str (procedures [0 ][0 ]))
513- except (
514- IndexError , # when sql returned no results
515- SnowparkSQLException , # when database, or schema doesn't exist
516- ):
517- raise NotFoundError (
518- f"Function with name { udf_name } and arguments { arg_types } could not be found in schema '{ db_name } .{ schema_name } '"
519- )
434+ return (
435+ self ._root .databases [db_name ]
436+ .schemas [schema_name ]
437+ .user_defined_functions [function_id ]
438+ .fetch ()
439+ )
520440
521441 # set methods
522442 def set_current_database (self , database : Union [str , Database ]) -> None :
@@ -546,7 +466,7 @@ def database_exists(self, database: Union[str, Database]) -> bool:
546466 """
547467 db_name = self ._parse_database (database )
548468 try :
549- self .get_database ( db_name )
469+ self ._root . databases [ db_name ]. fetch ( )
550470 return True
551471 except NotFoundError :
552472 return False
@@ -567,7 +487,7 @@ def schema_exists(
567487 db_name = self ._parse_database (database , schema )
568488 schema_name = self ._parse_schema (schema )
569489 try :
570- self .get_schema ( schema = schema_name , database = db_name )
490+ self ._root . databases [ db_name ]. schemas [ schema_name ]. fetch ( )
571491 return True
572492 except NotFoundError :
573493 return False
@@ -591,7 +511,9 @@ def table_exists(
591511 schema_name = self ._parse_schema (schema , table )
592512 table_name = table if isinstance (table , str ) else table .name
593513 try :
594- self .get_table (table_name = table_name , database = db_name , schema = schema_name )
514+ self ._root .databases [db_name ].schemas [schema_name ].tables [
515+ table_name
516+ ].fetch ()
595517 return True
596518 except NotFoundError :
597519 return False
@@ -615,7 +537,7 @@ def view_exists(
615537 schema_name = self ._parse_schema (schema , view )
616538 view_name = view if isinstance (view , str ) else view .name
617539 try :
618- self .get_view ( view_name = view_name , database = db_name , schema = schema_name )
540+ self ._root . databases [ db_name ]. schemas [ schema_name ]. views [ view_name ]. fetch ( )
619541 return True
620542 except NotFoundError :
621543 return False
@@ -637,24 +559,14 @@ def procedure_exists(
637559 database: database name or ``Database`` object. Defaults to None.
638560 schema: schema name or ``Schema`` object. Defaults to None.
639561 """
562+ db_name = self ._parse_database (database , procedure )
563+ schema_name = self ._parse_schema (schema , procedure )
564+ procedure_id = self ._parse_function_or_procedure (procedure , arg_types )
565+
640566 try :
641- if isinstance (procedure , Procedure ):
642- if arg_types is not None or database is not None or schema is not None :
643- raise ArgumentError (
644- "When provided procedure is a Procedure class no other arguments can be provided"
645- )
646- database = procedure .database_name
647- schema = procedure .schema_name
648- arg_types = [
649- type_string_to_type_object (a .datatype ) for a in procedure .arguments
650- ]
651- procedure = procedure .name
652- self .get_procedure (
653- procedure_name = procedure ,
654- arg_types = arg_types ,
655- database = database ,
656- schema = schema ,
657- )
567+ self ._root .databases [db_name ].schemas [schema_name ].procedures [
568+ procedure_id
569+ ].fetch ()
658570 return True
659571 except NotFoundError :
660572 return False
@@ -678,24 +590,14 @@ def user_defined_function_exists(
678590 database: database name or ``Database`` object. Defaults to None.
679591 schema: schema name or ``Schema`` object. Defaults to None.
680592 """
593+ db_name = self ._parse_database (database , udf )
594+ schema_name = self ._parse_schema (schema , udf )
595+ function_id = self ._parse_function_or_procedure (udf , arg_types )
596+
681597 try :
682- if isinstance (udf , UserDefinedFunction ):
683- if arg_types is not None or database is not None or schema is not None :
684- raise ArgumentError (
685- "When provided udf is a UserDefinedFunction class no other arguments can be provided"
686- )
687- database = udf .database_name
688- schema = udf .schema_name
689- arg_types = [
690- type_string_to_type_object (a .datatype ) for a in udf .arguments
691- ]
692- udf = udf .name
693- self .get_user_defined_function (
694- udf_name = udf ,
695- arg_types = arg_types ,
696- database = database ,
697- schema = schema ,
698- )
598+ self ._root .databases [db_name ].schemas [schema_name ].user_defined_functions [
599+ function_id
600+ ].fetch ()
699601 return True
700602 except NotFoundError :
701603 return False
@@ -708,7 +610,7 @@ def drop_database(self, database: Union[str, Database]) -> None:
708610 database: database name or ``Database`` object.
709611 """
710612 db_name = self ._parse_database (database )
711- self ._session . sql ( f"DROP DATABASE { db_name } " ). collect ()
613+ self ._root . databases [ db_name ]. drop ()
712614
713615 def drop_schema (
714616 self ,
@@ -725,7 +627,7 @@ def drop_schema(
725627 """
726628 db_name = self ._parse_database (database , schema )
727629 schema_name = self ._parse_schema (schema )
728- self ._session . sql ( f"DROP SCHEMA { db_name } . { schema_name } " ). collect ()
630+ self ._root . databases [ db_name ]. schemas [ schema_name ]. drop ()
729631
730632 def drop_table (
731633 self ,
@@ -746,7 +648,7 @@ def drop_table(
746648 schema_name = self ._parse_schema (schema , table )
747649 table_name = table if isinstance (table , str ) else table .name
748650
749- self ._session . sql ( f"DROP TABLE { db_name } . { schema_name } . { table_name } " ). collect ()
651+ self ._root . databases [ db_name ]. schemas [ schema_name ]. tables [ table_name ]. drop ()
750652
751653 def drop_view (
752654 self ,
@@ -767,7 +669,7 @@ def drop_view(
767669 schema_name = self ._parse_schema (schema , view )
768670 view_name = view if isinstance (view , str ) else view .name
769671
770- self ._session . sql ( f"DROP VIEW { db_name } . { schema_name } . { view_name } " ). collect ()
672+ self ._root . databases [ db_name ]. schemas [ schema_name ]. views [ view_name ]. drop ()
771673
772674 # aliases
773675 listDatabases = list_databases
0 commit comments