omnata-plugin-runtime 0.11.0a313__py3-none-any.whl → 0.11.0a314__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -470,10 +470,20 @@ class SnowflakeViewPart(BaseModel):
470
470
  c.name_with_comment(binding_list) for c in self.columns
471
471
  ]
472
472
 
473
- def cte_text(self,original_name: bool = False, include_only_columns:Optional[List[str]] = None) -> str:
473
+ def cte_text(self,original_name: bool = False,
474
+ include_only_columns:Optional[List[str]] = None,
475
+ include_extra_columns:Optional[List[str]] = None
476
+ ) -> str:
474
477
  """
475
478
  Returns the CTE text for this view part.
476
479
  """
480
+ if include_extra_columns is not None:
481
+ # includes direct columns plus any extra specified
482
+ return f""" "{self.stream_name}" as (
483
+ select {', '.join([c.definition(original_name=original_name,remove_stream_prefix=self.stream_name) for c in self.columns
484
+ if c.original_name in include_extra_columns or not c.is_join_column])}
485
+ from {self.raw_table_location.get_fully_qualified_name()}
486
+ ) """
477
487
  if include_only_columns is None:
478
488
  return f""" "{self.stream_name}" as (
479
489
  select {', '.join([c.definition(original_name=original_name,remove_stream_prefix=self.stream_name) for c in self.direct_columns()])}
@@ -504,6 +514,29 @@ class SnowflakeViewParts(BaseModel):
504
514
  ..., description="The other streams that are joined to the main stream"
505
515
  )
506
516
 
517
+ def column_indirectly_references_other_streams(
518
+ self,
519
+ all_view_parts:List[SnowflakeViewPart],
520
+ stream_name:str,column_name:str) -> bool:
521
+
522
+ for part in all_view_parts:
523
+ if part.stream_name == stream_name:
524
+ for col in part.columns:
525
+ if col.original_name == column_name:
526
+ if col.referenced_columns:
527
+ for ref_stream, ref_cols in col.referenced_columns.items():
528
+ if ref_stream != stream_name:
529
+ return True
530
+ else:
531
+ # we have to call this recursively in case the referenced column also references other streams
532
+ result = any(
533
+ self.column_indirectly_references_other_streams(
534
+ all_view_parts, ref_stream, ref_col
535
+ ) for ref_col in ref_cols
536
+ )
537
+ return result
538
+ return False
539
+
507
540
  def view_body(self):
508
541
  """
509
542
  Creates a view definition from the parts.
@@ -519,31 +552,40 @@ class SnowflakeViewParts(BaseModel):
519
552
 
520
553
  # first, we need to collapse all referenced columns into a single map
521
554
  all_referenced_columns:Dict[str,List[str]] = {}
555
+
556
+ # if a column references other columns, but there are no dependencies outside of its own stream, we can include those columns in the initial CTE for that stream
557
+ # because they can be calculated directly without needing joins
558
+ columns_only_referencing_own_stream:Dict[str,List[str]] = {}
559
+
560
+
522
561
  for part in [self.main_part] + self.joined_parts:
523
- # if the main part references any columns in this part in its joins, we need to include those columns
562
+ # if the main part references any columns in this part in its joins, we need to include those columns because they are used in the join condition
524
563
  aliases_for_stream = [j.join_stream_alias for j in self.main_part.joins
525
564
  if j.join_stream_name == part.stream_name]
526
565
  columns_used_in_joins = [
527
566
  j.left_column for j in self.main_part.joins if j.left_alias in aliases_for_stream
528
567
  ]
529
- if part.stream_name not in all_referenced_columns:
530
- all_referenced_columns[part.stream_name] = []
531
- all_referenced_columns[part.stream_name] += columns_used_in_joins
568
+ all_referenced_columns.setdefault(part.stream_name, []).extend(columns_used_in_joins)
569
+ # now, for each column in the part, if it references columns in other streams, we need to include those columns
532
570
  for column in part.columns:
533
571
  if column.referenced_columns:
534
572
  for stream_name, referenced_columns in column.referenced_columns.items():
535
- if stream_name not in all_referenced_columns:
536
- all_referenced_columns[stream_name] = []
537
- all_referenced_columns[stream_name] += referenced_columns
573
+ all_referenced_columns.setdefault(stream_name, []).extend(referenced_columns)
574
+ # populate columns_only_referencing_own_stream by following the chain of references until we reach a column that references another stream or has no references
575
+ if self.column_indirectly_references_other_streams(
576
+ [self.main_part] + self.joined_parts, part.stream_name, column.original_name
577
+ ) == False:
578
+ columns_only_referencing_own_stream.setdefault(part.stream_name, []).append(column.original_name)
579
+ else:
580
+ # if the column has no references, it can be included in the initial CTE for its own stream
581
+ columns_only_referencing_own_stream.setdefault(part.stream_name, []).append(column.original_name)
582
+ # if this part has joins to other streams, we need to include the join columns
538
583
  for join in part.joins:
539
- if join.join_stream_name not in all_referenced_columns:
540
- all_referenced_columns[join.join_stream_name] = []
541
- all_referenced_columns[join.join_stream_name].append(join.join_stream_column)
542
- all_referenced_columns[part.stream_name].append(join.left_column)
543
-
584
+ all_referenced_columns.setdefault(join.join_stream_name, []).append(join.join_stream_column)
585
+ all_referenced_columns.setdefault(part.stream_name, []).append(join.left_column)
544
586
 
545
587
  ctes = [
546
- self.main_part.cte_text(original_name=True)
588
+ self.main_part.cte_text(original_name=True,include_extra_columns=columns_only_referencing_own_stream.get(self.main_part.stream_name))
547
589
  ] + [
548
590
  part.cte_text(original_name=True,include_only_columns=all_referenced_columns.get(part.stream_name))
549
591
  for part in joined_parts_deduped
@@ -553,9 +595,9 @@ class SnowflakeViewParts(BaseModel):
553
595
  final_cte = f""" OMNATA_FINAL_CTE as (
554
596
  select {', '.join(
555
597
  [
556
- f'"{self.main_part.stream_name}"."{c.original_name}"' for c in self.main_part.direct_columns()
598
+ f'"{self.main_part.stream_name}"."{c.original_name}"' for c in self.main_part.columns if not c.is_join_column or c.original_name in columns_only_referencing_own_stream.get(self.main_part.stream_name,[])
557
599
  ]+[
558
- c.definition(original_name=True) for c in self.main_part.join_columns()
600
+ c.definition(original_name=True) for c in self.main_part.columns if c.is_join_column and c.original_name not in columns_only_referencing_own_stream.get(self.main_part.stream_name,[])
559
601
  ])}
560
602
  from "{self.main_part.stream_name}" """
561
603
  if len(self.main_part.joins) > 0:
@@ -761,6 +803,19 @@ class SnowflakeViewParts(BaseModel):
761
803
 
762
804
  return cls(main_part=main_stream_view_part, joined_parts=joined_parts)
763
805
 
806
+
807
+ # Helper function to find a view part by stream name
808
+ def find_part(view_part: SnowflakeViewPart, joined_parts: List[SnowflakeViewPart], stream_name: str) -> Optional[SnowflakeViewPart]:
809
+ if stream_name == view_part.stream_name:
810
+ return view_part
811
+ for part in joined_parts:
812
+ if part.stream_name == stream_name:
813
+ return part
814
+ for join in view_part.joins:
815
+ if join.join_stream_alias == stream_name:
816
+ return view_part
817
+ return None
818
+
764
819
  def prune(view_part: SnowflakeViewPart, joined_parts: List[SnowflakeViewPart]) -> bool:
765
820
  """
766
821
  Prunes columns from view parts that reference fields that don't exist in the referenced streams.
@@ -773,12 +828,6 @@ def prune(view_part: SnowflakeViewPart, joined_parts: List[SnowflakeViewPart]) -
773
828
  Raises ValueError if a cyclic dependency is detected.
774
829
  """
775
830
  columns_removed = False
776
-
777
- # Helper function to find a view part by stream name
778
- def find_part(stream_name: str) -> Optional[SnowflakeViewPart]:
779
- if stream_name == view_part.stream_name:
780
- return view_part
781
- return next((p for p in joined_parts if p.stream_name == stream_name), None)
782
831
 
783
832
  # Helper function to check if a column should be kept or removed
784
833
  def should_keep_column(column: SnowflakeViewColumn, part: SnowflakeViewPart) -> bool:
@@ -793,7 +842,7 @@ def prune(view_part: SnowflakeViewPart, joined_parts: List[SnowflakeViewPart]) -
793
842
  # Check each referenced stream and its fields
794
843
  for ref_stream_name, ref_fields in column.referenced_columns.items():
795
844
  # Find the referenced part
796
- ref_part = find_part(ref_stream_name)
845
+ ref_part = find_part(view_part, joined_parts,ref_stream_name)
797
846
 
798
847
  # If referenced stream doesn't exist, remove the column
799
848
  if ref_part is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: omnata-plugin-runtime
3
- Version: 0.11.0a313
3
+ Version: 0.11.0a314
4
4
  Summary: Classes and common runtime components for building and running Omnata Plugins
5
5
  Author: James Weakley
6
6
  Author-email: james.weakley@omnata.com
@@ -2,12 +2,12 @@ omnata_plugin_runtime/__init__.py,sha256=MS9d1whnfT_B3-ThqZ7l63QeC_8OEKTuaYV5wTw
2
2
  omnata_plugin_runtime/api.py,sha256=5gbjbnFy72Xjf0E3kbG23G0V2J3CorvD5kpBn_BkdlI,8084
3
3
  omnata_plugin_runtime/configuration.py,sha256=SffokJfgvy6V3kUsoEjXcK3GdNgHo6U3mgBEs0qBv4I,46972
4
4
  omnata_plugin_runtime/forms.py,sha256=Lrbr3otsFDrvHWJw7v-slsW4PvEHJ6BG1Yl8oaJfiDo,20529
5
- omnata_plugin_runtime/json_schema.py,sha256=xI5YeoxdV1e4fYLUYB-1ZGXZrLAIrSnKj91189wf8cQ,49943
5
+ omnata_plugin_runtime/json_schema.py,sha256=w_4bnxZMzqRCzEUQi02ZlKOOyQ5CU71A_vTipw0XPBE,53191
6
6
  omnata_plugin_runtime/logging.py,sha256=WBuZt8lF9E5oFWM4KYQbE8dDJ_HctJ1pN3BHwU6rcd0,4461
7
7
  omnata_plugin_runtime/omnata_plugin.py,sha256=PV1BzsqI2yi3pd6DBSRc1s1QJ_My-b6pewrB7ad4sms,140256
8
8
  omnata_plugin_runtime/plugin_entrypoints.py,sha256=_1pDLov3iQorGmfcae8Sw2bVjxw1vYeowBaKKNzRclQ,32629
9
9
  omnata_plugin_runtime/rate_limiting.py,sha256=qpr5esU4Ks8hMzuMpSR3gLFdor2ZUXYWCjmsQH_K6lQ,25882
10
- omnata_plugin_runtime-0.11.0a313.dist-info/LICENSE,sha256=rGaMQG3R3F5-JGDp_-rlMKpDIkg5n0SI4kctTk8eZSI,56
11
- omnata_plugin_runtime-0.11.0a313.dist-info/METADATA,sha256=cKUI7DscZ7fka1sfOEUJ0T9p3usHMohmiuBc9TPVM-E,2211
12
- omnata_plugin_runtime-0.11.0a313.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
13
- omnata_plugin_runtime-0.11.0a313.dist-info/RECORD,,
10
+ omnata_plugin_runtime-0.11.0a314.dist-info/LICENSE,sha256=rGaMQG3R3F5-JGDp_-rlMKpDIkg5n0SI4kctTk8eZSI,56
11
+ omnata_plugin_runtime-0.11.0a314.dist-info/METADATA,sha256=yxlKyBrmjoHXXptlv4EeZG5_AhqN4tJZ3SuZjmJ6SFs,2211
12
+ omnata_plugin_runtime-0.11.0a314.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
13
+ omnata_plugin_runtime-0.11.0a314.dist-info/RECORD,,