frostlake-connector
A high-level Python client for Frostlake, built on the
frostlake PEP 249 driver.
Where the driver is a minimal DB-API surface, this package adds the conveniences an
application usually wants: %s and %(name)s binding, dict-shaped rows, multi-statement
scripts, session setup on connect, and a full exception hierarchy.
pip install frostlake-connector
The driver comes along as a dependency and speaks Frostlake's HTTP protocol, so no JVM is needed on the client.
Engine version
Requires a Frostlake engine 0.2.0 or newer. Ask a running server which one it is with
SELECT CURRENT_VERSION() — every release answers it, so the check works against any engine.
The client versions independently of the engine: it speaks the HTTP protocol, not the jar, so this is a floor rather than a lockstep pin.
Usage
import frostlake_connector
conn = frostlake_connector.connect(host="localhost", port=18082,
database="MY_DB", schema="PUBLIC",
warehouse="COMPUTE_WH",
session_parameters={"QUERY_TAG": "ci"})
cur = conn.cursor()
cur.execute("SELECT id, name FROM people WHERE id = %s", (1,))
print(cur.fetchall()) # [(1, 'Ada')]
What it covers
connect(**kwargs)—host/portselect the server;role,warehouse,databaseandschemabecomeUSEstatements (in that order) andsession_parameters/timezonebecomeALTER SESSION SET. Unrecognised keywords are accepted and ignored, so a configuration carried over from another warehouse still loads. Those names fold like unquoted SQL —database="my_db"selectsMY_DB— so include the double quotes (database='"my_db"') to reach an object whose real name is not upper case.- Cursors:
execute(returns the cursor),executemany,fetchone/fetchmany/fetchall,nextsetfor multi-statement results, iteration, context-manager use,rowcountfrom DML, andquery_id.DictCursorreturns dicts instead of tuples. A script handed toexecutewhole travels as one request, and a session runs one statement per request until something asks for more:execute(sql, num_statements=n)declares the count for that one call (0for any number), as the account's connector does, and leaves the session's ownMULTI_STATEMENT_COUNTwhere it was, whileALTER SESSION SET MULTI_STATEMENT_COUNT = nsets it for the session;execute_stringsplits the script client-side instead, so it needs neither. - Descriptions:
ResultMetadata(name, type_code, display_size, internal_size, precision, scale, is_nullable), wheretype_codeis a numeric family code — seeconstants.FIELD_ID_TO_NAME— so callers can branch without parsing SQL type text.internal_sizecarries the column's length — characters for text, bytes for binary — when the server sends one, and staysNonefor other types and for engines predating the field.display_sizeis alwaysNone, as in the account's own Python client. - Binding:
pyformatby default (%s,%(name)s,%%), orparamstyle="qmark"for?. Placeholders inside string literals, quoted identifiers, comments and$$…$$bodies are left alone. execute_string()splits a script on top-level semicolons — respecting$$…$$procedure bodies — and returns one cursor per statement.- Transactions:
autocommit(mode),commit(),rollback(). With autocommit off the connection stays transactional: ending one transaction opens the next. TheBEGINeach transaction starts with stays owed until the engine takes it. If a setup statement or theBEGINitself fails, the statement tried next sends it again first, so it never commits on its own where arollback()could not reach it. Acommit()orrollback()that fails still leaves the next statement in a transaction the nextcommit()reaches. ACOMMITthe engine refuses is rolled back before the refusal is raised, and the next statement opens a fresh transaction. ACOMMITwhose answer never came leaves the transaction open for the next statement to join.autocommit(True)turns autocommit on even when theCOMMITit sends fails: the error is raised, a transaction left open is committed on the way, and the next statement commits on its own. is_closed(),session_id, and connections as context managers.- Errors: a PEP 249 hierarchy in
frostlake_connector.errors— everything derives fromError, database failures fromDatabaseError. Each carriesmsg,errno,sqlstate,query_idandquery; engine compile errors arrive asProgrammingError(errno=1003, sqlstate="42000"), with the engine's message text authoritative.SessionLostError, anOperationalError, reports a lost session (see below).
Session lifetime
A connection holds one engine session, kept by the frostlake driver underneath. What
connect() sets up — USE ROLE, USE WAREHOUSE, USE DATABASE, USE SCHEMA, then an
ALTER SESSION SET for each of session_parameters and timezone — is the connection's
scope. It goes on before the first statement, and back on any session that replaces a lost
one. A setup statement the engine refuses (a warehouse or database that does not exist, a
parameter it does not know) stays first in line: every statement fails with that refusal,
its query naming the refused statement, until the engine accepts it. Nothing runs
without the rest of the setup in its place.
- What is sent. Once the engine has shown that it tracks sessions (its answers carry
newSession, as engines from 0.1.0 do), every request that names the session also sendsrequireSession: true: resume this session, or refuse. An engine whose answers lack the field is never sent it. - After a lost session. The engine forgets a session that sat idle for 30 minutes, was
released, or went with a restart, and it refuses a request that requires it (HTTP 404)
without running anything. When the session held nothing a fresh one would lack, the
connection starts a fresh session, puts the scope on it, and sends the statement once
more. A second refusal raises. When the session held an open transaction, or context
set up with
USE,SET/UNSET,ALTER SESSION, a temporary object, or aCREATE/DROPof a database or schema,errors.SessionLostErroris raised instead. The statement did not run, and in a fresh session it would run somewhere its author did not intend. The connection stays usable. The next statement starts a fresh session on the scope, and with autocommit off it opens a transaction there first. - Close.
close(), and leaving awithblock, release the session withDELETE /api/sessions/{id}, which rolls back a transaction left open. An engine without that endpoint gets aROLLBACKfor an open transaction instead, and keeps the session until its own idle expiry. Either is one request, bounded by the shorter ofnetwork_timeoutand 5 seconds.close()never raises, and a secondclose()sends nothing.
Running the tests
export JAVA_HOME=/path/to/jdk17
export FROSTLAKE_CLASSPATH="/path/to/frostlake-db.jar:<engine deps>"
python3 test/test_facade.py
The suite boots a real DatabaseHttpServer and covers connect-kwargs context
(CURRENT_DATABASE/CURRENT_SCHEMA/CURRENT_WAREHOUSE), binding in both paramstyles,
descriptions and type codes, DictCursor, executemany, execute_string, transaction
discipline, the error surface and the session lifetime. Without FROSTLAKE_CLASSPATH the
integration tests skip and the unit tests still run, the session scenarios among them
against a scripted stand-in engine.
Set FL_CORPUS to the engine's testkit directory (an absolute path) and the same run also
replays the engine's language-neutral SQL corpus through the facade (testkit_runner.py);
without it, that test skips:
FL_CORPUS=/path/to/frostlake/engine/src/test/resources/testkit python3 test/test_facade.py
Related
frostlake— the PEP 249 driver underneath.dbt-frostlake— the dbt adapter, which uses this client as its transport.
Metadata
Release files for frostlake-connector 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| frostlake_connector-0.3.0.tar.gz | 32.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| frostlake_connector-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 49.7 kB
Release files / frostlake_connector-0.3.0.tar.gz
| Download URL | frostlake_connector-0.3.0.tar.gz |
|---|---|
| Size | 32.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
59cc692531630ae0e384b2a78b8628c29fe84fbcdddb693360fb70721472eb7f
|
|
BLAKE2b-256 checksum How to use checksums |
087b356005b2f82cb410ae587288d489b371d56dda39ce0cbf366ccd7a0f2a5e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / frostlake_connector-0.3.0-py3-none-any.whl
| Download URL | frostlake_connector-0.3.0-py3-none-any.whl |
|---|---|
| Size | 16.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3687d68f815b050e7eb1d4c2037440b739553ddfc6c749a61eb1c0eb42d8d46a
|
|
BLAKE2b-256 checksum How to use checksums |
c5eea34387febe6d003d0ebbc42a3ee4efe8ab342ef0e251b65be8b58d654c6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|