schemaForWriteTargetResolution returns the default schema to resolve UNqualified write targets against, per engine — the schema the engine will actually write to, or the sentinel when that can't be determined here (so the schema_name attribute is omitted and schema-scoped grants fail closed). Qualif
(engine storepb.Engine, databaseName, requestSchema string)
| 2000 | // sentinel when that can't be determined here (so the schema_name attribute is omitted and |
| 2001 | // schema-scoped grants fail closed). Qualified targets ignore this and keep their qualifier. |
| 2002 | func schemaForWriteTargetResolution(engine storepb.Engine, databaseName, requestSchema string) string { |
| 2003 | switch engine { |
| 2004 | case storepb.Engine_POSTGRES: |
| 2005 | // Execution pins search_path to QueryRequest.schema when set; otherwise the |
| 2006 | // connection user's default ($user, public) is not knowable here. |
| 2007 | if requestSchema != "" { |
| 2008 | return requestSchema |
| 2009 | } |
| 2010 | return unresolvedSchemaSentinel |
| 2011 | case storepb.Engine_MSSQL: |
| 2012 | // No per-request schema pin; execution uses the login's default_schema, which is not |
| 2013 | // in synced metadata. Never trust a request schema for MSSQL. |
| 2014 | return unresolvedSchemaSentinel |
| 2015 | case storepb.Engine_ORACLE: |
| 2016 | // Execution pins CURRENT_SCHEMA to the connection database (= schema) once at pool Open |
| 2017 | // (oracle.go), and the SQL Editor opens a fresh pool per request, so an unqualified write |
| 2018 | // resolves to databaseName — knowable and execution-accurate. (A mid-batch ALTER SESSION |
| 2019 | // is covered by the multi-statement fallback.) This pin is the reason the schema is |
| 2020 | // auth-grade here; if the driver ever stops pinning per-connection, switch to the sentinel. |
| 2021 | return databaseName |
| 2022 | case storepb.Engine_MYSQL, storepb.Engine_TIDB: |
| 2023 | // No schema layer; the extractor emits an empty schema and resource.schema_name is omitted. |
| 2024 | return "" |
| 2025 | default: |
| 2026 | // Fail closed for any other engine. An engine that reaches here without an explicit, |
| 2027 | // execution-verified schema mapping must NOT have its unqualified writes resolved against |
| 2028 | // a guessed default — e.g. a pg-family extractor (COCKROACHDB, REDSHIFT) would fill in the |
| 2029 | // metadata search_path, a REAL schema name, which we'd then assert as resource.schema_name |
| 2030 | // and over-allow a schema-scoped grant. The sentinel maps to an omitted attribute, so |
| 2031 | // schema-scoped grants fail closed while table-only grants still match. SUP-222 / BYT-9698. |
| 2032 | return unresolvedSchemaSentinel |
| 2033 | } |
| 2034 | } |
| 2035 | |
| 2036 | // sanitizeResults sanitizes the strings in the results by replacing all the invalid UTF-8 characters with its hexadecimal representation. |
| 2037 | func sanitizeResults(results []*v1pb.QueryResult) { |
no outgoing calls