7
7
import dbt .clients .agate_helper
8
8
9
9
from dbt import ui # type: ignore
10
- from dbt .adapters .base import BaseAdapter , available , RelationType , SchemaSearchMap , AdapterConfig
10
+ from dbt .adapters .base import (
11
+ BaseAdapter ,
12
+ available ,
13
+ RelationType ,
14
+ SchemaSearchMap ,
15
+ AdapterConfig ,
16
+ )
11
17
from dbt .adapters .bigquery .relation import BigQueryRelation
12
18
from dbt .adapters .bigquery import BigQueryColumn
13
19
from dbt .adapters .bigquery import BigQueryConnectionManager
@@ -47,11 +53,15 @@ class PartitionConfig(dbtClassMixin):
47
53
data_type : str = "date"
48
54
granularity : str = "day"
49
55
range : Optional [Dict [str , Any ]] = None
56
+ time_ingestion_partitioning : bool = False
57
+
58
+ def reject_partition_field_column (self , columns : List [Any ]) -> List [str ]:
59
+ return [c for c in columns if not c .name .upper () == self .field .upper ()]
50
60
51
61
def render (self , alias : Optional [str ] = None ):
52
- column : str = self .field
62
+ column : str = self .field if not self . time_ingestion_partitioning else "_PARTITIONTIME"
53
63
if alias :
54
- column = f"{ alias } .{ self . field } "
64
+ column = f"{ alias } .{ column } "
55
65
56
66
if self .data_type .lower () == "int64" or (
57
67
self .data_type .lower () == "date" and self .granularity .lower () == "day"
@@ -89,7 +99,11 @@ def render(self):
89
99
90
100
def _stub_relation (* args , ** kwargs ):
91
101
return BigQueryRelation .create (
92
- database = "" , schema = "" , identifier = "" , quote_policy = {}, type = BigQueryRelation .Table
102
+ database = "" ,
103
+ schema = "" ,
104
+ identifier = "" ,
105
+ quote_policy = {},
106
+ type = BigQueryRelation .Table ,
93
107
)
94
108
95
109
@@ -209,14 +223,22 @@ def check_schema_exists(self, database: str, schema: str) -> bool:
209
223
def get_columns_in_relation (self , relation : BigQueryRelation ) -> List [BigQueryColumn ]:
210
224
try :
211
225
table = self .connections .get_bq_table (
212
- database = relation .database , schema = relation .schema , identifier = relation .identifier
226
+ database = relation .database ,
227
+ schema = relation .schema ,
228
+ identifier = relation .identifier ,
213
229
)
214
230
return self ._get_dbt_columns_from_bq_table (table )
215
231
216
232
except (ValueError , google .cloud .exceptions .NotFound ) as e :
217
233
logger .debug ("get_columns_in_relation error: {}" .format (e ))
218
234
return []
219
235
236
+ @available .parse (lambda * a , ** k : [])
237
+ def add_time_ingestion_partition_column (self , columns ) -> List [BigQueryColumn ]:
238
+ "Add time ingestion partition column to columns list"
239
+ columns .append (self .Column ("_PARTITIONTIME" , "TIMESTAMP" , None , "NULLABLE" ))
240
+ return columns
241
+
220
242
def expand_column_types (self , goal : BigQueryRelation , current : BigQueryRelation ) -> None : # type: ignore[override]
221
243
# This is a no-op on BigQuery
222
244
pass
@@ -358,7 +380,10 @@ def _materialize_as_view(self, model: Dict[str, Any]) -> str:
358
380
359
381
logger .debug ("Model SQL ({}):\n {}" .format (model_alias , model_sql ))
360
382
self .connections .create_view (
361
- database = model_database , schema = model_schema , table_name = model_alias , sql = model_sql
383
+ database = model_database ,
384
+ schema = model_schema ,
385
+ table_name = model_alias ,
386
+ sql = model_sql ,
362
387
)
363
388
return "CREATE VIEW"
364
389
@@ -379,7 +404,10 @@ def _materialize_as_table(
379
404
380
405
logger .debug ("Model SQL ({}):\n {}" .format (table_name , model_sql ))
381
406
self .connections .create_table (
382
- database = model_database , schema = model_schema , table_name = table_name , sql = model_sql
407
+ database = model_database ,
408
+ schema = model_schema ,
409
+ table_name = table_name ,
410
+ sql = model_sql ,
383
411
)
384
412
385
413
return "CREATE TABLE"
@@ -462,7 +490,8 @@ def _partitions_match(self, table, conf_partition: Optional[PartitionConfig]) ->
462
490
if not is_partitioned and not conf_partition :
463
491
return True
464
492
elif conf_partition and table .time_partitioning is not None :
465
- table_field = table .time_partitioning .field .lower ()
493
+ partioning_field = table .time_partitioning .field or "_PARTITIONTIME"
494
+ table_field = partioning_field .lower ()
466
495
table_granularity = table .partitioning_type .lower ()
467
496
return (
468
497
table_field == conf_partition .field .lower ()
@@ -508,7 +537,9 @@ def is_replaceable(
508
537
509
538
try :
510
539
table = self .connections .get_bq_table (
511
- database = relation .database , schema = relation .schema , identifier = relation .identifier
540
+ database = relation .database ,
541
+ schema = relation .schema ,
542
+ identifier = relation .identifier ,
512
543
)
513
544
except google .cloud .exceptions .NotFound :
514
545
return True
@@ -630,7 +661,12 @@ def load_dataframe(self, database, schema, table_name, agate_table, column_overr
630
661
631
662
@available .parse_none
632
663
def upload_file (
633
- self , local_file_path : str , database : str , table_schema : str , table_name : str , ** kwargs
664
+ self ,
665
+ local_file_path : str ,
666
+ database : str ,
667
+ table_schema : str ,
668
+ table_name : str ,
669
+ ** kwargs ,
634
670
) -> None :
635
671
conn = self .connections .get_thread_connection ()
636
672
client = conn .handle
0 commit comments