Skip to content

fix(sql): fix to recognise view names in quotes#6771

Merged
bluestreak01 merged 3 commits intomasterfrom
ia_view_quotes
Feb 13, 2026
Merged

fix(sql): fix to recognise view names in quotes#6771
bluestreak01 merged 3 commits intomasterfrom
ia_view_quotes

Conversation

@glasstiger
Copy link
Copy Markdown
Contributor

@glasstiger glasstiger commented Feb 11, 2026

Summary

When a view name is quoted (single or double quotes), SqlParser passes the quoted token directly to getTableTokenIfExists(), which fails to find the view. This affects three code paths:

  • SELECT ... FROM 'my_view'parseFromClause
  • SELECT ... JOIN 'my_view' ON ...parseJoin
  • COMPILE VIEW 'my_view'parseCompileView

The fix adds unquote() to all three getTableTokenIfExists() calls so the view is recognized regardless of quoting.

Test plan

  • testQueryViewInQuotes — SELECT FROM with single-quoted and double-quoted view name
  • testQueryViewInQuotesJoin — JOIN with single-quoted and double-quoted view name
  • testCompileViewInQuotes — COMPILE VIEW with single-quoted and double-quoted view name

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 11, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds token unquoting to three table/view lookup sites in SqlParser to properly resolve quoted identifiers. Includes new tests validating that views can be compiled and queried when their names are quoted using single or double quotes.

Changes

Cohort / File(s) Summary
Parser token unquoting
core/src/main/java/io/questdb/griffin/SqlParser.java
Modified three call sites (parseCompileView, parseFromClause, parseJoin) to wrap token lookups with unquote(), ensuring quoted or schema-qualified identifiers are normalized before view/table resolution.
View compilation and query tests
core/src/test/java/io/questdb/test/cairo/view/ViewCompileTest.java, core/src/test/java/io/questdb/test/cairo/view/ViewQueryTest.java
Added new test methods verifying views can be compiled and queried when names are enclosed in single or double quotes, including join scenarios.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

Bug, SQL

Suggested reviewers

  • bluestreak01
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing SQL parser to recognize view names when they are quoted.
Description check ✅ Passed The description provides relevant context about the issue, affected code paths, and the solution, with a clear test plan covering the changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ia_view_quotes

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@glasstiger
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@glasstiger
Copy link
Copy Markdown
Contributor Author

[PR Coverage check]

😍 pass : 3 / 3 (100.00%)

file detail

path covered line new line coverage
🔵 io/questdb/griffin/SqlParser.java 3 3 100.00%

@bluestreak01
Copy link
Copy Markdown
Member

@CodeRabbit what's the latest, did you review?

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 13, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

@bluestreak01, yes, I triggered the review earlier. Let me provide you with a detailed analysis of the changes now.


🏁 Script executed:

#!/bin/bash

# Get the actual diff for SqlParser.java to see the exact changes
echo "=== SqlParser.java changes ==="
git diff origin/master...HEAD -- core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Find unquote method implementation ==="
# Find the unquote method to understand what it does
ast-grep --pattern 'unquote($$$) {
  $$$
}'

echo -e "\n\n=== Check for other getTableTokenIfExists calls that might need unquote ==="
# Search for other places where getTableTokenIfExists is called without unquote
rg -n "getTableTokenIfExists\(" core/src/main/java/io/questdb/griffin/SqlParser.java -A 1 -B 1

echo -e "\n\n=== View the test files to assess coverage ==="
cat core/src/test/java/io/questdb/test/cairo/view/ViewCompileTest.java | grep -A 30 "testCompileViewInQuotes"

echo -e "\n\n=== View query test details ==="
cat core/src/test/java/io/questdb/test/cairo/view/ViewQueryTest.java | grep -A 60 "testQueryViewInQuotes"

Length of output: 7287


🏁 Script executed:

#!/bin/bash

echo "=== Find unquote method definition in SqlParser ==="
# Look for the unquote method definition
rg -n "^\s*(private|protected|public).*unquote\(" core/src/main/java/io/questdb/griffin/ -A 10

echo -e "\n\n=== Context around line 1410 usage ==="
# Get more context around the line 1410 usage that doesn't have unquote
sed -n '1400,1420p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Check if there are other code paths that get table tokens ==="
# Find patterns where tokens might be used to look up views/tables
rg -n "getTableToken\(" core/src/main/java/io/questdb/griffin/SqlParser.java -C 2

echo -e "\n\n=== Look for similar quote handling patterns ==="
# Check how quotes are handled elsewhere in the parser
rg -n "unquote\(" core/src/main/java/io/questdb/griffin/SqlParser.java -B 2 -A 1

Length of output: 12250


🏁 Script executed:

#!/bin/bash

echo "=== Get full context of line 1410 materialized view code ==="
# Get wider context to understand the materialized view parsing
sed -n '1390,1430p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Find where baseTableName gets its value ==="
# Track back where baseTableName comes from
sed -n '1200,1250p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Check if there are test cases for materialized views with quoted names ==="
# Search for materialized view tests with quotes
rg -n "CREATE MATERIALIZED VIEW.*['\"]" core/src/test/ --type java

echo -e "\n\n=== Look for edge case handling in tests ==="
# Check what edge cases are tested
cat core/src/test/java/io/questdb/test/cairo/view/ViewQueryTest.java | head -100

Length of output: 22431


🏁 Script executed:

#!/bin/bash

echo "=== Verify SqlParser extends WhereClauseParser ==="
# Check class hierarchy
rg -n "^public class SqlParser" core/src/main/java/io/questdb/griffin/SqlParser.java -A 2

echo -e "\n\n=== Verify unquote is accessible to SqlParser ==="
# Check if SqlParser can access unquote from WhereClauseParser
rg -n "class WhereClauseParser" core/src/main/java/io/questdb/griffin/WhereClauseParser.java

echo -e "\n\n=== Check if there are DROP VIEW, ALTER VIEW, or other view commands ==="
# Look for other view-related commands that might need similar fixes
rg -n "(DROP|ALTER|SHOW|DESCRIBE)\s+VIEW" core/src/main/java/io/questdb/griffin/SqlParser.java -i

echo -e "\n\n=== Look for edge cases: schema-qualified names ==="
# Check sansPublicSchema usage - it might interact with quotes
rg -n "sansPublicSchema" core/src/main/java/io/questdb/griffin/SqlParser.java | head -20

echo -e "\n\n=== Check test for schema-qualified quoted names ==="
# See if tests cover "public"."view_name" or similar
rg -n "public\\..*['\"]" core/src/test/java/io/questdb/test/cairo/view/ --type java

Length of output: 1206


🏁 Script executed:

#!/bin/bash

echo "=== Search for unquote method in SqlParser class ==="
# Look for unquote method anywhere in SqlParser.java
rg -n "unquote" core/src/main/java/io/questdb/griffin/SqlParser.java | head -5

echo -e "\n\n=== Check if SqlParser has access to unquote via inheritance or import ==="
# Check imports and class declaration
head -100 core/src/main/java/io/questdb/griffin/SqlParser.java | grep -E "(import|extends|implements)"

echo -e "\n\n=== Find the unquote method that SqlParser is using ==="
# Search for all unquote methods in the griffin package
fd -e java . core/src/main/java/io/questdb/griffin/ --exec rg -l "^\s*(private|protected|public).*unquote\("

echo -e "\n\n=== Check GenericLexer.unquote ==="
rg -n "public.*unquote" core/src/main/java/io/questdb/griffin/SqlParserLexer.java core/src/main/java/io/questdb/std/str/AbstractCharSequence.java core/src/main/java/io/questdb/std/GenericLexer.java -A 5

echo -e "\n\n=== Verify the actual unquote call in the diff ==="
# Double check what unquote is being called
git show HEAD:core/src/main/java/io/questdb/griffin/SqlParser.java | grep -n "import.*unquote" 

Length of output: 5134


🏁 Script executed:

#!/bin/bash

echo "=== Check for DROP VIEW implementation ==="
# Look for drop view parsing
rg -n "DROP.*VIEW|drop.*view" core/src/main/java/io/questdb/griffin/SqlParser.java -i -C 3

echo -e "\n\n=== Check sansPublicSchema implementation ==="
# Understand what sansPublicSchema does and its interaction with quotes
sed -n '4539,4570p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Test edge case: public.view_name with quotes ==="
# See if there are tests for schema-qualified quoted identifiers
rg -n "public\." core/src/test/java/io/questdb/test/cairo/view/ --type java -C 2

echo -e "\n\n=== Check if views can be dropped and if that code path needs fixing ==="
rg -n "dropView|DROP_VIEW|drop.*View" core/src/main/java/io/questdb/griffin/ --type java

echo -e "\n\n=== Verify the order of operations: sansPublicSchema then unquote ==="
# In parseCompileView, check if sansPublicSchema is called before unquote
sed -n '930,940p' core/src/main/java/io/questdb/griffin/SqlParser.java

Length of output: 2905


🏁 Script executed:

#!/bin/bash

echo "=== Check parseFromClause around line 2593 for sansPublicSchema ==="
sed -n '2580,2610p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Check parseJoin around line 3248 for sansPublicSchema ==="
sed -n '3240,3260p' core/src/main/java/io/questdb/griffin/SqlParser.java

echo -e "\n\n=== Test what happens with schema-qualified quoted names ==="
# Create a test to see if this edge case is handled
cat > /tmp/test_quoted_schema.sql << 'EOF'
-- Test cases that might fail:
-- COMPILE VIEW "public"."view1"
-- SELECT FROM "public"."view1"
-- JOIN "public"."view1"
EOF
cat /tmp/test_quoted_schema.sql

echo -e "\n\n=== Search for existing tests with public schema ==="
rg -n "public\." core/src/test/java/io/questdb/test/ --type java -g '*View*Test.java' | head -20

echo -e "\n\n=== Check what Chars.isQuoted does ==="
rg -n "public.*isQuoted" core/src/main/java/io/questdb/std/Chars.java -A 5

echo -e "\n\n=== Understand the token format for schema-qualified names ==="
# Check how "public"."table" is tokenized
rg -n "schema.*qualified|qualified.*name" core/src/main/java/io/questdb/griffin/ --type java | head -10

Length of output: 3781


@bluestreak01, yes I've completed a thorough review. Here are my findings:

✅ Core Fix is Correct

The PR correctly adds unquote() before getTableTokenIfExists() in three critical locations:

  1. Line 936 (parseCompileView): COMPILE VIEW 'view_name'
  2. Line 2593 (parseFromClause): SELECT FROM 'view_name'
  3. Line 3248 (parseJoin): JOIN 'view_name'

This properly strips quotes so the view lookup succeeds. Test coverage at 100% confirms the fix works for the stated issue.

⚠️ Potential Edge Case: Schema-Qualified Quoted Names

Issue: None of the three fixed locations call sansPublicSchema() before unquote(). This differs from the established pattern used elsewhere in the codebase.

Lines 1210-1213 (CREATE VIEW):

tok = sansPublicSchema(tok, lexer);
assertNameIsQuotedOrNotAKeyword(tok, lexer.lastTokenPosition());
tableOpBuilder.setTableNameExpr(nextLiteral(
    assertNoDotsAndSlashes(unquote(tok), lexer.lastTokenPosition()), ...

Lines 1222-1224 (CREATE MATERIALIZED VIEW):

baseTableName = sansPublicSchema(tok, lexer);
assertNameIsQuotedOrNotAKeyword(baseTableName, lexer.lastTokenPosition());
baseTableName = unquote(baseTableName);

But in the three fixes:

  • Line 936: cairoEngine.getTableTokenIfExists(unquote(tok)) — no sansPublicSchema
  • Line 2593: cairoEngine.getTableTokenIfExists(unquote(tok)) — no sansPublicSchema
  • Line 3248: cairoEngine.getTableTokenIfExists(unquote(tok)) — no sansPublicSchema

Concern: If a user writes COMPILE VIEW "public"."my_view" or SELECT FROM "public"."my_view", the token won't be properly stripped of the schema prefix before the view lookup.

Looking at sansPublicSchema() implementation (lines 4539-4565), it handles quoted tokens and strips the "public." prefix. Without this call, schema-qualified quoted view names may not resolve correctly.

📝 Suggested Follow-ups

  1. Add test cases for schema-qualified quoted view names:

    COMPILE VIEW "public"."view1"
    SELECT FROM "public"."view1"  
    JOIN "public"."view1"
  2. Consider adding sansPublicSchema() calls before unquote() in the three locations if this edge case is valid, following the pattern:

    tok = sansPublicSchema(tok, lexer);
    final TableToken tt = cairoEngine.getTableTokenIfExists(unquote(tok));
  3. Verify whether the lexer tokenizes "public"."view1" as a single token or two separate tokens. If it's two tokens, sansPublicSchema() would already handle it correctly and no change is needed.

Question: Does QuestDB support schema-qualified view names in practice? If not, this edge case may be moot. If yes, it needs a test to confirm current behavior.


🧠 Learnings used
Learnt from: javier
Repo: questdb/questdb PR: 0
File: :0-0
Timestamp: 2026-02-06T18:22:28.130Z
Learning: In questdb/questdb, for PRs requested by javier, provide line-cited, push-back style reviews with concrete follow-ups (tests, diffs, and performance considerations).

Learnt from: javier
Repo: questdb/questdb PR: 0
File: :0-0
Timestamp: 2026-02-06T18:22:28.130Z
Learning: For questdb/questdb, javier expects a rigorous, push-back style review; always include concrete line-cited findings and propose targeted tests/fixes when reviewing javier’s PRs.

@bluestreak01 bluestreak01 merged commit 8ee1f22 into master Feb 13, 2026
44 checks passed
@bluestreak01 bluestreak01 deleted the ia_view_quotes branch February 13, 2026 18:51
maciulis pushed a commit to maciulis/questdb that referenced this pull request Feb 19, 2026
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.

2 participants