-
Notifications
You must be signed in to change notification settings - Fork 204
Fix: Properly quote database and schema identifiers for SQL compatibility #1987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: Properly quote database and schema identifiers for SQL compatibility #1987
Conversation
WalkthroughFunction now strips surrounding quotes from the retrieved relation identifier, logs the stripped value, and returns the stripped relation. On exception it logs the error, records via tracking if present, and returns the fallback Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
|
👋 @mschmidoev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
elementary/monitor/data_monitoring/data_monitoring.py (2)
82-83: If embedding inside single-quoted SQL literals, escape single quotes insteadIf the goal is to safely place the relation inside a single-quoted SQL string literal (e.g., in a Slack snippet), converting double quotes is unnecessary and potentially harmful. Instead, escape single quotes in the content:
- relation = relation.replace('"', "'") if relation else relation + display_relation = relation.replace("'", "''") if relation else relationThis yields a string-literal-safe version while preserving any double quotes that are harmless inside single-quoted literals.
82-85: Scope quote-normalization for display onlyWe verified that the
get_elementary_database_and_schemamacro always returns an unquoteddatabase.schemastring, and thatself.elementary_database_and_schemais used broadly (in tests, Slack messages, alert formatting, etc.). Replacing quotes on the canonical return value is a no-op today but could strip valid identifier quoting in the future. To avoid mutating the source-of-truth, only normalize for display:In
elementary/monitor/data_monitoring/data_monitoring.py(lines 82–85):- # Replace double quotes with single quotes for proper SQL compatibility - relation = relation.replace('"', "'") if relation else relation - logger.info(f"Elementary's database and schema: '{relation}'") - return relation + # Display-only: replace double quotes with single quotes in logs + display_relation = relation.replace('"', "'") if isinstance(relation, str) else relation + logger.info(f"Elementary's database and schema: '{display_relation}'") + return relationIf downstream callers (e.g. Slack templates) need a “safe” string, consider adding a derived
elementary_database_and_schema_displayproperty or performing.replace('"', "'")at the call site instead.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
elementary/monitor/data_monitoring/data_monitoring.py(1 hunks)
4c14bf7 to
6a66be5
Compare
|
@mschmidoev The CI is failing for some reason. Can you update your branch to the latest |
…and_schema - Replace double quotes with single quotes for proper SQL compatibility - Fixes SQL errors in Slack alert messages when database/schema names contain quotes - Added conditional check to handle None values safely
6a66be5 to
a3a3581
Compare
a3a3581 to
68defa0
Compare
68defa0 to
60faf1c
Compare
|
@elazarlachkar should be good to go :) |
|
Hi @mschmidoev! The CI still has the issue we solved on Thanks, and sorry for the trouble. |
…e-quotes-with-single-quotes
60faf1c to
701198f
Compare
|
Hey @elazarlachkar , no dramas, should be good now |
…e-quotes-with-single-quotes
|
Hi @mschmidoev! |
|
Thanks @elazarlachkar, was off last week but this PR should be up to date with master branch now! |
|
@elazarlachkar looks like that's worked this time around! Let me know if there's anything else you need :) ) |
|
Hey @elazarlachkar just checking if there's any progress here :) |
elazarlachkar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @mschmidoev!
I really apologize for the delay here. At the end of September I shifted my focus to other things, and I missed your check in message.
I checked your changes myself, and consulted one of my colleagues here at Elementary, and added a comment I think should be addressed.
Please let me know what you think? This PR is a priority for me now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
elementary/monitor/data_monitoring/data_monitoring.py (1)
82-85: LGTM! Implementation follows the agreed approach.The solution correctly strips surrounding quotes from the relation to avoid case sensitivity issues and double-quoting problems, as discussed in the previous review. The implementation is clean and straightforward.
Optional: Consider the try-except-else pattern.
Static analysis suggests moving the return statement to an
elseblock for slightly more idiomatic exception handling:try: relation = self.internal_dbt_runner.run_operation( "elementary_cli.get_elementary_database_and_schema", quiet=True )[0] # Strip quotes from relation to avoid case sensitivity issues and double-quoting strip_relation = relation.strip('"') logger.info(f"Elementary's database and schema: '{strip_relation}'") - return strip_relation except Exception as ex: logger.error("Failed to parse Elementary's database and schema.") if self.tracking: self.tracking.record_internal_exception(ex) return "<elementary_database>.<elementary_schema>" +else: + return strip_relationThis pattern makes the success path more explicit, though the current code is perfectly valid.
Note: Identifier quoting assumptions.
The stripped relation (e.g.,
my_db.my_schema) will work correctly as long as the database and schema names don't contain special characters, spaces, or reserved words that require quoting in SQL. This should be fine for typical use cases, but if issues arise downstream with specific identifier names, this assumption may need revisiting.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
elementary/monitor/data_monitoring/data_monitoring.py(1 hunks)
🧰 Additional context used
🪛 Ruff (0.14.7)
elementary/monitor/data_monitoring/data_monitoring.py
85-85: Consider moving this statement to an else block
(TRY300)
|
@mschmidoev I merged the change, thanks for the PR! |
Summary
This PR updates the logic for constructing the elementary_database_and_schema identifier so that the database and schema are each wrapped in double quotes, e.g. "database"."schema". This ensures correct SQL syntax and avoids treating the entire string as a single identifier.
Details
Previously, the code would wrap the whole database.schema string in quotes, resulting in "database.schema", which is not valid in standard SQL.
Now, the code splits the identifier on the dot and wraps each part individually: "database"."schema".
If only a schema is present, it is wrapped as "schema".
#1986
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.