Skip to content

feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint - #55

Merged
krinart merged 4 commits into
trunkfrom
feat/nsql-endpoint
Aug 19, 2026
Merged

krinart merged 4 commits into
trunkfrom
feat/nsql-endpoint

Conversation

@krinart

@krinart krinart commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Adds text-to-SQL support to the Java SDK, matching what gospice already exposes: nsql() translates a natural-language question into SQL via the runtime's configured LLM and runs it, and nsqlGenerateSql() generates the SQL without running it.

Includes new request/response model classes, unit tests against a local mock HTTP server (no live runtime needed), and a short README section.

Text-to-SQL was reachable from other SDKs but not from Java. nsql() runs the
generated query and returns the rows alongside the SQL; nsqlGenerateSql()
stops after generation so the query can be inspected or run separately.
Copilot AI balanced review requested due to automatic review settings August 19, 2026 18:24

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Java SDK support for runtime text-to-SQL operations.

Changes:

  • Adds nsql() and nsqlGenerateSql() HTTP APIs.
  • Introduces NSQL request, response, schema, and field models.
  • Adds mock-server tests and usage documentation.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
README.md Documents NSQL usage.
SpiceClient.java Implements NSQL HTTP operations.
NsqlRequest.java Models NSQL request options.
NsqlResponse.java Models query results.
NsqlSchema.java Models result schemas.
NsqlField.java Models schema fields.
NsqlTest.java Tests requests, responses, validation, and errors.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/main/java/ai/spice/SpiceClient.java Outdated
Comment thread src/main/java/ai/spice/NsqlRequest.java Outdated
@krinart krinart self-assigned this Aug 19, 2026
withApiKey() makes SpiceClient's constructor perform a real Flight
handshake, but the API-key test only stood up the HTTP mock server,
not a Flight server. The handshake against a dead default Flight
address failed unpredictably by platform (reliable on Windows CI,
intermittent on Linux/macOS). Start a TestFlightSqlServer with
matching credentials for that case.
Copilot AI review requested due to automatic review settings August 19, 2026 18:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/main/java/ai/spice/SpiceClient.java:1624

  • Gson returns null rather than throwing for an empty body or the valid JSON literal null, so a successful but malformed runtime response makes nsql() return null despite its response contract. Reject a null decoded value so these responses consistently surface as ExecutionException, just like other malformed bodies.
            return GSON.fromJson(new String(body, StandardCharsets.UTF_8), NsqlResponse.class);
        } catch (JsonSyntaxException err) {

src/main/java/ai/spice/NsqlRequest.java:48

  • new Gson() serializes primitive booleans even at their default value, so a query-only request always includes "sample_data_enabled":false even though the option was never set. This contradicts the “only includes set fields” behavior and the referenced gospice API, which marks this field omitempty. Represent the unset state (for example with a nullable Boolean plus a false-returning getter) or build the request JSON explicitly, and assert this key is absent in the query-only test.
    @SerializedName("sample_data_enabled")
    private boolean sampleDataEnabled;

- Reject a null/empty-body decoded response instead of letting nsql()
  return null in violation of its contract.
- Box sampleDataEnabled so an unset value is omitted from the request
  body instead of always sending "sample_data_enabled":false.
- Defensively copy NsqlRequest.datasets on the way in and return an
  unmodifiable view on the way out.
Copilot AI review requested due to automatic review settings August 19, 2026 19:40

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/main/java/ai/spice/SpiceClient.java:1672

  • NSQL can legitimately run beyond this shared 60-second control-plane timeout: the runtime may perform up to 10 generation/execution retries, and the Spice CLI gives this same endpoint a five-minute silence deadline. This cancels valid long-running requests after one minute, unlike gospice's caller-controlled context. Use an NSQL-specific timeout (or expose one to callers).
                    .timeout(HTTP_REQUEST_TIMEOUT)

src/main/java/ai/spice/NsqlRequest.java:90

  • withDatasets(Collections.emptyList()) keeps a non-null empty list, so Gson sends "datasets":[]. This differs from the stated gospice parity: its omitempty contract omits an empty list because it means “all datasets” (spice-rs does the same). Normalize empty input to null so optional-field encoding remains consistent.
        this.datasets = datasets == null ? null : new ArrayList<>(datasets);

src/main/java/ai/spice/SpiceClient.java:1663

  • Strings.isNullOrEmpty accepts whitespace-only text, so " " reaches the runtime despite the validation contract requiring a natural-language query; the current spice-rs validation explicitly rejects this case. Treat blank strings as invalid before making the HTTP call.
        if (Strings.isNullOrEmpty(request.getQuery())) {

@krinart krinart changed the title feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint Aug 19, 2026
@krinart krinart changed the title feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint Aug 19, 2026
@krinart krinart mentioned this pull request Aug 19, 2026
@krinart
krinart enabled auto-merge (squash) August 19, 2026 22:02
Copilot AI review requested due to automatic review settings August 19, 2026 22:05
@krinart
krinart merged commit dcd719d into trunk Aug 19, 2026
21 checks passed
@krinart
krinart deleted the feat/nsql-endpoint branch August 19, 2026 22:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

krinart added a commit that referenced this pull request Aug 20, 2026
* release: prepare v0.8.0

Bumps pom.xml/Version.java to 0.8.0 and adds release notes covering the
four additive feature PRs (#53-#56): search, Nsql/NsqlGenerateSql,
active-query management, and async queries.

japicmp.oldVersion stays at 0.6.0 rather than bumping to 0.7.0: v0.7.0
was tagged and GitHub-released but its Maven Central publish never
completed, so it isn't a resolvable dependency. See the pom.xml comment
for detail.

* docs: reflect that #54 (search) and #55 (nsql) have merged

* docs: scope v0.8.0 to search + nsql only

#53 (active queries) and #56 (async queries) will not merge for this
release; remove them from the release notes' What's New and reflect
that in Release status instead of listing them as still-pending
dependencies.

* Update release notes for v0.8.0

Removed release status section and notes on features not included in v0.8.0.

* Update release notes for v0.8.0

Removed testing section from release notes for v0.8.0.

* Update release notes for v0.8.0

Removed highlights section from release notes for v0.8.0.

* Change japicmp.oldVersion from 0.6.0 to 0.7.0

Updated the old version for japicmp to 0.7.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants