SQL Queries and History¶
The public SDKs execute SQL through a synchronous convenience method:
Python:
SDKClient.run_sql(statement)Go:
(*SDKClient).RunSQL(ctx, statement)
Both call the Catalog service’s NL2SQL run_sql operation. The statement must
use fully qualified table names such as analytics.orders; this is how the
service identifies the target database.
Execute a query in Python¶
Create the high-level client from an authenticated RawClient:
import os
from moi import RawClient, SDKClient
raw = RawClient(
base_url=os.environ["MOI_BASE_URL"],
api_key=os.environ["MOI_API_KEY"],
)
client = SDKClient(raw)
response = client.run_sql(
"SELECT order_id, total "
"FROM analytics.orders "
"ORDER BY order_id DESC "
"LIMIT 20"
)
for result in response.get("results", []):
print(result.get("columns", []))
for row in result.get("rows", []):
print(row)
The Python client returns the decoded response data as dictionaries and lists. Do not bind application logic to undocumented envelope fields.
The lower-level equivalent is:
response = raw.run_nl2sql(
{
"operation": "run_sql",
"statement": "SELECT COUNT(*) FROM analytics.orders",
}
)
Prefer SDKClient.run_sql for direct SQL execution because it validates that
the statement is not empty and supplies the operation value.
Execute a query in Go¶
package main
import (
"context"
"fmt"
"log"
"os"
sdk "github.com/matrixorigin/moi-go-sdk"
)
func main() {
raw, err := sdk.NewRawClient(
os.Getenv("MOI_BASE_URL"),
os.Getenv("MOI_API_KEY"),
)
if err != nil {
log.Fatal(err)
}
client := sdk.NewSDKClient(raw)
response, err := client.RunSQL(
context.Background(),
"SELECT order_id, total "+
"FROM analytics.orders "+
"ORDER BY order_id DESC LIMIT 20",
)
if err != nil {
log.Fatal(err)
}
for _, result := range response.Results {
fmt.Println(result.Columns)
for _, row := range result.Rows {
fmt.Println(row)
}
}
}
Go returns *NL2SQLRunSQLResponse. Each NL2SQLResult contains Columns []string and Rows []NL2SQLRow; a row is a string slice.
Design around the published contract¶
The public Python and Go repositories do not currently expose a query handle
or statement ID from run_sql. They also do not publish SDK methods for:
asynchronous query polling or streaming results;
result pagination or result download;
cancelling or killing a running statement;
retrieving SQL History or an execution profile.
As a result, retry policy belongs to the application. A transport failure does not prove that a statement was never accepted. Avoid automatically retrying a statement that can change data unless the statement and surrounding workflow are explicitly idempotent.
The published examples exercise one statement per call. Multi-statement and transaction semantics are not part of the documented SDK contract, so submit statements separately and use a database driver when the application requires session or transaction control.
Record what your application needs¶
If the caller needs its own query record, capture it before invoking the SDK:
an application-generated request ID;
the exact SQL text or a redacted form;
the selected database and table metadata IDs;
start and finish timestamps;
success or failure, plus a sanitized error;
any result summary that is safe to retain.
Do not log API keys or unrestricted result rows. For error classification and request IDs, see Responses, errors, and pagination. AI Studio operators can inspect UI-side records in SQL History, but that page does not add a query-history method to the public SDK.
Saved SQL and query history are separate concerns. See Workbook and history boundary before designing persistence around SQL Editor workbooks.