sqlframe

repository·main·Indexed 19 days ago

https://github.com/eakmanrq/sqlframe

sqlframe implements the PySpark DataFrame API to enable running transformation pipelines directly on database engines such as BigQuery, DuckDB, and Postgres, eliminating the need for Spark clusters. It allows users to either replace PySpark imports via an activate function or use engine-native session classes. Key features include optimized SQL generation via df.sql(optimize=True), OpenAI-powered SQL enrichment (v1.4.0+), and support for PySpark Catalog and Column methods.

Tokens
37K
Snippets
115
Records
151
Agent score
67%

What's inside sqlframe

  1. Avoid connection errors with automatic reconnection

    main

    The Databricks SQL Connector for Python may close idle connections, which can cause errors in SQLFrame when it attempts to use a closed connection.

    To prevent this, instead of passing a Connection object (which is required for the activate function), pass the connection parameters directly to the DatabricksSession constructor. This allows SQLFrame to manage the connection and automatically reconnect when needed.

    import os
    from sqlframe.databricks import DatabricksSession
    
    session = DatabricksSession(
        server_hostname="dbc-xxxxxxxx-xxxx.cloud.databricks.com",
        http_path="/sql/1.0/warehouses/xxxxxxxxxxxxxxxx",
        access_token=os.environ["ACCESS_TOKEN"],
        auth_type="access_token",
        catalog="catalog",
        schema="schema",
    )
  2. Use the Snowflake `Table` class for DML operations

    main

    SQLFrame extends standard PySpark functionality for Snowflake by providing a Table class. This class is returned when calling session.table("table_name"). Unlike standard DataFrames, the Table class supports Data Manipulation Language (DML) operations such as update, delete, and merge.

    Note that these methods do not execute immediately; they return a LazyExpression object which must be executed using the .execute() method.

    from sqlframe.snowflake import SnowflakeSession
    
    # ... setup connection and session ...
    
    table_employee = session.table("employee")  # Returns a SnowflakeTable object
  3. How to enable SQLFrame for BigQuery

    main

    You can enable SQLFrame for BigQuery using one of two patterns:

    1. Direct Import: Replace pyspark.sql imports with sqlframe.bigquery. This is recommended when converting an existing PySpark pipeline. Note that many classes will have a BigQuery prefix (e.g., BigQueryDataFrame instead of DataFrame).

    2. Activation: Use the activate("bigquery", ...) function. This allows you to continue using pyspark.sql imports while SQLFrame runs the operations on BigQuery behind the scenes. Once activated, pyspark.sql.SparkSession will return a SQLFrame BigQuerySession object.

    # Pattern 1: Direct Import
    from sqlframe.bigquery import BigQuerySession
    from sqlframe.bigquery import functions as F
    from sqlframe.bigquery import BigQueryDataFrame
    
    # Pattern 2: Activation
    from sqlframe import activate
    activate("bigquery", config={"default_dataset": "sqlframe.db1"})
    from pyspark.sql import SparkSession
  4. How standalone mode works in SQLFrame

    main
    Standalone mode allows SQLFrame to perform query generation without requiring access to a live database. Because there is no active connection, you must explicitly provide schema information for any tables you wish to reference. Operations that require an actual database connection (such as executing the generated SQL) will not work in this mode.
  5. Use the BigQuery Table class for DML operations

    main

    SQLFrame extends BigQuery capabilities by providing a Table class that supports Data Manipulation Language (DML) operations not natively available in PySpark, such as update, delete, and merge.

    To obtain a Table object, use the session.table("table_name") method. This returns a BigqueryTable instance. Most DML methods return a LazyExpression object, which must be explicitly executed using the .execute() method to perform the operation on the BigQuery backend.

    import google.auth
    from google.cloud.bigquery.dbapi import connect
    from sqlframe.bigquery import BigQuerySession
    
    # ... setup connection and session ...
    session = BigQuerySession(conn=conn, default_dataset="sqlframe.db1")
    
    # Create a DataFrame and save it as a table
    session.createDataFrame(data).write.mode("overwrite").saveAsTable("employee")
    
    # Access the table for DML operations
    table_employee = session.table("employee")
  6. Use DuckDB-specific array functions

    main
    When working with DuckDB via SQLFrame, note that the standard PySpark reverse function only operates on strings and will not work on arrays. To reverse an array, you must use the SQLFrame-specific array_reverse function.
  7. Use the Table class for DML operations in Databricks

    main

    SQLFrame provides a Table class for Databricks that extends standard PySpark functionality by supporting Data Manipulation Language (DML) operations like update, delete, and merge. You can obtain a Table object (specifically a DatabricksTable) by calling session.table("table_name").

    Note that these methods return a LazyExpression object, which must be executed using the .execute() method to perform the operation on the server.

    from databricks.sql import connect
    from sqlframe.databricks import DatabricksSession
    
    conn = connect(
        server_hostname="dbc-xxxxxxxx-xxxx.cloud.databricks.com",
        http_path="/sql/1.0/warehouses/xxxxxxxxxxxxxxxx",
        access_token="YOUR_TOKEN",
        auth_type="access_token",
        catalog="catalog",
        schema="schema",
    )
    session = DatabricksSession(conn=conn)
    
    # Returns a DatabricksTable object
    table_employee = session.table("employee")
  8. Enable SQLFrame for Snowflake

    main

    You can enable SQLFrame for Snowflake using two different approaches depending on your workflow:

    1. Direct Import: Best for converting existing PySpark pipelines. Replace pyspark.sql imports with sqlframe.snowflake. Note that many classes will have a Snowflake prefix (e.g., SnowflakeDataFrame instead of DataFrame).

    2. Activation: Best if you want to continue using the standard pyspark.sql API. By calling activate("snowflake", conn=conn), any subsequent calls to pyspark.sql.SparkSession will return a SQLFrame SnowflakeSession object, and all operations will be executed directly on Snowflake.

    # Direct Import approach
    from sqlframe.snowflake import SnowflakeSession
    from sqlframe.snowflake import functions as F
    from sqlframe.snowflake import SnowflakeDataFrame
    
    # Activation approach
    from sqlframe import activate
    from snowflake.connector import connect
    import os
    
    conn = connect(
        account=os.environ["SNOWFLAKE_ACCOUNT"],
        user=os.environ["SNOWFLAKE_USER"],
        password=os.environ["SNOWFLAKE_PASSWORD"],
        warehouse=os.environ["SNOWFLAKE_WAREHOUSE"],
        database=os.environ["SNOWFLAKE_DATABASE"],
        schema=os.environ["SNOWFLAKE_SCHEMA"],
    )
    activate("snowflake", conn=conn)
    
    from pyspark.sql import SparkSession
    spark = SparkSession.builder.getOrCreate()
  9. Use the DuckDB Table class for DML operations

    main

    SQLFrame provides a Table class for DuckDB that extends standard DataFrame functionality with Data Manipulation Language (DML) operations like update and delete. This class is returned when using the session.table("table_name") method.

    Note that DML operations like update and delete return a LazyExpression object. To apply the changes to the underlying database, you must call the .execute() method on that expression.

    import duckdb
    from sqlframe.duckdb import DuckDBSession
    
    conn = duckdb.connect(database=":memory:")
    session = DuckDBSession(conn=conn)
    
    # Create a table via session
    df_employee = session.createDataFrame([
        {"id": 1, "fname": "Jack", "lname": "Shephard", "age": 37, "store_id": 1}
    ])
    df_employee.write.mode("overwrite").saveAsTable("employee")
    
    # Access the Table object
    table_employee = session.table("employee")
  10. Enable SQLFrame for Redshift

    main

    SQLFrame can be enabled for Redshift in two ways:

    1. Direct Import: Replace pyspark.sql imports with sqlframe.redshift imports. Note that many classes will have a Redshift prefix (e.g., RedshiftDataFrame instead of DataFrame).
    2. Activation: Use the activate("redshift", conn=conn) function. This allows you to continue using the standard pyspark.sql API while SQLFrame runs the operations directly on Redshift behind the scenes.

    Both methods require a redshift_connector.Connection object.

    # Method 1: Direct Import
    from sqlframe.redshift import RedshiftSession
    from sqlframe.redshift import functions as F
    from sqlframe.redshift import RedshiftDataFrame
    
    # Method 2: Activation
    import os
    from redshift_connector import connect
    from sqlframe import activate
    
    conn = connect(
        user="user",
        password=os.environ["PASSWORD"],
        database="database",
        host="xxxxx.xxxxxx.region.redshift-serverless.amazonaws.com",
        port=5439,
    )
    activate("redshift", conn=conn)
    
    from pyspark.sql import SparkSession
    # SparkSession is now a RedshiftSession
  11. How to enable SQLFrame for Databricks

    main

    SQLFrame can be integrated into your workflow in two ways:

    1. Direct Import: Replace pyspark.sql imports with sqlframe.databricks. Note that many classes use a Databricks prefix (e.g., DatabricksDataFrame instead of DataFrame). This is recommended when converting existing PySpark pipelines.

    2. Activation: Use the activate("databricks", ...) function. This allows you to continue using standard pyspark.sql imports while SQLFrame runs the operations on Databricks behind the scenes. After calling activate, a standard SparkSession will behave as a SQLFrame DatabricksSession object.

  12. Enable SQLFrame for DuckDB

    main

    You can enable SQLFrame for DuckDB using one of two methods:

    1. Direct Import: Replace pyspark.sql imports with sqlframe.duckdb. Note that many classes will have a DuckDB prefix (e.g., DuckDBDataFrame instead of DataFrame). This is recommended when converting an existing PySpark pipeline.
    2. Activation: Use the activate("duckdb") function. This allows you to continue using the standard pyspark.sql API, but SQLFrame will run the operations on DuckDB behind the scenes. In this mode, SparkSession becomes a DuckDBSession object.
    # Method 1: Direct Import
    from sqlframe.duckdb import DuckDBSession
    from sqlframe.duckdb import functions as F
    from sqlframe.duckdb import DuckDBDataFrame
    
    # Method 2: Activation
    from sqlframe import activate
    activate("duckdb")
    
    from pyspark.sql import SparkSession