1616
1717import dataclasses
1818import typing
19- from typing import TYPE_CHECKING
19+
20+ import google .cloud .bigquery as bigquery
2021
2122import bigframes .core .compile .googlesql .abc as abc
2223import bigframes .core .compile .googlesql .expression as expr
2324
24- if TYPE_CHECKING :
25- import google .cloud .bigquery as bigquery
26-
2725"""This module provides a structured representation of GoogleSQL syntax using nodes.
2826Each node's name and child nodes are designed to strictly follow the official GoogleSQL
2927syntax rules outlined in the documentation:
3028https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax"""
3129
30+ TABLE_SOURCE_TYPE = typing .Union [str , bigquery .TableReference ]
31+
3232
3333@dataclasses .dataclass
3434class QueryExpr (abc .SQLSyntax ):
@@ -53,11 +53,47 @@ def sql(self) -> str:
5353class Select (abc .SQLSyntax ):
5454 """This class represents GoogleSQL `select` syntax."""
5555
56- select_list : typing .Sequence [typing .Union [SelectExpression , SelectAll ]]
57- from_clause_list : typing .Sequence [FromClause ] = ()
56+ select_list : typing .Sequence [
57+ typing .Union [SelectExpression , SelectAll ]
58+ ] = dataclasses .field (default_factory = list )
59+ from_clause_list : typing .Sequence [FromClause ] = dataclasses .field (
60+ default_factory = list
61+ )
5862 distinct : bool = False
5963
64+ def select (
65+ self ,
66+ columns : typing .Union [typing .Iterable [str ], str , None ] = None ,
67+ distinct : bool = False ,
68+ ) -> Select :
69+ if isinstance (columns , str ):
70+ columns = [columns ]
71+ self .select_list : typing .List [typing .Union [SelectExpression , SelectAll ]] = (
72+ [
73+ SelectExpression (expression = expr .ColumnExpression (name = column ))
74+ for column in columns
75+ ]
76+ if columns
77+ else [SelectAll (expression = expr .StarExpression ())]
78+ )
79+ self .distinct = distinct
80+ return self
81+
82+ def from_ (
83+ self ,
84+ sources : typing .Union [TABLE_SOURCE_TYPE , typing .Iterable [TABLE_SOURCE_TYPE ]],
85+ ) -> Select :
86+ if (not isinstance (sources , typing .Iterable )) or isinstance (sources , str ):
87+ sources = [sources ]
88+ self .from_clause_list = [
89+ FromClause (FromItem .from_source (source )) for source in sources
90+ ]
91+ return self
92+
6093 def sql (self ) -> str :
94+ if (self .select_list is not None ) and (not self .select_list ):
95+ raise ValueError ("Select clause has not been properly initialized." )
96+
6197 text = ["SELECT" ]
6298
6399 if self .distinct :
@@ -66,7 +102,7 @@ def sql(self) -> str:
66102 select_list_sql = ",\n " .join ([select .sql () for select in self .select_list ])
67103 text .append (select_list_sql )
68104
69- if self .from_clause_list is not None :
105+ if self .from_clause_list :
70106 from_clauses_sql = ",\n " .join (
71107 [clause .sql () for clause in self .from_clause_list ]
72108 )
@@ -118,19 +154,27 @@ class FromItem(abc.SQLSyntax):
118154 as_alias : typing .Optional [AsAlias ] = None
119155
120156 @classmethod
121- def from_table_ref (
157+ def from_source (
122158 cls ,
123- table_ref : bigquery .TableReference ,
159+ subquery_or_tableref : typing . Union [ bigquery .TableReference , str ] ,
124160 as_alias : typing .Optional [AsAlias ] = None ,
125161 ):
126- return cls (
127- expression = expr .TableExpression (
128- table_id = table_ref .table_id ,
129- dataset_id = table_ref .dataset_id ,
130- project_id = table_ref .project ,
131- ),
132- as_alias = as_alias ,
133- )
162+ if isinstance (subquery_or_tableref , bigquery .TableReference ):
163+ return cls (
164+ expression = expr .TableExpression (
165+ table_id = subquery_or_tableref .table_id ,
166+ dataset_id = subquery_or_tableref .dataset_id ,
167+ project_id = subquery_or_tableref .project ,
168+ ),
169+ as_alias = as_alias ,
170+ )
171+ elif isinstance (subquery_or_tableref , str ):
172+ return cls (
173+ expression = subquery_or_tableref ,
174+ as_alias = as_alias ,
175+ )
176+ else :
177+ raise ValueError ("The source must be bigquery.TableReference or str." )
134178
135179 def sql (self ) -> str :
136180 if isinstance (self .expression , (expr .TableExpression , expr .CTEExpression )):
0 commit comments