Skip to Content
Kubling 26.5 changes namespaces, JDBC identifiers and error codes. Review the migration guide →
ClientsgRPC ClientsProtocol Reference

Protocol reference PREVIEW

The public client protocol is defined with Protocol Buffers in the kubling-grpc repository. The protobuf package is kubling.v1. The server reports its effective protocol and session-bound capabilities through GetServerInfo.

Client gRPC is the application interface exposed by the Kubling Engine. Provider gRPC is a separate contract used between Kubling and a physical source integration. Do not mix their protobuf packages or lifecycle rules.

Contract files

FilePurpose
command.protoSessions, SQL execution, ordered result events, transactions and server information.
value.protoLogical values, declared types, arrays, spatial values and LOB references.
capability.protoAuthenticated capabilities, protocol limits, directional type support and affinity.
transaction.protoTransaction state, outcome and affinity enums.
lob.protoBounded LOB upload, download and release operations.
error.protoStable structured application errors and retryability.

Generate application clients from a released proto/v* tag or use an SDK built from one. A branch head is not a compatibility boundary.

Services

SessionService

RPCResult
LoginAn expiring token, session identity, VDB identity, timezone and affinity.
LogoutCloses the logical session represented by the token.
PingConfirms that the transport is reachable.
PingSessionConfirms that a token and optional session ID remain valid.

QueryService

RPCBehavior
ExecuteExecutes SQL once and streams its actual result kind.
QueryLegacy server-streaming query API.
ExecLegacy unary update API.
BeginTransactionStarts or obtains the session transaction and returns its opaque ID when supported.
CommitTransactionCommits the active transaction, optionally asserting its ID.
RollbackTransactionRolls back the active transaction, optionally asserting its ID.
IsInTransactionReports whether the session currently has an active transaction.
GetTransactionStatusReturns an authoritative retained observation for one transaction ID when supported.
GetServerInfoReturns product information and authenticated, session-bound capabilities.

LobService v26.5+

RPCBehavior
ReadLobStreams bounded chunks from an issued BLOB or CLOB reference.
WriteLobUploads one immutable LOB and returns a reference.
ReleaseLobReleases a reference before its normal expiry.

The expiring token is an explicit protobuf field. It is not an HTTP authorization header or implicit gRPC metadata value.

Negotiate before execution v26.5+

New clients should negotiate after Login:

  1. call GetServerInfo with the expiring token
  2. inspect features, directional supported_types, limits and affinity
  3. retain the opaque capability_id from that response
  4. send that ID with every Execute and LOB request
  5. list only output features the client can decode in accepted_features

Capabilities are effective for the authenticated session, selected VDB and serving node. Kubling rejects a stale or mismatched capability_id before executing SQL. Calling GetServerInfo without a token preserves legacy product information, but it does not provide authenticated capability guarantees.

Zero in a protocol limit means unknown, not unlimited. A client may impose a smaller local bound.

Feature registry

FeatureContract
generic_execute_v1Ordered Execute events with a checked capability snapshot.
typed_parameters_v1Explicit parameter types, including typed NULL.
structured_errors_v1KublingError details in the final gRPC status.
transaction_ids_v1Opaque transaction IDs and stale-ID protection.
transaction_status_v1Retained authoritative transaction observations.
array_values_v1Typed homogeneous arrays with bounded nesting.
spatial_values_v1WKB geometry and geography with optional SRID or CRS.
lob_read_v1LOB references, bounded reads and explicit release.
lob_write_v1Immutable LOB upload and references as input parameters.
multiple_results_v1More than one primary result in execution order.
generated_keys_v1Associated, separately streamed generated-key results.

Feature activation is explicit. Do not infer LOB support from BLOB output, array support from JSON, or transaction status retention from transaction IDs.

Execute event stream v26.5+

Execute replaces statement-kind probing. Submit the SQL once and consume the events in order.

EventMeaning
ResultSetStartStarts a query or generated-key result and carries its schema.
ResultRowsCarries zero or more positional rows for that result ID.
ResultSetEndCloses the result and reports its total row count.
UpdateResultReports one update result with known or explicitly unknown counts.
ExecutionEndCloses the successful execution and reports result count and transaction state.

A result set follows this grammar:

ResultSetStart -> ResultRows* -> ResultSetEnd

A zero-row result still emits ResultSetStart and ResultSetEnd. Result IDs are consecutive from one and include query, update and generated-key results. Generated keys use their own result ID and identify the parent update.

Successful completion requires both:

  • exactly one ExecutionEnd after every result
  • final gRPC status OK

Rows are not proof of success. A constraint, transport or engine failure may arrive after rows have already been delivered. That stream ends with a non-OK status and no ExecutionEnd, so the consumer must discard any assumption of successful completion.

Never recover from a result-shape error by replaying the same SQL through Query or Exec. The first call may already have changed remote state.

Consume the result stream directly

The Go SDK exposes the generated service through cli.QueryService(). A minimal scalar execution first obtains the authenticated capability ID:

info, err := cli.QueryService().GetServerInfo(ctx, &kublingv1.GetServerInfoRequest{ ExpiringToken: cli.Token(), }) if err != nil { return err } stream, err := cli.QueryService().Execute(ctx, &kublingv1.ExecuteRequest{ ExpiringToken: cli.Token(), Sql: "SELECT id, name FROM provider.PROJECT ORDER BY id", CapabilityId: info.GetCapabilities().GetCapabilityId(), }) if err != nil { return err } sawExecutionEnd := false for { event, err := stream.Recv() if errors.Is(err, io.EOF) { if !sawExecutionEnd { return errors.New("Kubling stream ended without ExecutionEnd") } break } if err != nil { return err } // Handle each event in order and enforce matching result IDs. if event.GetExecutionEnd() != nil { sawExecutionEnd = true } }

Add an optional feature to AcceptedFeatures only after checking that the server advertises it and the client can process the corresponding output.

Legacy Query and Exec

Query and Exec remain available for compatibility. Query streams QueryBatch messages whose columns normally appear in the first batch. Exec returns affected rows, per-command counts and optional generated keys.

Legacy RPCs never emit the new array, spatial-with-CRS or LOB-reference variants. New clients should use Execute rather than guessing the statement kind or losing negotiated representations.

Values and parameters v26.5+

Value uses a protobuf oneof so logical types do not collapse into text.

Logical familyWire representation
String, character, JSON and XMLUTF-8 text variants.
Boolean and fixed-width numeric valuesMatching protobuf scalar with logical range validation.
Big integer and decimalCanonical decimal text to preserve precision.
Date, time and timestampISO local text. A timestamp is not implicitly converted to UTC.
Binary, BLOB and CLOBInline wrapper or a negotiated LOB reference.
Geometry and geographyPlain WKB, optionally with explicit SRID or CRS.
ArrayElement descriptor plus homogeneous values, including nested arrays.
SQL NULLExplicit NullValue, optionally paired with a declared type.

Rows are positional. Associate every value with the schema in ResultSetStart and validate its declared logical type.

A Parameter carries a value and may carry declared_type. Presence of that descriptor activates typed_parameters_v1 and distinguishes a typed null from legacy inferred null. Array descriptors are recursive, and non-null elements must match the declared element type.

Missing spatial metadata means unknown, not EPSG:4326. The protocol never implies coordinate transformation.

Transactions v26.5+

Transactions belong to the logical session, not the network channel. When transaction_ids_v1 is advertised, BeginTransaction returns an opaque ID that can be asserted in SQL, commit and rollback requests. A stale ID must fail before Kubling acts on a different active transaction.

GetTransactionStatus is available only with transaction_status_v1. Its retention bound comes from the authenticated capability snapshot. UNKNOWN means that Kubling cannot establish the historical outcome; it does not mean rolled back. Likewise, IsInTransaction.active = false proves only that no transaction is currently active.

Observe the advertised affinity. Losing the owning node can make a session, transaction observation or LOB reference unavailable even while another Kubling node is healthy.

LOB lifecycle v26.5+

An accepted lob_read_v1 result may contain an immutable, session-scoped LobReference rather than inline data. Read it in chunks no larger than the negotiated limit, then call ReleaseLob when finished.

lob_write_v1 uploads a BLOB or UTF-8 CLOB before execution and returns a reference that can be used as a parameter. CLOB sizes and offsets are UTF-8 byte counts, not character counts.

References remain valid until their declared expiry, explicit release, session closure or node loss. They are opaque identifiers, not bearer credentials, and must be used with the same session and capability context.

Catalog reflection v26.5+

The client contract does not define a separate catalog RPC. Query SYS and SYSADMIN views through Execute, including SYS.Tables, SYS.Columns, SYS.KeyColumns, SYS.ReferenceKeyColumns and SYSADMIN.Views.

This keeps schema discovery in the same authenticated SQL model as ordinary data access.

Errors, cancellation and deadlines v26.5+

Application failures use standard gRPC status codes. With structured_errors_v1, google.rpc.Status.details may contain one KublingError with a stable code, optional SQLSTATE, category, retryability, transaction observation and whether SQL is known to have started.

When KublingError.code contains a Kubling error identifier, it uses the KBLnnnnn format. Domain-specific families such as LQ_* retain their own namespaces. See the 26.5 naming migration.

The human-readable gRPC message is diagnostic. Missing structured detail never implies that a retry is safe. In particular, do not retry a mutation unless the structured contract and application semantics both allow it.

Cancelling a client context or reaching its deadline releases execution resources and leaves the logical session usable. A cancelled or failed stream does not emit ExecutionEnd. Cancellation can race with remote work, so it is not proof that a transaction or mutation had no effect.

Generate clients

The contract repository uses Buf and keeps generation configuration beside the protobuf sources. From a pinned released checkout:

./scripts/generate.sh

Generated code provides the transport contract. Applications remain responsible for trusted channel credentials, deadlines, token protection, capability renewal, ordered event validation, transaction coordination and LOB release.

Last updated on