Repository navigation
feat: add Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint - #55
Conversation
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.
There was a problem hiding this comment.
Pull request overview
Adds Java SDK support for runtime text-to-SQL operations.
Changes:
- Adds
nsql()andnsqlGenerateSql()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.
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.
There was a problem hiding this comment.
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
nullrather than throwing for an empty body or the valid JSON literalnull, so a successful but malformed runtime response makesnsql()return null despite its response contract. Reject a null decoded value so these responses consistently surface asExecutionException, 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":falseeven though the option was never set. This contradicts the “only includes set fields” behavior and the referenced gospice API, which marks this fieldomitempty. Represent the unset state (for example with a nullableBooleanplus 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.
There was a problem hiding this comment.
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: itsomitemptycontract omits an empty list because it means “all datasets” (spice-rs does the same). Normalize empty input tonullso optional-field encoding remains consistent.
this.datasets = datasets == null ? null : new ArrayList<>(datasets);
src/main/java/ai/spice/SpiceClient.java:1663
Strings.isNullOrEmptyaccepts 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())) {
Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint
Nsql and NsqlGenerateSql for the runtime's /v1/nsql endpointNsql and NsqlGenerateSql for the runtime's /v1/nsql endpoint
# Conflicts: # README.md
* 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.
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, andnsqlGenerateSql()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.