snowpark-connect 0.32.0__py3-none-any.whl → 0.33.0__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.
Potentially problematic release.
This version of snowpark-connect might be problematic. Click here for more details.
- snowflake/snowpark_connect/column_name_handler.py +92 -27
- snowflake/snowpark_connect/column_qualifier.py +0 -4
- snowflake/snowpark_connect/expression/hybrid_column_map.py +5 -4
- snowflake/snowpark_connect/expression/map_sql_expression.py +12 -4
- snowflake/snowpark_connect/expression/map_unresolved_attribute.py +58 -21
- snowflake/snowpark_connect/expression/map_unresolved_function.py +62 -27
- snowflake/snowpark_connect/includes/python/pyspark/pandas/spark/__init__.py +16 -0
- snowflake/snowpark_connect/includes/python/pyspark/pandas/spark/accessors.py +1281 -0
- snowflake/snowpark_connect/includes/python/pyspark/pandas/spark/functions.py +203 -0
- snowflake/snowpark_connect/includes/python/pyspark/pandas/spark/utils.py +202 -0
- snowflake/snowpark_connect/relation/map_aggregate.py +2 -4
- snowflake/snowpark_connect/relation/map_column_ops.py +5 -0
- snowflake/snowpark_connect/relation/map_join.py +218 -146
- snowflake/snowpark_connect/relation/map_row_ops.py +136 -54
- snowflake/snowpark_connect/relation/map_sql.py +102 -16
- snowflake/snowpark_connect/relation/read/map_read_json.py +87 -2
- snowflake/snowpark_connect/relation/utils.py +46 -0
- snowflake/snowpark_connect/relation/write/map_write.py +186 -275
- snowflake/snowpark_connect/resources_initializer.py +25 -13
- snowflake/snowpark_connect/server.py +9 -24
- snowflake/snowpark_connect/type_mapping.py +2 -0
- snowflake/snowpark_connect/typed_column.py +2 -2
- snowflake/snowpark_connect/utils/sequence.py +21 -0
- snowflake/snowpark_connect/utils/session.py +8 -1
- snowflake/snowpark_connect/version.py +1 -1
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/METADATA +3 -1
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/RECORD +35 -93
- snowflake/snowpark_connect/includes/jars/antlr4-runtime-4.9.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-cli-1.5.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-codec-1.16.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-collections-3.2.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-collections4-4.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-compiler-3.1.9.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-compress-1.26.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-crypto-1.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-dbcp-1.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-io-2.16.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-lang-2.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-lang3-3.12.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-logging-1.1.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-math3-3.6.1.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-pool-1.5.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/commons-text-1.10.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/hadoop-client-api-trimmed-3.3.4.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-annotations-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-core-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-core-asl-1.9.13.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-databind-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-dataformat-yaml-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-datatype-jsr310-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/jackson-module-scala_2.12-2.15.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-ast_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-core_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-jackson_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-native_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/json4s-scalap_2.12-3.7.0-M11.jar +0 -0
- snowflake/snowpark_connect/includes/jars/kryo-shaded-4.0.2.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-1.2-api-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-api-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-core-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/log4j-slf4j2-impl-2.20.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/paranamer-2.8.3.jar +0 -0
- snowflake/snowpark_connect/includes/jars/paranamer-2.8.jar +0 -0
- snowflake/snowpark_connect/includes/jars/sas-scala-udf_2.12-0.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-collection-compat_2.12-2.7.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-library-2.12.18.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-parser-combinators_2.12-2.3.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-reflect-2.12.18.jar +0 -0
- snowflake/snowpark_connect/includes/jars/scala-xml_2.12-2.1.0.jar +0 -0
- snowflake/snowpark_connect/includes/jars/slf4j-api-2.0.7.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-catalyst_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-common-utils_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-connect-client-jvm_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-core_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-graphx_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-hive-thriftserver_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-hive_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-kvstore_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-launcher_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-mesos_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-mllib-local_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-network-common_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-network-shuffle_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-repl_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-sketch_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-sql-api_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-sql_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-tags_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-unsafe_2.12-3.5.6.jar +0 -0
- snowflake/snowpark_connect/includes/jars/spark-yarn_2.12-3.5.6.jar +0 -0
- {snowpark_connect-0.32.0.data → snowpark_connect-0.33.0.data}/scripts/snowpark-connect +0 -0
- {snowpark_connect-0.32.0.data → snowpark_connect-0.33.0.data}/scripts/snowpark-session +0 -0
- {snowpark_connect-0.32.0.data → snowpark_connect-0.33.0.data}/scripts/snowpark-submit +0 -0
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/WHEEL +0 -0
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/licenses/LICENSE-binary +0 -0
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/licenses/LICENSE.txt +0 -0
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/licenses/NOTICE-binary +0 -0
- {snowpark_connect-0.32.0.dist-info → snowpark_connect-0.33.0.dist-info}/top_level.txt +0 -0
|
@@ -117,6 +117,57 @@ def _spark_to_snowflake(multipart_id: str) -> str:
|
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
def _validate_table_exist_and_of_type(
|
|
121
|
+
snowpark_table_name: str,
|
|
122
|
+
session: snowpark.Session,
|
|
123
|
+
table_type: str,
|
|
124
|
+
table_schema_or_error: DataType | SnowparkSQLException,
|
|
125
|
+
) -> None:
|
|
126
|
+
if not isinstance(table_schema_or_error, DataType):
|
|
127
|
+
exception = AnalysisException(
|
|
128
|
+
f"[TABLE_OR_VIEW_NOT_FOUND] The table or view `{snowpark_table_name}` cannot be found."
|
|
129
|
+
)
|
|
130
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
131
|
+
raise exception
|
|
132
|
+
_validate_table_type(snowpark_table_name, session, table_type)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _validate_table_type(
|
|
136
|
+
snowpark_table_name: str,
|
|
137
|
+
session: snowpark.Session,
|
|
138
|
+
table_type: str,
|
|
139
|
+
) -> None:
|
|
140
|
+
actual_type = get_table_type(snowpark_table_name, session)
|
|
141
|
+
if table_type == "iceberg":
|
|
142
|
+
if actual_type not in ("ICEBERG", "TABLE"):
|
|
143
|
+
exception = AnalysisException(
|
|
144
|
+
f"Table {snowpark_table_name} is not an iceberg table"
|
|
145
|
+
)
|
|
146
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
147
|
+
raise exception
|
|
148
|
+
elif table_type == "fdn":
|
|
149
|
+
if actual_type not in ("NORMAL", "TABLE"):
|
|
150
|
+
exception = AnalysisException(
|
|
151
|
+
f"Table {snowpark_table_name} is not a FDN table"
|
|
152
|
+
)
|
|
153
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
154
|
+
raise exception
|
|
155
|
+
else:
|
|
156
|
+
raise ValueError(
|
|
157
|
+
f"Invalid table_type: {table_type}. Must be 'iceberg' or 'fdn'"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _validate_table_does_not_exist(
|
|
162
|
+
snowpark_table_name: str,
|
|
163
|
+
table_schema_or_error: DataType | SnowparkSQLException,
|
|
164
|
+
) -> None:
|
|
165
|
+
if isinstance(table_schema_or_error, DataType):
|
|
166
|
+
exception = AnalysisException(f"Table {snowpark_table_name} already exists")
|
|
167
|
+
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
168
|
+
raise exception
|
|
169
|
+
|
|
170
|
+
|
|
120
171
|
def map_write(request: proto_base.ExecutePlanRequest):
|
|
121
172
|
write_op = request.plan.command.write_operation
|
|
122
173
|
telemetry.report_io_write(write_op.source)
|
|
@@ -240,7 +291,6 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
240
291
|
"format_type_options": {
|
|
241
292
|
"COMPRESSION": compression,
|
|
242
293
|
},
|
|
243
|
-
"overwrite": overwrite,
|
|
244
294
|
}
|
|
245
295
|
# Download from the base write path to ensure we fetch whatever Snowflake produced.
|
|
246
296
|
# Using the base avoids coupling to exact filenames/prefixes.
|
|
@@ -347,14 +397,9 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
347
397
|
table_schema_or_error = _get_table_schema_or_error(
|
|
348
398
|
snowpark_table_name, session
|
|
349
399
|
)
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
)
|
|
354
|
-
attach_custom_error_code(
|
|
355
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
356
|
-
)
|
|
357
|
-
raise exception
|
|
400
|
+
_validate_table_does_not_exist(
|
|
401
|
+
snowpark_table_name, table_schema_or_error
|
|
402
|
+
)
|
|
358
403
|
create_iceberg_table(
|
|
359
404
|
snowpark_table_name=snowpark_table_name,
|
|
360
405
|
location=write_op.options.get("location", None),
|
|
@@ -373,17 +418,7 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
373
418
|
snowpark_table_name, session
|
|
374
419
|
)
|
|
375
420
|
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
376
|
-
|
|
377
|
-
"ICEBERG",
|
|
378
|
-
"TABLE",
|
|
379
|
-
):
|
|
380
|
-
exception = AnalysisException(
|
|
381
|
-
f"Table {snowpark_table_name} is not an iceberg table"
|
|
382
|
-
)
|
|
383
|
-
attach_custom_error_code(
|
|
384
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
385
|
-
)
|
|
386
|
-
raise exception
|
|
421
|
+
_validate_table_type(snowpark_table_name, session, "iceberg")
|
|
387
422
|
else:
|
|
388
423
|
create_iceberg_table(
|
|
389
424
|
snowpark_table_name=snowpark_table_name,
|
|
@@ -423,29 +458,25 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
423
458
|
snowpark_table_name, session
|
|
424
459
|
)
|
|
425
460
|
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
435
|
-
)
|
|
436
|
-
raise exception
|
|
461
|
+
_validate_table_type(snowpark_table_name, session, "iceberg")
|
|
462
|
+
create_iceberg_table(
|
|
463
|
+
snowpark_table_name=snowpark_table_name,
|
|
464
|
+
location=write_op.options.get("location", None),
|
|
465
|
+
schema=input_df.schema,
|
|
466
|
+
snowpark_session=session,
|
|
467
|
+
mode="replace",
|
|
468
|
+
)
|
|
437
469
|
else:
|
|
438
470
|
create_iceberg_table(
|
|
439
471
|
snowpark_table_name=snowpark_table_name,
|
|
440
472
|
location=write_op.options.get("location", None),
|
|
441
473
|
schema=input_df.schema,
|
|
442
474
|
snowpark_session=session,
|
|
475
|
+
mode="create",
|
|
443
476
|
)
|
|
444
|
-
|
|
445
|
-
input_df, "truncate", snowpark_table_name, table_schema_or_error
|
|
446
|
-
).saveAsTable(
|
|
477
|
+
_get_writer_for_table_creation(input_df).saveAsTable(
|
|
447
478
|
table_name=snowpark_table_name,
|
|
448
|
-
mode="
|
|
479
|
+
mode="append",
|
|
449
480
|
column_order=_column_order_for_write,
|
|
450
481
|
)
|
|
451
482
|
case _:
|
|
@@ -491,18 +522,9 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
491
522
|
snowpark_table_name, session
|
|
492
523
|
)
|
|
493
524
|
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
):
|
|
498
|
-
exception = AnalysisException(
|
|
499
|
-
f"Table {snowpark_table_name} is not a FDN table"
|
|
500
|
-
)
|
|
501
|
-
attach_custom_error_code(
|
|
502
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
503
|
-
)
|
|
504
|
-
raise exception
|
|
505
|
-
write_mode = "truncate"
|
|
525
|
+
_validate_table_type(snowpark_table_name, session, "fdn")
|
|
526
|
+
|
|
527
|
+
write_mode = "overwrite"
|
|
506
528
|
_validate_schema_and_get_writer(
|
|
507
529
|
input_df,
|
|
508
530
|
write_mode,
|
|
@@ -511,27 +533,15 @@ def map_write(request: proto_base.ExecutePlanRequest):
|
|
|
511
533
|
).saveAsTable(
|
|
512
534
|
table_name=snowpark_table_name,
|
|
513
535
|
mode=write_mode,
|
|
536
|
+
copy_grants=True,
|
|
514
537
|
column_order=_column_order_for_write,
|
|
515
538
|
)
|
|
516
539
|
case "append":
|
|
517
540
|
table_schema_or_error = _get_table_schema_or_error(
|
|
518
541
|
snowpark_table_name, session
|
|
519
542
|
)
|
|
520
|
-
if isinstance(
|
|
521
|
-
|
|
522
|
-
) and get_table_type( # Table exists
|
|
523
|
-
snowpark_table_name, session
|
|
524
|
-
) not in (
|
|
525
|
-
"NORMAL",
|
|
526
|
-
"TABLE",
|
|
527
|
-
):
|
|
528
|
-
exception = AnalysisException(
|
|
529
|
-
f"Table {snowpark_table_name} is not a FDN table"
|
|
530
|
-
)
|
|
531
|
-
attach_custom_error_code(
|
|
532
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
533
|
-
)
|
|
534
|
-
raise exception
|
|
543
|
+
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
544
|
+
_validate_table_type(snowpark_table_name, session, "fdn")
|
|
535
545
|
|
|
536
546
|
_validate_schema_and_get_writer(
|
|
537
547
|
input_df,
|
|
@@ -598,113 +608,105 @@ def map_write_v2(request: proto_base.ExecutePlanRequest):
|
|
|
598
608
|
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
599
609
|
raise exception
|
|
600
610
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
raise exception
|
|
611
|
+
is_iceberg = write_op.provider.lower() == "iceberg"
|
|
612
|
+
table_type = "iceberg" if is_iceberg else "fdn"
|
|
613
|
+
|
|
614
|
+
match write_op.mode:
|
|
615
|
+
case commands_proto.WriteOperationV2.MODE_CREATE:
|
|
616
|
+
table_schema_or_error = _get_table_schema_or_error(
|
|
617
|
+
snowpark_table_name, session
|
|
618
|
+
)
|
|
619
|
+
_validate_table_does_not_exist(snowpark_table_name, table_schema_or_error)
|
|
620
|
+
|
|
621
|
+
if is_iceberg:
|
|
613
622
|
create_iceberg_table(
|
|
614
623
|
snowpark_table_name=snowpark_table_name,
|
|
615
624
|
location=write_op.table_properties.get("location"),
|
|
616
625
|
schema=input_df.schema,
|
|
617
626
|
snowpark_session=session,
|
|
618
627
|
)
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
)
|
|
657
|
-
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
658
|
-
if get_table_type(snowpark_table_name, session) not in (
|
|
659
|
-
"ICEBERG",
|
|
660
|
-
"TABLE",
|
|
661
|
-
):
|
|
662
|
-
exception = AnalysisException(
|
|
663
|
-
f"Table {snowpark_table_name} is not an iceberg table"
|
|
664
|
-
)
|
|
665
|
-
attach_custom_error_code(
|
|
666
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
667
|
-
)
|
|
668
|
-
raise exception
|
|
669
|
-
else:
|
|
670
|
-
exception = AnalysisException(
|
|
671
|
-
f"[TABLE_OR_VIEW_NOT_FOUND] Table {snowpark_table_name} does not exist"
|
|
672
|
-
)
|
|
673
|
-
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
674
|
-
raise exception
|
|
675
|
-
_validate_schema_and_get_writer(
|
|
676
|
-
input_df, "truncate", snowpark_table_name, table_schema_or_error
|
|
677
|
-
).saveAsTable(
|
|
678
|
-
table_name=snowpark_table_name,
|
|
679
|
-
mode="truncate",
|
|
680
|
-
column_order=_column_order_for_write,
|
|
628
|
+
_get_writer_for_table_creation(input_df).saveAsTable(
|
|
629
|
+
table_name=snowpark_table_name,
|
|
630
|
+
mode="append" if is_iceberg else "errorifexists",
|
|
631
|
+
column_order=_column_order_for_write,
|
|
632
|
+
)
|
|
633
|
+
|
|
634
|
+
case commands_proto.WriteOperationV2.MODE_APPEND:
|
|
635
|
+
table_schema_or_error = _get_table_schema_or_error(
|
|
636
|
+
snowpark_table_name, session
|
|
637
|
+
)
|
|
638
|
+
_validate_table_exist_and_of_type(
|
|
639
|
+
snowpark_table_name, session, table_type, table_schema_or_error
|
|
640
|
+
)
|
|
641
|
+
_validate_schema_and_get_writer(
|
|
642
|
+
input_df, "append", snowpark_table_name, table_schema_or_error
|
|
643
|
+
).saveAsTable(
|
|
644
|
+
table_name=snowpark_table_name,
|
|
645
|
+
mode="append",
|
|
646
|
+
column_order=_column_order_for_write,
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
case commands_proto.WriteOperationV2.MODE_OVERWRITE | commands_proto.WriteOperationV2.MODE_OVERWRITE_PARTITIONS:
|
|
650
|
+
# TODO: handle the filter condition for MODE_OVERWRITE
|
|
651
|
+
table_schema_or_error = _get_table_schema_or_error(
|
|
652
|
+
snowpark_table_name, session
|
|
653
|
+
)
|
|
654
|
+
_validate_table_exist_and_of_type(
|
|
655
|
+
snowpark_table_name, session, table_type, table_schema_or_error
|
|
656
|
+
)
|
|
657
|
+
|
|
658
|
+
if is_iceberg:
|
|
659
|
+
create_iceberg_table(
|
|
660
|
+
snowpark_table_name=snowpark_table_name,
|
|
661
|
+
location=write_op.options.get("location", None),
|
|
662
|
+
schema=input_df.schema,
|
|
663
|
+
snowpark_session=session,
|
|
664
|
+
mode="replace",
|
|
681
665
|
)
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
666
|
+
writer = _get_writer_for_table_creation(input_df)
|
|
667
|
+
save_mode = "append"
|
|
668
|
+
else:
|
|
669
|
+
writer = _validate_schema_and_get_writer(
|
|
670
|
+
input_df, "overwrite", snowpark_table_name, table_schema_or_error
|
|
685
671
|
)
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
672
|
+
save_mode = "overwrite"
|
|
673
|
+
|
|
674
|
+
writer.saveAsTable(
|
|
675
|
+
table_name=snowpark_table_name,
|
|
676
|
+
mode=save_mode,
|
|
677
|
+
column_order=_column_order_for_write,
|
|
678
|
+
)
|
|
679
|
+
|
|
680
|
+
case commands_proto.WriteOperationV2.MODE_REPLACE:
|
|
681
|
+
table_schema_or_error = _get_table_schema_or_error(
|
|
682
|
+
snowpark_table_name, session
|
|
683
|
+
)
|
|
684
|
+
_validate_table_exist_and_of_type(
|
|
685
|
+
snowpark_table_name, session, table_type, table_schema_or_error
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
if is_iceberg:
|
|
689
|
+
create_iceberg_table(
|
|
690
|
+
snowpark_table_name=snowpark_table_name,
|
|
691
|
+
location=write_op.table_properties.get("location"),
|
|
692
|
+
schema=input_df.schema,
|
|
693
|
+
snowpark_session=session,
|
|
694
|
+
mode="replace",
|
|
706
695
|
)
|
|
707
|
-
|
|
696
|
+
save_mode = "append"
|
|
697
|
+
else:
|
|
698
|
+
save_mode = "overwrite"
|
|
699
|
+
|
|
700
|
+
_validate_schema_and_get_writer(
|
|
701
|
+
input_df, "replace", snowpark_table_name, table_schema_or_error
|
|
702
|
+
).saveAsTable(
|
|
703
|
+
table_name=snowpark_table_name,
|
|
704
|
+
mode=save_mode,
|
|
705
|
+
column_order=_column_order_for_write,
|
|
706
|
+
)
|
|
707
|
+
|
|
708
|
+
case commands_proto.WriteOperationV2.MODE_CREATE_OR_REPLACE:
|
|
709
|
+
if is_iceberg:
|
|
708
710
|
create_iceberg_table(
|
|
709
711
|
snowpark_table_name=snowpark_table_name,
|
|
710
712
|
location=write_op.table_properties.get("location"),
|
|
@@ -712,116 +714,24 @@ def map_write_v2(request: proto_base.ExecutePlanRequest):
|
|
|
712
714
|
snowpark_session=session,
|
|
713
715
|
mode="create_or_replace",
|
|
714
716
|
)
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
).saveAsTable(
|
|
734
|
-
table_name=snowpark_table_name,
|
|
735
|
-
mode="errorifexists",
|
|
736
|
-
column_order=_column_order_for_write,
|
|
737
|
-
)
|
|
738
|
-
case commands_proto.WriteOperationV2.MODE_APPEND:
|
|
739
|
-
table_schema_or_error = _get_table_schema_or_error(
|
|
740
|
-
snowpark_table_name, session
|
|
741
|
-
)
|
|
742
|
-
if not isinstance(table_schema_or_error, DataType): # Table not exists
|
|
743
|
-
exception = AnalysisException(
|
|
744
|
-
f"[TABLE_OR_VIEW_NOT_FOUND] The table or view `{write_op.table_name}` cannot be found."
|
|
745
|
-
)
|
|
746
|
-
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
747
|
-
raise exception
|
|
748
|
-
if get_table_type(snowpark_table_name, session) not in (
|
|
749
|
-
"NORMAL",
|
|
750
|
-
"TABLE",
|
|
751
|
-
):
|
|
752
|
-
exception = AnalysisException(
|
|
753
|
-
f"Table {snowpark_table_name} is not a FDN table"
|
|
754
|
-
)
|
|
755
|
-
attach_custom_error_code(exception, ErrorCodes.INVALID_OPERATION)
|
|
756
|
-
raise exception
|
|
757
|
-
_validate_schema_and_get_writer(
|
|
758
|
-
input_df, "append", snowpark_table_name, table_schema_or_error
|
|
759
|
-
).saveAsTable(
|
|
760
|
-
table_name=snowpark_table_name,
|
|
761
|
-
mode="append",
|
|
762
|
-
column_order=_column_order_for_write,
|
|
763
|
-
)
|
|
764
|
-
case commands_proto.WriteOperationV2.MODE_OVERWRITE | commands_proto.WriteOperationV2.MODE_OVERWRITE_PARTITIONS:
|
|
765
|
-
# TODO: handle the filter condition for MODE_OVERWRITE
|
|
766
|
-
table_schema_or_error = _get_table_schema_or_error(
|
|
767
|
-
snowpark_table_name, session
|
|
768
|
-
)
|
|
769
|
-
if isinstance(table_schema_or_error, DataType): # Table exists
|
|
770
|
-
if get_table_type(snowpark_table_name, session) not in (
|
|
771
|
-
"NORMAL",
|
|
772
|
-
"TABLE",
|
|
773
|
-
):
|
|
774
|
-
exception = AnalysisException(
|
|
775
|
-
f"Table {snowpark_table_name} is not a FDN table"
|
|
776
|
-
)
|
|
777
|
-
attach_custom_error_code(
|
|
778
|
-
exception, ErrorCodes.INVALID_OPERATION
|
|
779
|
-
)
|
|
780
|
-
raise exception
|
|
781
|
-
else:
|
|
782
|
-
exception = AnalysisException(
|
|
783
|
-
f"[TABLE_OR_VIEW_NOT_FOUND] Table {snowpark_table_name} does not exist"
|
|
784
|
-
)
|
|
785
|
-
attach_custom_error_code(exception, ErrorCodes.TABLE_NOT_FOUND)
|
|
786
|
-
raise exception
|
|
787
|
-
_validate_schema_and_get_writer(
|
|
788
|
-
input_df, "truncate", snowpark_table_name, table_schema_or_error
|
|
789
|
-
).saveAsTable(
|
|
790
|
-
table_name=snowpark_table_name,
|
|
791
|
-
mode="truncate",
|
|
792
|
-
column_order=_column_order_for_write,
|
|
793
|
-
)
|
|
794
|
-
case commands_proto.WriteOperationV2.MODE_REPLACE:
|
|
795
|
-
table_schema_or_error = _get_table_schema_or_error(
|
|
796
|
-
snowpark_table_name, session
|
|
797
|
-
)
|
|
798
|
-
if not isinstance(table_schema_or_error, DataType): # Table not exists
|
|
799
|
-
exception = AnalysisException(
|
|
800
|
-
f"Table {snowpark_table_name} does not exist"
|
|
801
|
-
)
|
|
802
|
-
attach_custom_error_code(exception, ErrorCodes.TABLE_NOT_FOUND)
|
|
803
|
-
raise exception
|
|
804
|
-
_validate_schema_and_get_writer(
|
|
805
|
-
input_df, "replace", snowpark_table_name, table_schema_or_error
|
|
806
|
-
).saveAsTable(
|
|
807
|
-
table_name=snowpark_table_name,
|
|
808
|
-
mode="overwrite",
|
|
809
|
-
column_order=_column_order_for_write,
|
|
810
|
-
)
|
|
811
|
-
case commands_proto.WriteOperationV2.MODE_CREATE_OR_REPLACE:
|
|
812
|
-
_validate_schema_and_get_writer(
|
|
813
|
-
input_df, "create_or_replace", snowpark_table_name
|
|
814
|
-
).saveAsTable(
|
|
815
|
-
table_name=snowpark_table_name,
|
|
816
|
-
mode="overwrite",
|
|
817
|
-
column_order=_column_order_for_write,
|
|
818
|
-
)
|
|
819
|
-
case _:
|
|
820
|
-
exception = SnowparkConnectNotImplementedError(
|
|
821
|
-
f"Write mode {commands_proto.WriteOperationV2.Mode.Name(write_op.mode)} is not supported"
|
|
822
|
-
)
|
|
823
|
-
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
824
|
-
raise exception
|
|
717
|
+
save_mode = "append"
|
|
718
|
+
else:
|
|
719
|
+
save_mode = "overwrite"
|
|
720
|
+
|
|
721
|
+
_validate_schema_and_get_writer(
|
|
722
|
+
input_df, "create_or_replace", snowpark_table_name
|
|
723
|
+
).saveAsTable(
|
|
724
|
+
table_name=snowpark_table_name,
|
|
725
|
+
mode=save_mode,
|
|
726
|
+
column_order=_column_order_for_write,
|
|
727
|
+
)
|
|
728
|
+
|
|
729
|
+
case _:
|
|
730
|
+
exception = SnowparkConnectNotImplementedError(
|
|
731
|
+
f"Write mode {commands_proto.WriteOperationV2.Mode.Name(write_op.mode)} is not supported"
|
|
732
|
+
)
|
|
733
|
+
attach_custom_error_code(exception, ErrorCodes.UNSUPPORTED_OPERATION)
|
|
734
|
+
raise exception
|
|
825
735
|
|
|
826
736
|
|
|
827
737
|
def _get_table_schema_or_error(
|
|
@@ -856,6 +766,7 @@ def _validate_schema_and_get_writer(
|
|
|
856
766
|
if write_mode is not None and write_mode.lower() in (
|
|
857
767
|
"replace",
|
|
858
768
|
"create_or_replace",
|
|
769
|
+
"overwrite",
|
|
859
770
|
):
|
|
860
771
|
return _get_writer_for_table_creation(input_df)
|
|
861
772
|
|
|
@@ -1053,14 +964,13 @@ def create_iceberg_table(
|
|
|
1053
964
|
if config_external_volume is None or config_external_volume == ""
|
|
1054
965
|
else f"EXTERNAL_VOLUME = '{config_external_volume}'"
|
|
1055
966
|
)
|
|
1056
|
-
|
|
967
|
+
copy_grants = ""
|
|
1057
968
|
match mode:
|
|
1058
969
|
case "create":
|
|
1059
970
|
create_sql = "CREATE"
|
|
1060
|
-
case "replace":
|
|
971
|
+
case "replace" | "create_or_replace":
|
|
1061
972
|
# There's no replace for iceberg table, so we use create or replace
|
|
1062
|
-
|
|
1063
|
-
case "create_or_replace":
|
|
973
|
+
copy_grants = "COPY GRANTS"
|
|
1064
974
|
create_sql = "CREATE OR REPLACE"
|
|
1065
975
|
case _:
|
|
1066
976
|
exception = SnowparkConnectNotImplementedError(
|
|
@@ -1072,7 +982,8 @@ def create_iceberg_table(
|
|
|
1072
982
|
{create_sql} ICEBERG TABLE {snowpark_table_name} ({",".join(table_schema)})
|
|
1073
983
|
CATALOG = 'SNOWFLAKE'
|
|
1074
984
|
{external_volume}
|
|
1075
|
-
{base_location}
|
|
985
|
+
{base_location}
|
|
986
|
+
{copy_grants};
|
|
1076
987
|
"""
|
|
1077
988
|
snowpark_session.sql(sql).collect()
|
|
1078
989
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#
|
|
2
2
|
# Copyright (c) 2012-2025 Snowflake Computing Inc. All rights reserved.
|
|
3
3
|
#
|
|
4
|
-
import pathlib
|
|
5
4
|
import threading
|
|
6
5
|
import time
|
|
7
6
|
|
|
@@ -51,11 +50,9 @@ def initialize_resources() -> None:
|
|
|
51
50
|
"""Upload Spark jar files required for creating Scala UDFs."""
|
|
52
51
|
stage = session.get_session_stage()
|
|
53
52
|
resource_path = stage + RESOURCE_PATH
|
|
54
|
-
import
|
|
53
|
+
import snowpark_connect_deps_1
|
|
54
|
+
import snowpark_connect_deps_2
|
|
55
55
|
|
|
56
|
-
pyspark_jars = (
|
|
57
|
-
pathlib.Path(snowflake.snowpark_connect.__file__).parent / "includes/jars"
|
|
58
|
-
)
|
|
59
56
|
jar_files = [
|
|
60
57
|
f"spark-sql_2.12-{SPARK_VERSION}.jar",
|
|
61
58
|
f"spark-connect-client-jvm_2.12-{SPARK_VERSION}.jar",
|
|
@@ -64,14 +61,29 @@ def initialize_resources() -> None:
|
|
|
64
61
|
"json4s-ast_2.12-3.7.0-M11.jar",
|
|
65
62
|
]
|
|
66
63
|
|
|
67
|
-
for
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
64
|
+
for jar_name in jar_files:
|
|
65
|
+
# Try to find the JAR in package 1 first, then package 2
|
|
66
|
+
jar_path = None
|
|
67
|
+
try:
|
|
68
|
+
jar_path = snowpark_connect_deps_1.get_jar_path(jar_name)
|
|
69
|
+
except FileNotFoundError:
|
|
70
|
+
try:
|
|
71
|
+
jar_path = snowpark_connect_deps_2.get_jar_path(jar_name)
|
|
72
|
+
except FileNotFoundError:
|
|
73
|
+
raise FileNotFoundError(
|
|
74
|
+
f"JAR {jar_name} not found in either package"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
session.file.put(
|
|
79
|
+
str(jar_path),
|
|
80
|
+
resource_path,
|
|
81
|
+
auto_compress=False,
|
|
82
|
+
overwrite=False,
|
|
83
|
+
source_compression="NONE",
|
|
84
|
+
)
|
|
85
|
+
except Exception as e:
|
|
86
|
+
raise RuntimeError(f"Failed to upload JAR {jar_name}: {e}")
|
|
75
87
|
|
|
76
88
|
start_time = time.time()
|
|
77
89
|
|