Skip to main content

SQLx Support for Kinetica via PostgreSQL Wire Protocol

This module provides helpers for using SQLx with Kinetica’s PostgreSQL wire protocol support.

Overview

Kinetica supports the PostgreSQL wire protocol on port 5432, which means you can use SQLx’s PostgreSQL driver directly. This module provides:

Quick Start

Type Mappings

Kinetica’s PostgreSQL protocol carries its types as below, as measured against Kinetica 7.2. Where the PostgreSQL type does not carry the value whole, read and write it through the wrappers this module provides (see KineticaText and its siblings).

Kinetica typeSent asRead asBind as
BOOLEANBOOLboolKineticaText(bool)
TINYINT, SMALLINT, INTEGERINT4i32KineticaText(i32)
BIGINTINT8i64KineticaText(i64)
UNSIGNED BIGINTTEXTKineticaText<u64>KineticaText(u64)
REALFLOAT4f32KineticaText(f32)
DOUBLEFLOAT8f64KineticaText(f64)
DECIMAL(p,s)NUMERICa decimal type, with SQLx’s bigdecimal or rust_decimal feature; or CAST(col AS VARCHAR) as KineticaText<String>KineticaText of its text
VARCHAR, VARCHAR(n)TEXTStringKineticaText(&str)
IPV4TEXTKineticaText<Ipv4Addr>KineticaText(Ipv4Addr)
UUIDTEXTKineticaText<uuid::Uuid>KineticaText(uuid::Uuid)
DATEDATEchrono::NaiveDateKineticaText(NaiveDate)
TIMETEXTKineticaText<NaiveTime>KineticaText(NaiveTime)
DATETIMETIMESTAMP, without its millisecondsCAST(col AS VARCHAR) as KineticaText<NaiveDateTime>KineticaText(NaiveDateTime)
TIMESTAMPINT8: milliseconds since the epochKineticaTimestampKineticaTimestamp
BLOBBYTEAVec<u8> or KineticaBytesKineticaBytes
GEOMETRY, BLOB(WKT)none: the query failsST_ASTEXT(col) as StringKineticaText of its WKT
JSONJSONserde_json::Value or KineticaJson<T>KineticaJson(value)
VECTOR(n)TEXT, e.g. [1,2.5,3]KineticaVectorKineticaVector in a plain INSERT; KineticaText(vector.as_slice()) elsewhere
arrays, e.g. INTEGER[3]PostgreSQL arrays numbered from 0KineticaArray<T>KineticaArray<T>

This crate enables SQLx’s chrono and json features, so NaiveDate and serde_json::Value read as they are. Nulls read as Option<_> of any of these, and bind as None.

What goes wrong without the wrappers:

  • SQLx’s Vec<T> refuses Kinetica’s arrays, which are numbered from 0.
  • A DATETIME read as a NaiveDateTime, or bound as one, loses its milliseconds.
  • Kinetica refuses uuid::Uuid, NaiveTime, decimal and Vec<u8> (BYTEA) parameters.
  • SQLx binds serde_json::Value and sqlx::types::Json as JSONB, which Kinetica refuses as invalid JSON.
  • A plain INSERT refuses a vector as text, and everything else refuses one as raw floats.

Parameters

Kinetica reads every parameter after a statement’s first as text, whatever type SQLx sends it as. A second integer, float or date parameter therefore fails to convert in an INSERT. In a WHERE clause it matches nothing, so an UPDATE or DELETE reports success and changes no rows. A literal beside such a parameter can be stored as NULL. Text parameters work in every position, and Kinetica converts each to its column’s type, so bind every parameter through a wrapper, which sends text:

JSON, Arrays and Vectors

Each is inserted, updated, filtered on and deleted by with ordinary SQL, binding the wrappers above. Measured against Kinetica 7.2:

  • JSON. Bind documents with KineticaJson, which takes any Serialize value; read them as KineticaJson<T> for any DeserializeOwned T. JSON_VALUE(col, $1)</code> (whose path may be a parameter), <code>JSON\_QUERY</code>, <code>JSON\_EXISTS</code>, <code>JSON\_LENGTH</code>, <code>JSON\_TYPE</code>, <code>IS\_JSON</code>, <code>JSON\_OBJECT</code> and <code>JSON\_ARRAY</code> work, with nested paths in <code>GROUP BY</code> and <code>JOIN</code> too. A SQL <code>NULL</code> and the JSON <code>null</code> stay distinct. Declare JSON columns as <code>JSON</code>: <code>VARCHAR(json)</code> and <code>STRING(json)</code> are plain strings on the server.</li> <li><strong>Full-text search.</strong> A <code>JSON(text\_search)</code> column, on a server with <code>enable\_text\_search</code>, is searched by key with <code>text\_match(col, $1) (bool) and ranked with text_match_bm25 or text_match_bm25_global (f64), the query bound as KineticaText(“customer.tier:Enterprise”). Do not UPDATE such a column: on Kinetica 7.2.3.21 that crashes a worker rank. Delete the row and insert it again.
  • Arrays. Bind with KineticaArray, and use KineticaArray<Option<T>> for arrays holding nulls. ARRAY_CONTAINS, ARRAY_CONTAINS_ANY, ARRAY_CONTAINS_ALL, ARRAY_LENGTH, col[i] (numbered from 1), ARRAY_APPEND, ARRAY_CONCAT, ARRAY_SLICE and ARRAY_TO_STRING work; arrays they compute arrive as JSON text, which KineticaArray reads too. A numeric ARRAY_CONTAINS(col, $1)</code> finds nothing whatever is bound: write <code>ARRAY\_CONTAINS\_ANY(col, $1) with a one-element KineticaArray. A fixed size, as in INTEGER[3], is not enforced, and an infinite float is refused.
  • Vectors. A plain INSERT … VALUES (n)</code>takes<ahref="/content/api/rust/sqlxsupport/struct.KineticaVector"title="structgpudbapi::sqlxsupport::KineticaVector"><code>KineticaVector</code></a>;<code>UPDATE...SETv=n)</code> takes <a href="/content/api/rust/sqlx_support/struct.KineticaVector" title="struct gpudb_api::sqlx_support::KineticaVector"><code>KineticaVector</code></a>; <code>UPDATE ... SET v = n, VECTOR(n, dims)</code> and function arguments take <code>KineticaText(vector.as\_slice())</code>. <code>L1\_DISTANCE</code>, <code>L2\_DISTANCE</code>, <code>COSINE\_DISTANCE</code>, <code>DOT\_PRODUCT</code> and <code>L2\_NORM</code> return <code>f32</code>, as does <code>v &lt;-&gt; CAST(1 AS VECTOR(n)); a bare v <-> $1 is refused.

Read arrays through sqlx::query: in the text form sqlx::raw_sql returns, Kinetica writes null in capitals wherever it occurs in a string element.

Compile-Time Checked Queries

SQLx supports compile-time checked queries with the query! macro. However, this requires a live database connection during compilation. For Kinetica, you can:

  1. Use the offline mode with sqlx prepare
  2. Use runtime queries with sqlx::query()

Transactions

Kinetica’s PostgreSQL protocol does not support transactions: pool.begin() fails (“got unexpected connection status after attempting to begin transaction”), and each statement applies when it runs.

Connection Pooling Best Practices

For optimal performance with Kinetica:

  • Set max_connections based on your workload (default: 10)
  • Use min_connections for warm connection pools
  • Set appropriate timeouts for your network latency

The server serves one session per thread, up to its postgres_proxy.max_threads (64 by default), shared by every client. It ends a session when its client sends PostgreSQL’s Terminate message, which pool.close() sends. A connection closed without it, as when a process exits or a task panics with the connection open, keeps its session until the server’s postgres_proxy.idle_connection_timeout (300 seconds by default). Pools that outgrow the server’s sessions wait, then fail with sqlx::Error::PoolTimedOut. SQLx 0.8’s pool.close() can return while a connection on its way back to the pool is still open: before a program ends, close again once pool.size() shows it is back (see SQLX_API.md).

Limitations

Besides the types and parameters above:

  • Transactions are not supported.
  • Sessions are limited by the server, and outlive connections that are not closed (see above).
  • PostgreSQL-specific features, such as LISTEN/NOTIFY, are not available.
  • Kinetica-specific SQL extensions should be written as raw SQL strings.

For full fidelity on every Kinetica type, and for Kinetica-specific operations (bulk insert, type management, KiFS), use the native API of the Kinetica client. It carries each value with its column’s properties.

Structs

A SQLx client that automatically batches INSERT statements and routes them through BulkInserter<GenericRecord> for high-performance shard-aware ingestion.
Statistics from batching operations.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. An array column’s value. Kinetica sends arrays numbered from 0, which SQLx’s own Vec<T> refuses; this reads them, in the binary form a query’s results come in and in the text form sqlx::raw_sql gives, and writes them as the JSON text Kinetica takes. It also reads the JSON text Kinetica sends for an array a function computes, such as ARRAY_APPEND(col, 4).
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A BLOB column’s value. Kinetica refuses a BYTEA parameter, but takes the bytes of a text parameter as they are, so this sends them under the text type; it reads the BYTEA Kinetica sends.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A JSON column’s value: anything serde serializes, bound directly as JSON, and read back from the JSON Kinetica sends.
Builder for creating Kinetica connection pools with sensible defaults.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A value carried as text, both ways, which Kinetica converts to and from its column’s type.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A TIMESTAMP column’s value: milliseconds since the Unix epoch, which Kinetica sends as BIGINT and takes as text.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A VECTOR(n) column’s value. Kinetica sends it as text, [1,2.5,3], and reads it from a parameter in two ways, depending on where it is:
Bulk inserter for SQLx that uses Kinetica’s HTTP API for efficient data loading.
Statistics from a paginated SQLx query execution.

Enums

Error type for BatchingSqlxClient operations
SSL mode for connections.

Constants

pub const DEFAULT_DATABASE: &str = “postgres”;

Default database name (PostgreSQL compatibility).

pub const DEFAULT_PORT: u16 = 5432;

Default PostgreSQL wire protocol port for Kinetica.

Traits

Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A value read from the text Kinetica sends: see KineticaText.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. An element of a Kinetica array: see KineticaArray.
Extension trait for PgPool with Kinetica-specific helpers.
Values for the Kinetica types SQLx’s own PostgreSQL types cannot read or write over Kinetica’s protocol, or cannot reliably: see their module. A value Kinetica takes as text: see KineticaText.

Functions

Create a connection URL from components.
Connect to Kinetica with minimal configuration.
Connect to Kinetica using environment variables.
Connect to Kinetica using PgConnectOptions.
Connect to Kinetica using a connection URL.
Parse a Kinetica connection URL from environment variables.

Type Aliases

Type alias for SQLx PostgreSQL connection.
Type alias for SQLx PostgreSQL connection pool configured for Kinetica.
Type alias for SQLx PostgreSQL transaction.