feat(http): REST API for SQL validation#6383
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis pull request removes the file-watching subsystem (KqueueFileWatcher, FileWatcher, LinuxFileWatcher, WindowsAccessor implementations) and replaces ObjList with ObjHashSet throughout HTTP context path collections. It introduces SqlValidationProcessor, a new HTTP processor for SQL validation, and updates HTTP server endpoint wiring to support SQL validation. Related tests and module exports are updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant HttpServer
participant SqlValidationProcessor
participant SqlCompiler
participant Cairo
Client->>HttpServer: POST /api/v1/sql/validate<br/>(query)
HttpServer->>SqlValidationProcessor: onRequestComplete()
SqlValidationProcessor->>SqlCompiler: compile(query)
alt SELECT query
SqlCompiler-->>SqlValidationProcessor: CompiledQuery (SELECT)
SqlValidationProcessor->>Cairo: executeNewSelect()
Cairo-->>SqlValidationProcessor: RecordCursor with metadata
SqlValidationProcessor->>SqlValidationProcessor: serialize columns to JSON
SqlValidationProcessor-->>Client: 200 OK<br/>{query, columns[]}
else DDL/DML query
SqlCompiler-->>SqlValidationProcessor: CompiledQuery (INSERT/CREATE/etc)
SqlValidationProcessor->>SqlValidationProcessor: buildConfirmation(type)
SqlValidationProcessor-->>Client: 200 OK<br/>{type: "INSERT"/<br/>"CREATE"/etc}
else Syntax error
SqlCompiler-->>SqlValidationProcessor: SqlException
SqlValidationProcessor->>SqlValidationProcessor: formatErrorResponse()
SqlValidationProcessor-->>Client: 400 Bad Request<br/>{error, position}
end
sequenceDiagram
participant OldFlow as File Watcher Flow<br/>(Removed)
participant NewFlow as Collection Type<br/>Migration
participant Processor as SQL Validation<br/>(New)
OldFlow->>OldFlow: FileWatcher monitors config files
OldFlow->>OldFlow: Triggers on changes via<br/>platform-specific watchers<br/>(kqueue/inotify/Windows)
NewFlow->>NewFlow: HTTP context paths<br/>now use ObjHashSet<br/>(instead of ObjList)
NewFlow->>NewFlow: Improves lookup performance<br/>for URL routing
Processor->>Processor: New HTTP endpoint<br/>validates SQL queries
Processor->>Processor: Returns column metadata<br/>and query confirmation
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45–60 minutes Areas requiring extra attention:
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example instruction:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (12)
core/src/test/java/io/questdb/test/cutlass/http/IODispatcherTest.java (2)
2326-2330: Avoid double‑brace initialization; build the set explicitly.Double‑brace creates an anonymous subclass and an extra synthetic reference. Prefer constructing, adding, returning; pre‑size to 1.
Apply:
- public ObjHashSet<String> getUrls() { - return new ObjHashSet<>() {{ - add("/upload"); - }}; - } + public ObjHashSet<String> getUrls() { + ObjHashSet<String> urls = new ObjHashSet<>(1); + urls.add("/upload"); + return urls; + }
8351-8355: Same here: replace double‑brace with explicit construction.Keeps allocations minimal and avoids anonymous subclassing.
Apply:
- public ObjHashSet<String> getUrls() { - return new ObjHashSet<>() {{ - add("/query"); - }}; - } + public ObjHashSet<String> getUrls() { + ObjHashSet<String> urls = new ObjHashSet<>(1); + urls.add("/query"); + return urls; + }core/src/test/java/io/questdb/test/cutlass/http/HttpServerTest.java (1)
171-175: Avoid double‑brace initialization in tests.Use a plain local, avoids synthetic class and is clearer.
- public ObjHashSet<String> getUrls() { - return new ObjHashSet<>() {{ - add("/service"); - }}; - } + public ObjHashSet<String> getUrls() { + ObjHashSet<String> urls = new ObjHashSet<>(); + urls.add("/service"); + return urls; + }core/src/main/java/io/questdb/cutlass/http/HttpServerConfiguration.java (1)
34-38: Minor: avoid double‑brace init in default method.- default ObjHashSet<String> getContextPathMetrics() { - return new ObjHashSet<>() {{ - add("/metrics"); - }}; - } + default ObjHashSet<String> getContextPathMetrics() { + ObjHashSet<String> s = new ObjHashSet<>(); + s.add("/metrics"); + return s; + }core/src/test/java/io/questdb/test/cutlass/http/HttpConnectionCountTest.java (2)
184-188: Prefer simple initialization over double‑brace.- public ObjHashSet<String> getUrls() { - return new ObjHashSet<>() {{ - add(ILP_TEST_PATH); - }}; - } + public ObjHashSet<String> getUrls() { + ObjHashSet<String> urls = new ObjHashSet<>(); + urls.add(ILP_TEST_PATH); + return urls; + }
328-332: Same here: avoid double‑brace initialization.- public ObjHashSet<String> getUrls() { - return new ObjHashSet<>(){{ - add(EXEC_TEST_URI); - }}; - } + public ObjHashSet<String> getUrls() { + ObjHashSet<String> urls = new ObjHashSet<>(); + urls.add(EXEC_TEST_URI); + return urls; + }core/src/test/java/io/questdb/test/cutlass/http/line/LineHttpSenderMockServerTest.java (2)
682-706: ExpandedtestWithMockoverloads keep call sites simple and resource handling correctThe new overloads that accept a
senderBuilderFactoryand optionalverifyBeforeCloseflag centralize setup logic while preserving the previous behavior. The inner implementation still uses try-with-resources forWorkerPoolandHttpServer, so lifetimes and leak checks remain correct.If you touch this again, consider documenting the
verifyBeforeCloseflag briefly (e.g., Javadoc) so future readers know when to prefer one verification timing over the other.Also applies to: 709-712
715-719:getUrls()migration toObjHashSet<String>matches updated HTTP APISwitching the mock
HttpRequestHandlerFactoryimplementations to returnObjHashSet<String>and explicitly adding/writeand/settingsaligns the test scaffolding with the productionHttpRequestHandlerFactorycontract and with the new context-path set type.Double‑brace initialization is fine in tests, but a small helper like
urls("/write")/urls("/settings")would avoid anonymous subclasses and be slightly clearer.Also applies to: 729-733
core/src/test/java/io/questdb/test/PropServerConfigurationTest.java (1)
1735-1781: Fuzz test for web-console-derived context paths aligns with ObjHashSet usage but could compare sets more directlyThe updated fuzz test:
- Models each configurable path as a
FuzzItemcarrying the property key, pinned value, default web‑console suffix set (CONTEXT_PATH_*), and a getter returning the correspondingObjHashSet<String>.- Randomly pins a subset of paths, then for each item builds an
expectedObjHashSetof pinned values pluswebConsolePath + suffixfor each default suffix, and comparesexpected.toString()against the actual set’stoString().- Verifies ILP context paths remain equal to
HttpFullFatServerConfiguration.CONTEXT_PATH_ILP.toString()and that redirects match the new web-console path.The logic is sound and gives good coverage of path recomputation.
Instead of relying on
ObjHashSet’stoString()ordering, you might make the test resilient to insertion-order changes by:
- comparing the sets directly (if
ObjHashSet.equalsis defined appropriately), or- asserting that both
expectedand actual contain the same elements (e.g., by iterating and checking membership) without depending on iteration order.
This keeps the test focused on membership semantics rather than internal ordering.Also applies to: 1797-1819, 2095-2100
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java (1)
223-255: ReuseprepareExecutionContextinresumeSendOnce you introduce a helper to bind
sqlExecutionContextto the connection (as suggested earlier),resumeSend()can call it instead of duplicating the.with(...)logic. This keeps the behavior consistent between initial execution and resume paths and reduces the chance of divergence in future edits.core/src/main/java/io/questdb/cutlass/http/HttpFullFatServerConfiguration.java (2)
34-59: Recommend immutable collections and avoiding double-brace initialization.The constants use double-brace initialization, which creates anonymous inner classes and is considered an anti-pattern. Additionally, these
ObjHashSetinstances are mutable and publicly accessible, allowing callers to modify them and potentially causing thread-safety issues or unexpected behavior.Consider refactoring to use an immutable collection pattern or factory methods that return unmodifiable sets.
Example refactor using factory methods:
- ObjHashSet<String> CONTEXT_PATH_EXEC = new ObjHashSet<>() {{ - add("/exec"); - add("/api/v1/sql/execute"); - }}; + ObjHashSet<String> CONTEXT_PATH_EXEC = createImmutableSet("/exec", "/api/v1/sql/execute");And add a static helper method (if ObjHashSet supports unmodifiable views):
static ObjHashSet<String> createImmutableSet(String... paths) { ObjHashSet<String> set = new ObjHashSet<>(); for (String path : paths) { set.add(path); } // Return unmodifiable view if available return set; }
64-68: Recommend pre-defining constants instead of creating instances on every call.The methods
getContextPathDefault()andgetContextPathILPPing()create newObjHashSetinstances on every invocation using double-brace initialization. This is inefficient and inconsistent with other accessor methods that return pre-defined constants.Consider defining these as constants like the others:
+ ObjHashSet<String> CONTEXT_PATH_DEFAULT = new ObjHashSet<>() {{ + add(DEFAULT_PROCESSOR_URL); + }}; + ObjHashSet<String> CONTEXT_PATH_ILP_PING = new ObjHashSet<>() {{ + add("/ping"); + }}; + default ObjHashSet<String> getContextPathDefault() { - return new ObjHashSet<>() {{ - add(DEFAULT_PROCESSOR_URL); - }}; + return CONTEXT_PATH_DEFAULT; } default ObjHashSet<String> getContextPathILPPing() { - return new ObjHashSet<>() {{ - add("/ping"); - }}; + return CONTEXT_PATH_ILP_PING; }Also applies to: 82-86
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
core/src/main/java/io/questdb/KqueueFileWatcher.java(0 hunks)core/src/main/java/io/questdb/PropServerConfiguration.java(6 hunks)core/src/main/java/io/questdb/ServerMain.java(0 hunks)core/src/main/java/io/questdb/cutlass/Services.java(6 hunks)core/src/main/java/io/questdb/cutlass/http/HttpFullFatServerConfiguration.java(1 hunks)core/src/main/java/io/questdb/cutlass/http/HttpRequestHandlerFactory.java(1 hunks)core/src/main/java/io/questdb/cutlass/http/HttpServer.java(12 hunks)core/src/main/java/io/questdb/cutlass/http/HttpServerConfiguration.java(1 hunks)core/src/main/java/io/questdb/cutlass/http/HttpServerConfigurationWrapper.java(2 hunks)core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java(1 hunks)core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessorState.java(1 hunks)core/src/main/java/io/questdb/cutlass/http/processors/StaticContentProcessorFactory.java(2 hunks)core/src/main/java/io/questdb/std/filewatch/FileWatcher.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/FileWatcherFactory.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/FileWatcherWindows.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/LinuxAccessor.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/LinuxAccessorFacade.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/LinuxAccessorFacadeImpl.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/LinuxFileWatcher.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/WindowsAccessor.java(0 hunks)core/src/main/java/io/questdb/std/filewatch/WindowsAccessorImpl.java(0 hunks)core/src/main/java/module-info.java(0 hunks)core/src/test/java/io/questdb/test/PropServerConfigurationTest.java(5 hunks)core/src/test/java/io/questdb/test/cutlass/http/HttpConnectionCountTest.java(3 hunks)core/src/test/java/io/questdb/test/cutlass/http/HttpMinTestBuilder.java(3 hunks)core/src/test/java/io/questdb/test/cutlass/http/HttpQueryTestBuilder.java(11 hunks)core/src/test/java/io/questdb/test/cutlass/http/HttpServerConfigurationBuilder.java(3 hunks)core/src/test/java/io/questdb/test/cutlass/http/HttpServerTest.java(2 hunks)core/src/test/java/io/questdb/test/cutlass/http/IODispatcherTest.java(3 hunks)core/src/test/java/io/questdb/test/cutlass/http/SqlValidationTest.java(1 hunks)core/src/test/java/io/questdb/test/cutlass/http/line/LineHttpSenderMockServerTest.java(6 hunks)core/src/test/java/io/questdb/test/std/filewatch/FileWatcherTest.java(0 hunks)core/src/test/java/io/questdb/test/std/filewatch/LinuxFileWatcherTest.java(0 hunks)core/src/test/java/module-info.java(0 hunks)utils/src/test/java/io/questdb/cliutil/Table2IlpTest.java(2 hunks)
💤 Files with no reviewable changes (15)
- core/src/main/java/io/questdb/std/filewatch/FileWatcher.java
- core/src/main/java/module-info.java
- core/src/main/java/io/questdb/std/filewatch/LinuxFileWatcher.java
- core/src/main/java/io/questdb/std/filewatch/FileWatcherFactory.java
- core/src/main/java/io/questdb/std/filewatch/LinuxAccessorFacadeImpl.java
- core/src/main/java/io/questdb/KqueueFileWatcher.java
- core/src/main/java/io/questdb/ServerMain.java
- core/src/test/java/io/questdb/test/std/filewatch/FileWatcherTest.java
- core/src/main/java/io/questdb/std/filewatch/LinuxAccessor.java
- core/src/main/java/io/questdb/std/filewatch/LinuxAccessorFacade.java
- core/src/test/java/io/questdb/test/std/filewatch/LinuxFileWatcherTest.java
- core/src/main/java/io/questdb/std/filewatch/WindowsAccessorImpl.java
- core/src/main/java/io/questdb/std/filewatch/WindowsAccessor.java
- core/src/test/java/module-info.java
- core/src/main/java/io/questdb/std/filewatch/FileWatcherWindows.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (35)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-other)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-pgwire)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-cairo-sub)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-cairo-root)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-fuzz2)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-fuzz1)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-griffin-sub)
- GitHub Check: New pull request (Rust Test and Lint on linux-jdk17)
- GitHub Check: New pull request (SelfHosted Cairo tests on linux-x86-graal)
- GitHub Check: New pull request (SelfHosted Running tests with cover on linux-griffin-root)
- GitHub Check: New pull request (SelfHosted Cairo tests on linux-x64-zfs)
- GitHub Check: New pull request (SelfHosted Cairo tests on linux-arm64)
- GitHub Check: New pull request (Hosted Running tests on windows-other-2)
- GitHub Check: New pull request (Hosted Running tests on windows-other-1)
- GitHub Check: New pull request (Hosted Running tests on windows-pgwire)
- GitHub Check: New pull request (Hosted Running tests on windows-cairo-2)
- GitHub Check: New pull request (Hosted Running tests on windows-cairo-1)
- GitHub Check: New pull request (Hosted Running tests on windows-fuzz2)
- GitHub Check: New pull request (Hosted Running tests on windows-fuzz1)
- GitHub Check: New pull request (Hosted Running tests on windows-griffin-sub)
- GitHub Check: New pull request (Hosted Running tests on windows-griffin-base)
- GitHub Check: New pull request (Hosted Running tests on mac-other)
- GitHub Check: New pull request (Hosted Running tests on mac-pgwire)
- GitHub Check: New pull request (Hosted Running tests on mac-cairo-fuzz)
- GitHub Check: New pull request (SelfHosted Other tests on linux-arm64)
- GitHub Check: New pull request (Hosted Running tests on mac-cairo)
- GitHub Check: New pull request (SelfHosted Other tests on linux-x86-graal)
- GitHub Check: New pull request (SelfHosted Griffin tests on linux-arm64)
- GitHub Check: New pull request (SelfHosted Griffin tests on linux-x64-zfs)
- GitHub Check: New pull request (Hosted Running tests on mac-griffin)
- GitHub Check: New pull request (SelfHosted Other tests on linux-x64-zfs)
- GitHub Check: New pull request (SelfHosted Griffin tests on linux-x86-graal)
- GitHub Check: New pull request (Check Changes Check changes)
- GitHub Check: build
- GitHub Check: build
🔇 Additional comments (41)
core/src/test/java/io/questdb/test/cutlass/http/HttpServerConfigurationBuilder.java (3)
54-55: LGTM: Fragmentation configuration fields added correctly.The fields follow the existing pattern and sensible defaults (Integer.MAX_VALUE effectively disables fragmentation unless explicitly configured).
162-170: LGTM: Configuration getters implemented correctly.The overridden methods correctly expose the fragmentation chunk sizes to the HTTP context configuration.
301-309: LGTM: Builder methods follow the fluent API pattern correctly.The methods are consistent with other builder methods in the class and correctly set the fragmentation chunk sizes.
core/src/test/java/io/questdb/test/cutlass/http/HttpMinTestBuilder.java (1)
43-109: LGTM: Test implementations updated to match interface change.Both anonymous
HttpRequestHandlerFactoryimplementations correctly returnObjHashSet<String>fromgetUrls(), aligning with the interface modification.core/src/main/java/io/questdb/cutlass/http/processors/StaticContentProcessorFactory.java (1)
30-42: LGTM: Migration from ObjList to ObjHashSet for URL collections.Verification confirms all implementations of
HttpRequestHandlerFactory.getUrls()correctly returnObjHashSet<String>across both test and production code (approximately 29 implementations). The change aligns with the updated interface and is semantically appropriate for URL path collections.core/src/main/java/io/questdb/cutlass/http/HttpRequestHandlerFactory.java (1)
27-30: LGTM: Interface change improves semantics for URL collections.Changing from
ObjList<String>toObjHashSet<String>is appropriate for URL collections—it enforces uniqueness and provides O(1) lookup performance.Verification confirms:
ObjHashSetsupports indexed access viaget(int index), delegating to its internalObjList- The single usage in
HttpServer.java:293-296uses indexed iteration but does not depend on ordering- All implementations (
TestJsonQueryProcessorFactory,StaticContentProcessorFactory) already returnObjHashSet<String>- No order-dependent patterns found in the codebase
core/src/test/java/io/questdb/test/cutlass/http/IODispatcherTest.java (1)
112-112: Import update looks good.Adding
ObjHashSetaligns with the interface change toHttpRequestHandlerFactory.getUrls(). No issues.core/src/test/java/io/questdb/test/cutlass/http/HttpServerTest.java (1)
45-45: Import switch to ObjHashSet looks good.core/src/main/java/io/questdb/cutlass/http/HttpServerConfiguration.java (2)
30-30: Import change to ObjHashSet is correct.
40-44: Wildcard interpretation is incorrect; the code is correct.The
"*"is not a wildcard pattern but a special sentinel value (HttpFullFatServerConfiguration.DEFAULT_PROCESSOR_URL) that designates a fallback/default handler. The HTTP routing inHttpServer.bind()explicitly checksif (DEFAULT_PROCESSOR_URL.equals(url))and assigns it toselector.defaultRequestProcessor(line 299-300). Request matching first attempts exact URL lookup inrequestHandlerMap, then falls back to the default processor if no match is found (line 401).When metrics are disabled,
getContextPathStatus()intentionally returns"*"to indicate the HealthCheckProcessor should act as a fallback handler rather than registering a specific/statuspath. This design is sound and does not create shadowing issues—the framework properly handles it.Likely an incorrect or invalid review comment.
core/src/test/java/io/questdb/test/cutlass/http/HttpConnectionCountTest.java (1)
50-50: Import of ObjHashSet acknowledged.core/src/main/java/io/questdb/PropServerConfiguration.java (5)
85-85: Import to ObjHashSet is correct.
226-235: New context path sets (execute/validate/etc.) look good.
1073-1076: Default additions include both legacy and new SQL endpoints — OK.
2399-2403: getUrls target type to ObjHashSet aligns with API change.
4648-4655: HTTP server config getters now expose ObjHashSet for paths; wiring for exec + SQL validation is consistent.Also applies to: 4658-4690
utils/src/test/java/io/questdb/cliutil/Table2IlpTest.java (1)
38-38: SqlValidationProcessor wiring in test helper matches production Services.createHttpServerThe new
sqlValidationProcessorBuilderuses the same JSON query configuration and worker-count pattern asJsonQueryProcessor, andHttpServer.addDefaultEndpointsis called with the updated signature includingilpV2WriteProcessorBuilderandsqlValidationProcessorBuilder. This keeps the Table2Ilp CLI test HTTP server in sync with the main Services wiring.Also applies to: 505-519
core/src/test/java/io/questdb/test/cutlass/http/line/LineHttpSenderMockServerTest.java (2)
109-117: Using text blocks for multi-line expected HTTP bodies improves readabilityReplacing concatenated strings with text blocks for multi-line payload expectations (
testAutoFlushRows,testJsonError,testTwoLines) keeps the intent clear while preserving the line structure needed for protocol correctness.Also applies to: 333-337, 609-612
149-195: New tests robustly cover /settings failure handling (single and multi-server)
testBadSettingsandtestBadSettingsManyServersexercise the error path when the/settingsendpoint fails, including the multi-server rotation scenario. The use ofMockErrorSettingsProcessorand explicitLineSenderExceptionassertions gives good coverage of the new settings-negotiation behavior.core/src/main/java/io/questdb/cutlass/Services.java (2)
110-115: HTTP server now cleanly wires in SQL validation alongside JSON and ILPThe introduction of
sqlValidationProcessorBuilderand passing it intoHttpServer.addDefaultEndpointsmirrors the existingJsonQueryProcessor/LineHttpProcessorImplpattern and cleanly exposes the new validation endpoint without altering existing behavior.Also applies to: 121-129
216-218:createMinHttpServerupdated to useObjHashSet<String>for context pathsReturning
ObjHashSet<String>from the health and metricsHttpRequestHandlerFactory.getUrls()implementations, delegating toconfiguration.getContextPathStatus()andgetContextPathMetrics(), keeps the minimal HTTP server consistent with the new context-path collection type.Also applies to: 236-238
core/src/test/java/io/questdb/test/cutlass/http/SqlValidationTest.java (3)
39-53: Static setup/teardown forTestHttpClientlooks correct; configuration reassignment merits a quick check
setUpStatic/tearDownStaticcorrectly free and recreatetestHttpClientaround the shared test lifecycle, avoiding leaks between runs. You also reassignconfiguration = new DefaultCairoConfiguration(root)afterAbstractCairoTest.setUpStatic(). IfAbstractCairoTest’s engine was created from a different configuration instance, just confirm that no code assumesengine.getConfiguration() == configuration; otherwise, this override is fine.
55-122:testValidationAllColumnTypesgives strong coverage of validation metadataThis test creates a table with a wide variety of column types (including arrays and multiple GEOHASH widths) and asserts that
/api/v1/sql/validatereturns the expectedcolumnsarray andtimestampindex forselect * from xyz limit 10. That’s a good end‑to‑end check of the new endpoint’s schema introspection.Please double‑check that the
timestampvalue13is defined as “zero‑based index of the designated timestamp column” in theSqlValidationProcessorcontract; if this semantics ever changes (e.g., to a column name), this test will need adjustment.
124-160: OK and syntax-error validation tests pin down the JSON contract
testValidationOkvalidates a simple aggregation query, andtestValidationSyntaxErrorasserts that invalid SQL returns a payload withquery,error, andposition. The hard‑codedpositionmakes this sensitive to parser behavior, but it’s valuable to keep the error-reporting contract stable.If the SQL parser’s error positioning logic changes frequently, consider asserting that
positionis non‑negative and that theerrormessage contains"Invalid column: b"rather than pinning the exact numeric offset.core/src/test/java/io/questdb/test/PropServerConfigurationTest.java (1)
1692-1716: Web-console path dependency test correctly includes new SQL execute endpoint
testWebConsolePathChangeUpdatesDefaultDependenciesnow expects:
- warnings under
/new-path/warnings,- exec under both
/new-path/execand/new-path/api/v1/sql/execute,- export/import/table-status/settings under the new web-console prefix,
while ILP paths remain unchanged. This is a clear, direct regression test for the new execute endpoint and for context-path rewiring.core/src/main/java/io/questdb/cutlass/http/HttpServer.java (4)
54-97: Constructor cache initialization & configuration pattern match look goodThe switch to pattern matching on
HttpFullFatServerConfigurationand keeping the min-server path on the no-op cache is clean and preserves behavior; the addedObjHashSetimport is consistent with the rest of the changes in this PR.
130-247: SQL validation endpoint wiring is consistent with existing endpointsExtending
addDefaultEndpointswithsqlValidationProcessorBuilderand binding it viagetContextPathSqlValidation()mirrors the existing export/import/tableStatus wiring. Keeping/execbound throughgetContextPathExec()ensures backward compatibility while adding the new/api/v1/sql/validatepath via configuration.
292-314: Migration toObjHashSet<String>inbindis safeIterating
ObjHashSet<String>viasize()andget(j)works with its dense storage model, and handler registration logic is unchanged apart from collection type. Since routing is by exact URL match and not order, the move fromObjListtoObjHashSetshould not affect behavior.
342-361:handleClientOperationrefactor is formatting-onlyThe extracted helper keeps the same control flow and exception-to-IOOperation mapping as before; no behavioral changes introduced.
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessorState.java (1)
59-395: State machine and metadata JSON construction are well-structuredThe per-connection state, explicit type whitelist in
addColumnTypeAndName, and the resume/bookmark logic fordoQueryPrefix/doQueryMetadata/querySuffixWithErrormatch the existing JSON query patterns and should behave correctly under buffer pressure and retries. The main dependency is that callers must invokeclear()between requests to resetqueryStateand related fields, which you handle on the processor side.core/src/test/java/io/questdb/test/cutlass/http/HttpQueryTestBuilder.java (3)
82-121: Fragmentation chunk size configuration is wired correctly for testsPropagating
forceSendFragmentationChunkSizeandforceRecvFragmentationChunkSizeinto the HTTP server configuration builder gives tests control over artificial fragmentation without affecting default behavior (Integer.MAX_VALUEeffectively disables it).
208-317: Test HTTP wiring for SQL validation and ObjHashSet URLs looks consistentUsing
ObjHashSet<String>for/upload,/query,/status, and the config-driven paths (includinggetContextPathSqlValidation()andgetContextPathExport()) aligns the test harness with the production server. TheSqlValidationProcessorbinding shares the same configuration/engine as other processors, so end-to-end tests should exercise the new endpoint realistically.
362-370: Fluent setters for fragmentation sizes are straightforwardThe new
withForceRecvFragmentationChunkSizeandwithForceSendFragmentationChunkSizemethods follow the existing builder pattern and keep the default behavior intact when unused.core/src/main/java/io/questdb/cutlass/http/HttpServerConfigurationWrapper.java (1)
39-121: Context-path methods correctly migrated toObjHashSet<String>Returning
ObjHashSet<String>from the variousgetContextPath*methods and delegating straight to the underlyingHttpFullFatServerConfigurationkeeps the wrapper consistent with the rest of the codebase’s move away fromObjList<String>.core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java (3)
431-464:doResumeSenderror handling and buffer-bookmarking match existing patternsThe resume loop correctly:
- delegates to
state.resume(response)based onqueryState,- handles SQL/implicit-cast errors by sending a SQL error response,
- converts
DataUnavailableExceptionintoQueryPausedExceptionwith a reset to the last bookmark, and- handles
NoSpaceLeftInResponseBufferExceptionvia chunk flushing or by escalating when a single unit exceeds buffer size.The final
readyForNextRequest(context)ensures the connection is ready once the JSON suffix has been sent.
506-534: URL parsing and empty-query handling look sound
parseUrl()cleanly distinguishes:
- missing/empty
queryparameter (logging and sending a version-sensitive empty-query notice), and- bad UTF‑8 in the
queryparameter (logging and returning a structured 400 response).This is in line with the behavior of other HTTP SQL endpoints and avoids attempting to compile invalid input.
545-571: Shared exception JSON helper is a good reuse of existing behavior
sendException()reusesJsonQueryProcessorState.prepareExceptionJson, keeping the error payload format consistent between validation and execution endpoints while letting you vary HTTP status codes. This also centralizes any future changes to the error schema.core/src/main/java/io/questdb/cutlass/http/HttpFullFatServerConfiguration.java (4)
31-31: LGTM: Import change aligns with collection type migration.The import change from
ObjListtoObjHashSetis consistent with the refactoring throughout this file.
54-56: LGTM: New SQL validation endpoint follows versioned API convention.The addition of
CONTEXT_PATH_VALIDATEwith the path/api/v1/sql/validatefollows good API versioning practices, consistent with other v1 endpoints like/api/v1/sql/execute.
70-94: LGTM: Accessor methods correctly return predefined constants.The accessor methods properly delegate to the static constants, providing a clean interface for accessing context paths.
96-98: LGTM: New SQL validation accessor method.The
getContextPathSqlValidation()method correctly returns theCONTEXT_PATH_VALIDATEconstant for the new SQL validation endpoint.
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java
Outdated
Show resolved
Hide resolved
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java
Show resolved
Hide resolved
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java
Show resolved
Hide resolved
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java
Outdated
Show resolved
Hide resolved
…ror() there could be a better fix - we could bookmark after writing the suffix to response buffer. maybe.
|
@CodeRabbit review the new changes and see if there are regressions |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 5080 🏁 Script executed: Length of output: 1791 🏁 Script executed: Length of output: 349 🏁 Script executed: Length of output: 2191 🏁 Script executed: Length of output: 4813 🏁 Script executed: Length of output: 700 🏁 Script executed: Length of output: 392 🏁 Script executed: Length of output: 1490 🏁 Script executed: Length of output: 823 🏁 Script executed: Length of output: 1032 🏁 Script executed: Length of output: 977 🏁 Script executed: Length of output: 2594 🏁 Script executed: Length of output: 1880 🏁 Script executed: Length of output: 42 🏁 Script executed: Length of output: 2125 🏁 Script executed: Length of output: 928 🏁 Script executed: Length of output: 2779 🏁 Script executed: Length of output: 2076 🏁 Script executed: Length of output: 1462 🏁 Script executed: Length of output: 186 🏁 Script executed: Length of output: 2777 🏁 Script executed: Length of output: 5304 @bluestreak01: I've completed a comprehensive review of the new changes. Here's my analysis: 🔴 Critical Regression Found1. Null State Bug in
|
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessor.java
Show resolved
Hide resolved
core/src/main/java/io/questdb/cutlass/http/processors/ExportQueryProcessorState.java
Outdated
Show resolved
Hide resolved
core/src/main/java/io/questdb/cutlass/http/processors/SqlValidationProcessorState.java
Outdated
Show resolved
Hide resolved
[PR Coverage check]😍 pass : 666 / 831 (80.14%) file detail
|
Introduces new APIs:
This is a non-breaking change. The existing
/execapi is still supported although it becomes deprecated with this PRTandem: https://github.com/questdb/questdb-enterprise/pull/782
Implementation
The new processor was a copy of
jsonprocessor, sans sending data to the client. I added fuzz tests for fragmentation to find out this copy is badly broken. This sent us on a bug hunt in all other processors and to extend fuzz tests. The net result are bugs fixed in:More test infrastructure was added to enable robust fuzz testing of http APIs