1+ """Module to convert from Ibis expression to SQL string."""
2+
13import base64
24import datetime
35from functools import partial
2224
2325
2426def build_ast (expr , context ):
27+ """Create a QueryAST from an Ibis expression."""
2528 builder = BigQueryQueryBuilder (expr , context = context )
2629 return builder .get_result ()
2730
2831
2932class BigQueryUDFNode (ops .ValueOp ):
30- pass
33+ """Represents use of a UDF."""
3134
3235
3336class BigQuerySelectBuilder (comp .SelectBuilder ):
37+ """Transforms expression IR to a query pipeline."""
38+
3439 @property
3540 def _select_class (self ):
3641 return BigQuerySelect
3742
3843
3944class BigQueryUDFDefinition (comp .DDL ):
45+ """Represents definition of a temporary UDF."""
46+
4047 def __init__ (self , expr , context ):
4148 self .expr = expr
4249 self .context = context
4350
4451 def compile (self ):
52+ """Generate UDF string from definition."""
4553 return self .expr .op ().js
4654
4755
4856class BigQueryUnion (comp .Union ):
57+ """Union of tables."""
58+
4959 @staticmethod
5060 def keyword (distinct ):
61+ """Use disctinct UNION if distinct is True."""
5162 return 'UNION DISTINCT' if distinct else 'UNION ALL'
5263
5364
5465def find_bigquery_udf (expr ):
66+ """Filter which includes only UDFs from expression tree."""
5567 if isinstance (expr .op (), BigQueryUDFNode ):
5668 result = expr
5769 else :
@@ -60,11 +72,13 @@ def find_bigquery_udf(expr):
6072
6173
6274class BigQueryQueryBuilder (comp .QueryBuilder ):
75+ """Generator of QueryASTs."""
6376
6477 select_builder = BigQuerySelectBuilder
6578 union_class = BigQueryUnion
6679
6780 def generate_setup_queries (self ):
81+ """Generate DDL for temporary resources."""
6882 queries = map (
6983 partial (BigQueryUDFDefinition , context = self .context ),
7084 lin .traverse (find_bigquery_udf , self .expr ),
@@ -78,6 +92,8 @@ def generate_setup_queries(self):
7892
7993
8094class BigQueryContext (comp .QueryContext ):
95+ """Recorder of information used in AST to SQL conversion."""
96+
8197 def _to_sql (self , expr , ctx ):
8298 builder = BigQueryQueryBuilder (expr , context = ctx )
8399 query_ast = builder .get_result ()
@@ -102,11 +118,13 @@ def extract_field_formatter(translator, expr):
102118
103119@bigquery_cast .register (str , dt .Timestamp , dt .Integer )
104120def bigquery_cast_timestamp_to_integer (compiled_arg , from_ , to ):
121+ """Convert TIMESTAMP to INT64 (seconds since Unix epoch)."""
105122 return 'UNIX_MICROS({})' .format (compiled_arg )
106123
107124
108125@bigquery_cast .register (str , dt .DataType , dt .DataType )
109126def bigquery_cast_generate (compiled_arg , from_ , to ):
127+ """Cast to desired type."""
110128 sql_type = ibis_type_to_bigquery_type (to )
111129 return 'CAST({} AS {})' .format (compiled_arg , sql_type )
112130
@@ -425,6 +443,8 @@ def _formatter(translator, expr):
425443
426444
427445class BigQueryExprTranslator (BaseExprTranslator ):
446+ """Translate expressions to strings."""
447+
428448 _registry = _operation_registry
429449 _rewrites = BaseExprTranslator ._rewrites .copy ()
430450
@@ -443,24 +463,28 @@ def _trans_param(self, expr):
443463
444464@compiles (ops .DayOfWeekIndex )
445465def bigquery_day_of_week_index (t , e ):
466+ """Convert timestamp to day-of-week integer."""
446467 arg = e .op ().args [0 ]
447468 arg_formatted = t .translate (arg )
448469 return 'MOD(EXTRACT(DAYOFWEEK FROM {}) + 5, 7)' .format (arg_formatted )
449470
450471
451472@rewrites (ops .DayOfWeekName )
452473def bigquery_day_of_week_name (e ):
474+ """Convert TIMESTAMP to day-of-week string."""
453475 arg = e .op ().args [0 ]
454476 return arg .strftime ('%A' )
455477
456478
457479@compiles (ops .Divide )
458480def bigquery_compiles_divide (t , e ):
481+ """Floating point division."""
459482 return 'IEEE_DIVIDE({}, {})' .format (* map (t .translate , e .op ().args ))
460483
461484
462485@compiles (ops .Strftime )
463486def compiles_strftime (translator , expr ):
487+ """Timestamp formatting."""
464488 arg , format_string = expr .op ().args
465489 arg_type = arg .type ()
466490 strftime_format_func_name = STRFTIME_FORMAT_FUNCTIONS [type (arg_type )]
@@ -480,6 +504,7 @@ def compiles_strftime(translator, expr):
480504
481505@compiles (ops .StringToTimestamp )
482506def compiles_string_to_timestamp (translator , expr ):
507+ """Timestamp parsing."""
483508 arg , format_string , timezone_arg = expr .op ().args
484509 fmt_string = translator .translate (format_string )
485510 arg_formatted = translator .translate (arg )
@@ -492,6 +517,7 @@ def compiles_string_to_timestamp(translator, expr):
492517
493518
494519class BigQueryTableSetFormatter (BaseTableSetFormatter ):
520+
495521 def _quote_identifier (self , name ):
496522 if re .match (r'^[A-Za-z][A-Za-z_0-9]*$' , name ):
497523 return name
0 commit comments