{"record":{"id":"ebef5d31a73f9852","repo":"googleapis/mcp-toolbox","slug":"unanalyzable-statements-like-s-s-are-not-allow","errorCode":null,"errorMessage":"unanalyzable statements like '%s %s' are not allowed","messagePattern":"unanalyzable statements like '(.+?) (.+?)' are not allowed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/tools/bigquery/bigquerycommon/table_name_parser.go","lineNumber":271,"sourceCode":"\t\t\t\t\t}\n\t\t\t\t\tif infoSchemaIdx > 2 {\n\t\t\t\t\t\treturn 0, fmt.Errorf(\"invalid INFORMATION_SCHEMA query path %q\", strings.Join(parts, \".\"))\n\t\t\t\t\t}\n\t\t\t\t\tparts = parts[:infoSchemaIdx+1]\n\t\t\t\t}\n\n\t\t\t\tif len(parts) == 1 {\n\t\t\t\t\tkeyword := strings.ToLower(parts[0])\n\t\t\t\t\tswitch keyword {\n\t\t\t\t\tcase \"call\":\n\t\t\t\t\t\treturn 0, fmt.Errorf(\"CALL is not allowed when dataset restrictions are in place, as the called procedure's contents cannot be safely analyzed\")\n\t\t\t\t\tcase \"immediate\":\n\t\t\t\t\t\tif lastToken == \"execute\" {\n\t\t\t\t\t\t\treturn 0, fmt.Errorf(\"EXECUTE IMMEDIATE is not allowed when dataset restrictions are in place, as its contents cannot be safely analyzed\")\n\t\t\t\t\t\t}\n\t\t\t\t\tcase \"procedure\", \"function\":\n\t\t\t\t\t\tif lastToken == \"create\" || lastToken == \"create or replace\" {\n\t\t\t\t\t\t\treturn 0, fmt.Errorf(\"unanalyzable statements like '%s %s' are not allowed\", strings.ToUpper(lastToken), strings.ToUpper(keyword))\n\t\t\t\t\t\t}\n\t\t\t\t\tcase verbCreate, verbAlter, verbDrop, verbSelect, verbInsert, verbUpdate, verbDelete, verbMerge:\n\t\t\t\t\t\tif statementVerb == \"\" {\n\t\t\t\t\t\t\tstatementVerb = keyword\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif statementVerb == verbCreate || statementVerb == verbAlter || statementVerb == verbDrop {\n\t\t\t\t\t\tif keyword == \"schema\" || keyword == \"dataset\" {\n\t\t\t\t\t\t\treturn 0, fmt.Errorf(\"dataset-level operations like '%s %s' are not allowed when dataset restrictions are in place\", strings.ToUpper(statementVerb), strings.ToUpper(keyword))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif _, ok := tableFollowsKeywords[keyword]; ok {\n\t\t\t\t\t\texpectingTable = true\n\t\t\t\t\t\tlastTableKeyword = keyword\n\t\t\t\t\t} else if _, ok := tableContextExitKeywords[keyword]; ok {\n\t\t\t\t\t\texpectingTable = false","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/tools/bigquery/bigquerycommon/table_name_parser.go#L253-L289","documentation":"parseSQL blocks statements it cannot safely analyze under dataset restrictions. CREATE/CREATE OR REPLACE of a PROCEDURE or FUNCTION embeds arbitrary SQL bodies that the parser cannot inspect, so it rejects the statement to ensure every table reference remains verifiable.","triggerScenarios":"Running a CREATE PROCEDURE, CREATE FUNCTION, CREATE OR REPLACE PROCEDURE, or CREATE OR REPLACE FUNCTION statement through TableParser/parseSQL while dataset restrictions are active.","commonSituations":"Setup/migration scripts that define routines before running queries; users trying to deploy UDFs or procedures through a restricted query tool; CI jobs that run DDL scripts through the same connection.","solutions":["Split routine-creation DDL out of the restricted path and run it separately without dataset restrictions","Remove the CREATE PROCEDURE/FUNCTION statement from the validated query","If the routine is already deployed, just call CALL proc() only if the procedure itself is allowed, or pre-create it via admin tooling"],"exampleFix":"// before\nCREATE FUNCTION myfunc(x INT64) AS (x * 2);\nSELECT myfunc(id) FROM proj.ds.t;\n// after\n-- create routine via unrestricted admin path first, then:\nSELECT myfunc(id) FROM proj.ds.t;","handlingStrategy":"validation","validationCode":"u := strings.ToUpper(sql)\nfor _, bad := range []string{\"CREATE PROCEDURE\", \"CREATE FUNCTION\", \"CREATE OR REPLACE PROCEDURE\", \"CREATE OR REPLACE FUNCTION\"} {\n    if strings.Contains(u, bad) {\n        return fmt.Errorf(\"query rejected: %s is not permitted under dataset restrictions\", bad)\n    }\n}","typeGuard":null,"tryCatchPattern":"_, err := parser.Parse(sql)\nif err != nil && strings.Contains(err.Error(), \"unanalyzable statements\") {\n    // route routine DDL to an unrestricted admin path\n    return handleRoutineDDL(sql)\n}","preventionTips":["Create procedures/functions via a separate unrestricted deployment step","Only send plain DML/DDL on tables through dataset-restricted tools","Validate SQL scripts for routine DDL before running them through the restricted path"],"tags":["bigquery","sql-parsing","dataset-restrictions","ddl"],"backgroundTag":"unanalyzable-statement-blocked","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}