sqlframe 1.7.0__tar.gz → 1.8.0__tar.gz
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.
- {sqlframe-1.7.0 → sqlframe-1.8.0}/PKG-INFO +1 -1
- sqlframe-1.8.0/blogs/add_chatgpt_support.md +101 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/adding_ai_to_meal.jpeg +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/hype_train.gif +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/marvin_paranoid_robot.gif +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/nonsense_sql.png +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/openai_full_rewrite.png +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/openai_replacing_cte_names.png +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/sqlglot_optimized_code.png +0 -0
- sqlframe-1.8.0/blogs/images/add_chatgpt_support/sunny_shake_head_no.gif +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/spark.md +12 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/setup.py +1 -1
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/_version.py +2 -2
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/functions.py +84 -4
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/session.py +1 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/catalog.py +4 -1
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/functions.py +1 -3
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/functions.pyi +12 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe.egg-info/PKG-INFO +1 -1
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe.egg-info/SOURCES.txt +9 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe.egg-info/requires.txt +1 -1
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/bigquery/test_bigquery_session.py +1 -1
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/test_int_functions.py +205 -7
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_functions.py +116 -7
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.github/CODEOWNERS +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.github/workflows/main.workflow.yaml +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.github/workflows/publish.workflow.yaml +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.gitignore +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.pre-commit-config.yaml +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/.readthedocs.yaml +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/LICENSE +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/Makefile +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/README.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/blogs/images/but_wait_theres_more.gif +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/blogs/images/cake.gif +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/blogs/images/you_get_pyspark_api.gif +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/blogs/sqlframe_universal_dataframe_api.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/bigquery.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/configuration.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/bigquery.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/duckdb.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/images/SF.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/images/favicon.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/images/favicon_old.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/images/sqlframe_diagram.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/images/sqlframe_logo.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/docs/postgres.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/duckdb.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/images/SF.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/images/favicon.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/images/favicon_old.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/images/sqlframe_diagram.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/images/sqlframe_logo.png +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/index.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/postgres.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/requirements.txt +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/snowflake.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/standalone.md +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/docs/stylesheets/extra.css +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/mkdocs.yml +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/pytest.ini +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/renovate.json +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/setup.cfg +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/LICENSE +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/_typing.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/decorators.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/exceptions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/function_alternatives.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/mixins/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/mixins/catalog_mixins.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/mixins/dataframe_mixins.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/mixins/readwriter_mixins.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/normalize.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/operations.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/readerwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/transforms.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/util.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/base/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/functions.pyi +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/bigquery/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/functions.pyi +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/duckdb/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/functions.pyi +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/postgres/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/redshift/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/functions.pyi +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/snowflake/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/spark/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/functions.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/group.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/readwriter.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe/standalone/window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe.egg-info/dependency_links.txt +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/sqlframe.egg-info/top_level.txt +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/common_fixtures.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/conftest.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/fixtures/employee.csv +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/fixtures/employee.json +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/fixtures/employee.parquet +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/fixtures/employee_extra_line.csv +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/bigquery/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/bigquery/test_bigquery_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/duck/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/duck/test_duckdb_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/duck/test_duckdb_dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/duck/test_duckdb_reader.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/duck/test_duckdb_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/postgres/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/postgres/test_postgres_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/postgres/test_postgres_dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/postgres/test_postgres_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/redshift/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/redshift/test_redshift_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/redshift/test_redshift_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/snowflake/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/snowflake/test_snowflake_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/snowflake/test_snowflake_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/spark/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/spark/test_spark_catalog.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/test_engine_dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/test_engine_reader.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/test_engine_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/test_engine_writer.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/fixtures.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/test_int_dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/test_int_dataframe_stats.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/test_int_grouped_data.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/test_int_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/__init__.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/fixtures.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_column.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_dataframe.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_dataframe_writer.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_session.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_session_case_sensitivity.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_types.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/standalone/test_window.py +0 -0
- {sqlframe-1.7.0 → sqlframe-1.8.0}/tests/unit/test_util.py +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Adding ChatGPT to SQLFrame - What is the Right Amount of AI?
|
|
2
|
+
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src="images/add_chatgpt_support/adding_ai_to_meal.jpeg" alt="Adding AI to Meal" width="800"/>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
Like many people today, I often grapple with how much AI to integrate into my daily tasks.
|
|
8
|
+
In my experience, AI can be a valuable tool for brainstorming when writing, but over-reliance on it can lead to generic text devoid of personality.
|
|
9
|
+
While I might be overly verbose and fond of metaphors, these quirks add character and make communication more engaging.
|
|
10
|
+
Take "Marvin the Paranoid Robot" from "Hitchhiker's Guide to the Galaxy," for instance.
|
|
11
|
+
His melancholic outlook makes him relatable to the audience, even though his intelligence is 50,000 times greater than ours.
|
|
12
|
+
|
|
13
|
+
<div align="center">
|
|
14
|
+
<img src="images/add_chatgpt_support/marvin_paranoid_robot.gif" alt="Sad Robot" width="800"/>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
When it comes to coding, I strive to eliminate imperfections as much as possible.
|
|
18
|
+
However, AI's tendency to hallucinate makes even a "trust but verify" approach challenging.
|
|
19
|
+
More often than not, especially when working with new libraries or languages, I find myself in a "that just can't be right, so let's move on" mindset.
|
|
20
|
+
|
|
21
|
+
<div align="center">
|
|
22
|
+
<img src="images/add_chatgpt_support/sunny_shake_head_no.gif" alt="Shake Head No" width="800"/>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
When I first considered integrating AI into SQLFrame, it immediately struck me as a bad idea.
|
|
26
|
+
Correctness and consistency are crucial attributes of the product.
|
|
27
|
+
It's one thing to say this, but I've backed it up by writing around 1,800 tests to cover PySpark functionality and ensure reliability.
|
|
28
|
+
Until AI improves significantly in this area, SQLFrame will continue to rely on and enhance its understanding of PySpark, ensuring it's available where people need it most.
|
|
29
|
+
|
|
30
|
+
I've received feedback that the SQL generated by SQLFrame can be hard to read, which is much appreciated feedback.
|
|
31
|
+
I realized that while my primary goal is to produce reliable SQL that runs consistently on my engine, readability is also crucial when sharing code with others.
|
|
32
|
+
Minor imperfections in the SQL are acceptable as long as they don't impede understanding. Large Language Models (LLMs) excel at understanding human communication and have been trained to interpret user intent.
|
|
33
|
+
Could SQLFrame leverage this capability?
|
|
34
|
+
Is it time for SQLFrame to join the AI hype train?
|
|
35
|
+
|
|
36
|
+
<div align="center">
|
|
37
|
+
<img src="images/add_chatgpt_support/hype_train.gif" alt="All aboard the train" width="800"/>
|
|
38
|
+
</div>
|
|
39
|
+
|
|
40
|
+
Starting with [1.4.0](https://github.com/eakmanrq/sqlframe), you can now have SQLFrame enrich generated SQL using OpenAI.
|
|
41
|
+
Provide your API key and include `df.sql(openai_config={})` (to use defaults, [config options here](https://sqlframe.readthedocs.io/en/stable/configuration/#optimized)) when generating SQL to see what it looks like.
|
|
42
|
+
Let's take a look at the example from the README.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from sqlframe.bigquery import BigQuerySession
|
|
46
|
+
from sqlframe.bigquery import functions as F
|
|
47
|
+
from sqlframe.bigquery import Window
|
|
48
|
+
|
|
49
|
+
session = BigQuerySession()
|
|
50
|
+
table_path = "bigquery-public-data.samples.natality"
|
|
51
|
+
# Top 5 years with the greatest year-over-year % change in new families with single child
|
|
52
|
+
df = (
|
|
53
|
+
session.table(table_path)
|
|
54
|
+
.where(F.col("ever_born") == 1)
|
|
55
|
+
.groupBy("year")
|
|
56
|
+
.agg(F.count("*").alias("num_single_child_families"))
|
|
57
|
+
.withColumn(
|
|
58
|
+
"last_year_num_single_child_families",
|
|
59
|
+
F.lag(F.col("num_single_child_families"), 1).over(Window.orderBy("year"))
|
|
60
|
+
)
|
|
61
|
+
.withColumn(
|
|
62
|
+
"percent_change",
|
|
63
|
+
(F.col("num_single_child_families") - F.col("last_year_num_single_child_families"))
|
|
64
|
+
/ F.col("last_year_num_single_child_families")
|
|
65
|
+
)
|
|
66
|
+
.orderBy(F.abs(F.col("percent_change")).desc())
|
|
67
|
+
.select(
|
|
68
|
+
F.col("year").alias("year"),
|
|
69
|
+
F.format_number("num_single_child_families", 0).alias("new families single child"),
|
|
70
|
+
F.format_number(F.col("percent_change") * 100, 2).alias("percent change"),
|
|
71
|
+
)
|
|
72
|
+
.limit(5)
|
|
73
|
+
)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Next we will compare SQLGlot optimized, OpenAI replacing SQLGlot optimized CTE names, and then OpenAI doing a full rewrite.
|
|
77
|
+
|
|
78
|
+
<div align="center">
|
|
79
|
+
<img src="images/add_chatgpt_support/sqlglot_optimized_code.png" alt="SQLGlot optimized code" width="800"/>
|
|
80
|
+
</div>
|
|
81
|
+
|
|
82
|
+
<div align="center">
|
|
83
|
+
<img src="images/add_chatgpt_support/openai_replacing_cte_names.png" alt="OpenAI Replacing CTE Names" width="800"/>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div align="center">
|
|
87
|
+
<img src="images/add_chatgpt_support/openai_full_rewrite.png" alt="OpenAI Full Rewrite" width="800"/>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
Overall, the results are promising and make me optimistic that SQLFrame can generate human-like SQL.
|
|
91
|
+
I believe the ideal approach would be to combine tuned SQLGlot optimization rules with OpenAI for tasks such as naming CTEs.
|
|
92
|
+
In the long term, it wouldn't surprise me if models are able to consistently convert accurate SQL into very human-friendly formats without needing any optimization assistance. 💪
|
|
93
|
+
If you are new to SQLFrame, checkout the [repo](https://github.com/eakmanrq/sqlframe) or [announcement blog post](https://towardsdev.com/sqlframe-turning-pyspark-into-a-universal-dataframe-api-e06a1c678f35). 🚀
|
|
94
|
+
If you want to see how I added this integration, checkout [part 1](https://www.loom.com/share/3fab8493818b46f7bff03faf101d2bb6?sid=ffc6a134-f465-478a-a453-7c69b296dc77) or [part 2](https://www.loom.com/share/4055e86dafdd406283d7ba0e0656f0c9?sid=ff0e2af4-1f5a-4760-bf10-9feb89ef9451) where I added this feature ([part 2](https://www.loom.com/share/4055e86dafdd406283d7ba0e0656f0c9?sid=ff0e2af4-1f5a-4760-bf10-9feb89ef9451) is shorter and I think better). 🍿
|
|
95
|
+
Final treat, I overrode the normal prompt with "turn the SQL into complete nonsense". The results:
|
|
96
|
+
|
|
97
|
+
<div align="center">
|
|
98
|
+
<img src="images/add_chatgpt_support/nonsense_sql.png" alt="OpenAI Full Rewrite" width="800"/>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
Nailed it.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -310,6 +310,7 @@ df.show(5)
|
|
|
310
310
|
* [lpad](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.lpad.html)
|
|
311
311
|
* [ltrim](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.ltrim.html)
|
|
312
312
|
* [make_date](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.make_date.html)
|
|
313
|
+
* [make_interval](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.make_interval.html)
|
|
313
314
|
* [map_concat](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.map_concat.html)
|
|
314
315
|
* [map_entries](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.map_entries.html)
|
|
315
316
|
* [map_filter](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.map_filter.html)
|
|
@@ -356,6 +357,8 @@ df.show(5)
|
|
|
356
357
|
* [row_number](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.row_number.html)
|
|
357
358
|
* [rpad](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.rpad.html)
|
|
358
359
|
* [rtrim](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.rtrim.html)
|
|
360
|
+
* [schema_of_csv](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.schema_of_csv.html)
|
|
361
|
+
* [schema_of_json](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.schema_of_json.html)
|
|
359
362
|
* [sec](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.sec.html)
|
|
360
363
|
* [second](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.second.html)
|
|
361
364
|
* [sentences](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.sentences.html)
|
|
@@ -375,6 +378,7 @@ df.show(5)
|
|
|
375
378
|
* [size](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.size.html)
|
|
376
379
|
* [skewness](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.skewness.html)
|
|
377
380
|
* [slice](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.slice.html)
|
|
381
|
+
* [stack](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.stack.html)
|
|
378
382
|
* [sort_array](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.sort_array.html)
|
|
379
383
|
* [soundex](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.soundex.html)
|
|
380
384
|
* [split](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.split.html)
|
|
@@ -405,6 +409,14 @@ df.show(5)
|
|
|
405
409
|
* [translate](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.translate.html)
|
|
406
410
|
* [trim](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.trim.html)
|
|
407
411
|
* [trunc](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.trunc.html)
|
|
412
|
+
* [try_add](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_add.html)
|
|
413
|
+
* [try_avg](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_avg.html)
|
|
414
|
+
* [try_divide](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_divide.html)
|
|
415
|
+
* [try_multiply](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_multiply.html)
|
|
416
|
+
* [try_subtract](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_subtract.html)
|
|
417
|
+
* [try_sum](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_sum.html)
|
|
418
|
+
* [try_to_binary](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_to_binary.html)
|
|
419
|
+
* [try_to_number](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.try_to_number.html)
|
|
408
420
|
* [typeof](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.typeof.html)
|
|
409
421
|
* [unbase64](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.unbase64.html)
|
|
410
422
|
* [unhex](https://spark.apache.org/docs/latest/api/python/reference/pyspark.sql/api/pyspark.sql.functions.unhex.html)
|
|
@@ -21,6 +21,7 @@ setup(
|
|
|
21
21
|
install_requires=[
|
|
22
22
|
"prettytable<3.11.0",
|
|
23
23
|
"sqlglot>=24.0.0,<25.1",
|
|
24
|
+
"typing_extensions>=4.8,<5",
|
|
24
25
|
],
|
|
25
26
|
extras_require={
|
|
26
27
|
"bigquery": [
|
|
@@ -42,7 +43,6 @@ setup(
|
|
|
42
43
|
"pre-commit>=3.5;python_version=='3.8'",
|
|
43
44
|
"pre-commit>=3.7,<3.8;python_version>='3.9'",
|
|
44
45
|
"ruff>=0.4.4,<0.5",
|
|
45
|
-
"typing_extensions>=4.11,<5",
|
|
46
46
|
"types-psycopg2>=2.9,<3",
|
|
47
47
|
],
|
|
48
48
|
"docs": [
|
|
@@ -151,9 +151,10 @@ def sumDistinct(col: ColumnOrName) -> Column:
|
|
|
151
151
|
sum_distinct = sumDistinct
|
|
152
152
|
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
# Product does not have a SQL function available
|
|
155
|
+
# @meta(unsupported_engines="*")
|
|
156
|
+
# def product(col: ColumnOrName) -> Column:
|
|
157
|
+
# raise NotImplementedError("Product is not currently implemented")
|
|
157
158
|
|
|
158
159
|
|
|
159
160
|
@meta()
|
|
@@ -1430,6 +1431,8 @@ def to_json(col: ColumnOrName, options: t.Optional[t.Dict[str, str]] = None) ->
|
|
|
1430
1431
|
|
|
1431
1432
|
@meta(unsupported_engines="*")
|
|
1432
1433
|
def schema_of_json(col: ColumnOrName, options: t.Optional[t.Dict[str, str]] = None) -> Column:
|
|
1434
|
+
if isinstance(col, str):
|
|
1435
|
+
col = lit(col)
|
|
1433
1436
|
if options is not None:
|
|
1434
1437
|
options_col = create_map([lit(x) for x in _flatten(options.items())])
|
|
1435
1438
|
return Column.invoke_anonymous_function(col, "SCHEMA_OF_JSON", options_col)
|
|
@@ -1438,6 +1441,8 @@ def schema_of_json(col: ColumnOrName, options: t.Optional[t.Dict[str, str]] = No
|
|
|
1438
1441
|
|
|
1439
1442
|
@meta(unsupported_engines="*")
|
|
1440
1443
|
def schema_of_csv(col: ColumnOrName, options: t.Optional[t.Dict[str, str]] = None) -> Column:
|
|
1444
|
+
if isinstance(col, str):
|
|
1445
|
+
col = lit(col)
|
|
1441
1446
|
if options is not None:
|
|
1442
1447
|
options_col = create_map([lit(x) for x in _flatten(options.items())])
|
|
1443
1448
|
return Column.invoke_anonymous_function(col, "SCHEMA_OF_CSV", options_col)
|
|
@@ -1560,7 +1565,9 @@ def from_csv(
|
|
|
1560
1565
|
) -> Column:
|
|
1561
1566
|
schema = schema if isinstance(schema, Column) else lit(schema)
|
|
1562
1567
|
if options is not None:
|
|
1563
|
-
option_cols = create_map(
|
|
1568
|
+
option_cols = create_map(
|
|
1569
|
+
[lit(str(x) if isinstance(x, bool) else x) for x in _flatten(options.items())]
|
|
1570
|
+
)
|
|
1564
1571
|
return Column.invoke_anonymous_function(col, "FROM_CSV", schema, option_cols)
|
|
1565
1572
|
return Column.invoke_anonymous_function(col, "FROM_CSV", schema)
|
|
1566
1573
|
|
|
@@ -1667,6 +1674,79 @@ def nullif(col1: ColumnOrName, col2: ColumnOrName) -> Column:
|
|
|
1667
1674
|
return Column.invoke_expression_over_column(col1, expression.Nullif, expression=col2)
|
|
1668
1675
|
|
|
1669
1676
|
|
|
1677
|
+
@meta(unsupported_engines="*")
|
|
1678
|
+
def stack(*cols: ColumnOrName) -> Column:
|
|
1679
|
+
columns = [Column.ensure_col(x) for x in cols]
|
|
1680
|
+
return Column.invoke_anonymous_function(
|
|
1681
|
+
columns[0], "STACK", *columns[1:] if len(columns) > 1 else []
|
|
1682
|
+
)
|
|
1683
|
+
|
|
1684
|
+
|
|
1685
|
+
@meta(unsupported_engines="*")
|
|
1686
|
+
def make_interval(
|
|
1687
|
+
years: t.Optional[ColumnOrName] = None,
|
|
1688
|
+
months: t.Optional[ColumnOrName] = None,
|
|
1689
|
+
weeks: t.Optional[ColumnOrName] = None,
|
|
1690
|
+
days: t.Optional[ColumnOrName] = None,
|
|
1691
|
+
hours: t.Optional[ColumnOrName] = None,
|
|
1692
|
+
mins: t.Optional[ColumnOrName] = None,
|
|
1693
|
+
secs: t.Optional[ColumnOrName] = None,
|
|
1694
|
+
) -> Column:
|
|
1695
|
+
values = [years, months, weeks, days, hours, mins, secs]
|
|
1696
|
+
for value in reversed(values.copy()):
|
|
1697
|
+
if value is not None:
|
|
1698
|
+
break
|
|
1699
|
+
values = values[:-1]
|
|
1700
|
+
else:
|
|
1701
|
+
raise ValueError("At least one value must be provided")
|
|
1702
|
+
columns = [Column.ensure_col(x) if x is not None else lit(None) for x in values]
|
|
1703
|
+
return Column.invoke_anonymous_function(columns[0], "MAKE_INTERVAL", *columns[1:])
|
|
1704
|
+
|
|
1705
|
+
|
|
1706
|
+
@meta(unsupported_engines="*")
|
|
1707
|
+
def try_add(left: ColumnOrName, right: ColumnOrName) -> Column:
|
|
1708
|
+
return Column.invoke_anonymous_function(left, "TRY_ADD", right)
|
|
1709
|
+
|
|
1710
|
+
|
|
1711
|
+
@meta(unsupported_engines="*")
|
|
1712
|
+
def try_avg(col: ColumnOrName) -> Column:
|
|
1713
|
+
return Column.invoke_anonymous_function(col, "TRY_AVG")
|
|
1714
|
+
|
|
1715
|
+
|
|
1716
|
+
@meta(unsupported_engines="*")
|
|
1717
|
+
def try_divide(left: ColumnOrName, right: ColumnOrName) -> Column:
|
|
1718
|
+
return Column.invoke_anonymous_function(left, "TRY_DIVIDE", right)
|
|
1719
|
+
|
|
1720
|
+
|
|
1721
|
+
@meta(unsupported_engines="*")
|
|
1722
|
+
def try_multiply(left: ColumnOrName, right: ColumnOrName) -> Column:
|
|
1723
|
+
return Column.invoke_anonymous_function(left, "TRY_MULTIPLY", right)
|
|
1724
|
+
|
|
1725
|
+
|
|
1726
|
+
@meta(unsupported_engines="*")
|
|
1727
|
+
def try_subtract(left: ColumnOrName, right: ColumnOrName) -> Column:
|
|
1728
|
+
return Column.invoke_anonymous_function(left, "TRY_SUBTRACT", right)
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
@meta(unsupported_engines="*")
|
|
1732
|
+
def try_sum(col: ColumnOrName) -> Column:
|
|
1733
|
+
return Column.invoke_anonymous_function(col, "TRY_SUM")
|
|
1734
|
+
|
|
1735
|
+
|
|
1736
|
+
@meta(unsupported_engines="*")
|
|
1737
|
+
def try_to_binary(col: ColumnOrName, format: t.Optional[ColumnOrName] = None) -> Column:
|
|
1738
|
+
if format is not None:
|
|
1739
|
+
return Column.invoke_anonymous_function(col, "TRY_TO_BINARY", format)
|
|
1740
|
+
return Column.invoke_anonymous_function(col, "TRY_TO_BINARY")
|
|
1741
|
+
|
|
1742
|
+
|
|
1743
|
+
@meta(unsupported_engines="*")
|
|
1744
|
+
def try_to_number(col: ColumnOrName, format: t.Optional[ColumnOrName] = None) -> Column:
|
|
1745
|
+
if format is not None:
|
|
1746
|
+
return Column.invoke_anonymous_function(col, "TRY_TO_NUMBER", format)
|
|
1747
|
+
return Column.invoke_anonymous_function(col, "TRY_TO_NUMBER")
|
|
1748
|
+
|
|
1749
|
+
|
|
1670
1750
|
@meta()
|
|
1671
1751
|
def _lambda_quoted(value: str) -> t.Optional[bool]:
|
|
1672
1752
|
return False if value == "_" else None
|
|
@@ -519,7 +519,10 @@ class SparkCatalog(
|
|
|
519
519
|
)
|
|
520
520
|
for col in df.columns
|
|
521
521
|
]
|
|
522
|
-
return [
|
|
522
|
+
return [
|
|
523
|
+
Column(**{name: x._asdict()[name] for name in Column._fields})
|
|
524
|
+
for x in self._spark_catalog.listColumns(tableName, dbName)
|
|
525
|
+
]
|
|
523
526
|
|
|
524
527
|
def listFunctions(
|
|
525
528
|
self, dbName: t.Optional[str] = None, pattern: t.Optional[str] = None
|
|
@@ -8,9 +8,7 @@ globals().update(
|
|
|
8
8
|
{
|
|
9
9
|
name: func
|
|
10
10
|
for name, func in inspect.getmembers(module, inspect.isfunction)
|
|
11
|
-
if hasattr(func, "unsupported_engines")
|
|
12
|
-
and "spark" not in func.unsupported_engines
|
|
13
|
-
and "*" not in func.unsupported_engines
|
|
11
|
+
if hasattr(func, "unsupported_engines") and "spark" not in func.unsupported_engines
|
|
14
12
|
}
|
|
15
13
|
)
|
|
16
14
|
|
|
@@ -132,6 +132,7 @@ from sqlframe.base.functions import (
|
|
|
132
132
|
lpad as lpad,
|
|
133
133
|
ltrim as ltrim,
|
|
134
134
|
make_date as make_date,
|
|
135
|
+
make_interval as make_interval,
|
|
135
136
|
map_concat as map_concat,
|
|
136
137
|
map_entries as map_entries,
|
|
137
138
|
map_filter as map_filter,
|
|
@@ -177,6 +178,8 @@ from sqlframe.base.functions import (
|
|
|
177
178
|
row_number as row_number,
|
|
178
179
|
rpad as rpad,
|
|
179
180
|
rtrim as rtrim,
|
|
181
|
+
schema_of_csv as schema_of_csv,
|
|
182
|
+
schema_of_json as schema_of_json,
|
|
180
183
|
sec as sec,
|
|
181
184
|
second as second,
|
|
182
185
|
sentences as sentences,
|
|
@@ -200,6 +203,7 @@ from sqlframe.base.functions import (
|
|
|
200
203
|
soundex as soundex,
|
|
201
204
|
split as split,
|
|
202
205
|
sqrt as sqrt,
|
|
206
|
+
stack as stack,
|
|
203
207
|
stddev as stddev,
|
|
204
208
|
stddev_pop as stddev_pop,
|
|
205
209
|
stddev_samp as stddev_samp,
|
|
@@ -225,6 +229,14 @@ from sqlframe.base.functions import (
|
|
|
225
229
|
translate as translate,
|
|
226
230
|
trim as trim,
|
|
227
231
|
trunc as trunc,
|
|
232
|
+
try_add as try_add,
|
|
233
|
+
try_avg as try_avg,
|
|
234
|
+
try_divide as try_divide,
|
|
235
|
+
try_multiply as try_multiply,
|
|
236
|
+
try_subtract as try_subtract,
|
|
237
|
+
try_sum as try_sum,
|
|
238
|
+
try_to_binary as try_to_binary,
|
|
239
|
+
try_to_number as try_to_number,
|
|
228
240
|
typeof as typeof,
|
|
229
241
|
unbase64 as unbase64,
|
|
230
242
|
unhex as unhex,
|
|
@@ -12,10 +12,19 @@ setup.py
|
|
|
12
12
|
.github/CODEOWNERS
|
|
13
13
|
.github/workflows/main.workflow.yaml
|
|
14
14
|
.github/workflows/publish.workflow.yaml
|
|
15
|
+
blogs/add_chatgpt_support.md
|
|
15
16
|
blogs/sqlframe_universal_dataframe_api.md
|
|
16
17
|
blogs/images/but_wait_theres_more.gif
|
|
17
18
|
blogs/images/cake.gif
|
|
18
19
|
blogs/images/you_get_pyspark_api.gif
|
|
20
|
+
blogs/images/add_chatgpt_support/adding_ai_to_meal.jpeg
|
|
21
|
+
blogs/images/add_chatgpt_support/hype_train.gif
|
|
22
|
+
blogs/images/add_chatgpt_support/marvin_paranoid_robot.gif
|
|
23
|
+
blogs/images/add_chatgpt_support/nonsense_sql.png
|
|
24
|
+
blogs/images/add_chatgpt_support/openai_full_rewrite.png
|
|
25
|
+
blogs/images/add_chatgpt_support/openai_replacing_cte_names.png
|
|
26
|
+
blogs/images/add_chatgpt_support/sqlglot_optimized_code.png
|
|
27
|
+
blogs/images/add_chatgpt_support/sunny_shake_head_no.gif
|
|
19
28
|
docs/bigquery.md
|
|
20
29
|
docs/configuration.md
|
|
21
30
|
docs/duckdb.md
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
prettytable<3.11.0
|
|
2
2
|
sqlglot<25.1,>=24.0.0
|
|
3
|
+
typing_extensions<5,>=4.8
|
|
3
4
|
|
|
4
5
|
[bigquery]
|
|
5
6
|
google-cloud-bigquery-storage<3,>=2
|
|
@@ -19,7 +20,6 @@ pytest-xdist<3.7,>=3.6
|
|
|
19
20
|
pytest<8.3,>=8.2.0
|
|
20
21
|
ruff<0.5,>=0.4.4
|
|
21
22
|
types-psycopg2<3,>=2.9
|
|
22
|
-
typing_extensions<5,>=4.11
|
|
23
23
|
|
|
24
24
|
[dev:python_version == "3.8"]
|
|
25
25
|
pre-commit>=3.5
|
{sqlframe-1.7.0 → sqlframe-1.8.0}/tests/integration/engines/bigquery/test_bigquery_session.py
RENAMED
|
@@ -16,5 +16,5 @@ def test_session_from_config():
|
|
|
16
16
|
conn.cursor().execute("CREATE SCHEMA IF NOT EXISTS db1")
|
|
17
17
|
conn.cursor().execute("CREATE TABLE IF NOT EXISTS db1.test_table (cola INT, colb STRING)")
|
|
18
18
|
session = BigQuerySession.builder.config("default_dataset", "sqlframe.db1").getOrCreate()
|
|
19
|
-
columns = session.catalog.get_columns("test_table")
|
|
19
|
+
columns = session.catalog.get_columns("db1.test_table")
|
|
20
20
|
assert columns == {"`cola`": exp.DataType.build("BIGINT"), "`colb`": exp.DataType.build("TEXT")}
|