@@ -76,6 +76,11 @@ class Dialect(BaseDialect):
7676 }
7777 TYPE_ARRAY_RE = re .compile (r"ARRAY<(.+)>" )
7878 TYPE_STRUCT_RE = re .compile (r"STRUCT<(.+)>" )
79+ # [BIG]NUMERIC, [BIG]NUMERIC(precision, scale), [BIG]NUMERIC(precision)
80+ TYPE_NUMERIC_RE = re .compile (r"^((BIG)?NUMERIC)(?:\((\d+)(?:, (\d+))?\))?$" )
81+ # https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#parameterized_decimal_type
82+ # The default scale is 9, which means a number can have up to 9 digits after the decimal point.
83+ DEFAULT_NUMERIC_PRECISION = 9
7984
8085 def random (self ) -> str :
8186 return "RAND()"
@@ -94,21 +99,43 @@ def type_repr(self, t) -> str:
9499
95100 def parse_type (self , table_path : DbPath , info : RawColumnInfo ) -> ColType :
96101 col_type = super ().parse_type (table_path , info )
97- if isinstance (col_type , UnknownColType ):
98- m = self .TYPE_ARRAY_RE .fullmatch (info .data_type )
99- if m :
100- item_info = attrs .evolve (info , data_type = m .group (1 ))
101- item_type = self .parse_type (table_path , item_info )
102- col_type = Array (item_type = item_type )
103-
104- # We currently ignore structs' structure, but later can parse it too. Examples:
105- # - STRUCT<INT64, STRING(10)> (unnamed)
106- # - STRUCT<foo INT64, bar STRING(10)> (named)
107- # - STRUCT<foo INT64, bar ARRAY<INT64>> (with complex fields)
108- # - STRUCT<foo INT64, bar STRUCT<a INT64, b INT64>> (nested)
109- m = self .TYPE_STRUCT_RE .fullmatch (info .data_type )
110- if m :
111- col_type = Struct ()
102+ if not isinstance (col_type , UnknownColType ):
103+ return col_type
104+
105+ m = self .TYPE_ARRAY_RE .fullmatch (info .data_type )
106+ if m :
107+ item_info = attrs .evolve (info , data_type = m .group (1 ))
108+ item_type = self .parse_type (table_path , item_info )
109+ col_type = Array (item_type = item_type )
110+ return col_type
111+
112+ # We currently ignore structs' structure, but later can parse it too. Examples:
113+ # - STRUCT<INT64, STRING(10)> (unnamed)
114+ # - STRUCT<foo INT64, bar STRING(10)> (named)
115+ # - STRUCT<foo INT64, bar ARRAY<INT64>> (with complex fields)
116+ # - STRUCT<foo INT64, bar STRUCT<a INT64, b INT64>> (nested)
117+ m = self .TYPE_STRUCT_RE .fullmatch (info .data_type )
118+ if m :
119+ col_type = Struct ()
120+ return col_type
121+
122+ m = self .TYPE_NUMERIC_RE .fullmatch (info .data_type )
123+ if m :
124+ precision = int (m .group (3 )) if m .group (3 ) else None
125+ scale = int (m .group (4 )) if m .group (4 ) else None
126+
127+ if scale is not None :
128+ # NUMERIC(..., scale) — scale is set explicitly
129+ effective_precision = scale
130+ elif precision is not None :
131+ # NUMERIC(...) — scale is missing but precision is set
132+ # effectively the same as NUMERIC(..., 0)
133+ effective_precision = 0
134+ else :
135+ # NUMERIC → default scale is 9
136+ effective_precision = 9
137+ col_type = Decimal (precision = effective_precision )
138+ return col_type
112139
113140 return col_type
114141
0 commit comments