## Code Analysis ### Resolved views use the view authorization path `server/auth/auth_handler.go:313-330` ```go func (h *AuthorizationHandler) HandleResolvedTableAuth(ctx *sql.Context, aqs sql.AuthorizationQueryState, auth vitess.AuthInformation, node sql.Node) error { if auth.TargetType == AuthTargetType_TableIdentifiers { switch node := node.(type) { case *plan.ResolvedTable: // resolved table handling case *plan.SubqueryAlias: // This case will always resolve to a view auth.TargetType = AuthTargetType_ViewIdentifiers } } return h.HandleAuth(ctx, aqs, auth) } ``` The resolved subquery alias is explicitly reclassified as a view before the common authorization handler runs. ### View privilege failures have a PostgreSQL authorization error `server/auth/auth_handler.go:193-212, 362-381` ```go case AuthTargetType_TableIdentifiers, AuthTargetType_ViewIdentifiers: relationKind := "table" if auth.TargetType == AuthTargetType_ViewIdentifiers { relationKind = "view" } // ... err = checkPrivilegeOnTable(state, relationKind, schemaName, auth.TargetNames[i+2], privileges) if err != nil { return err } func checkPrivilegeOnTable(state AuthorizationQueryState, relationKind, schemaName, tableName string, privileges []Privilege) error { // ... if !HasTablePrivilege(roleTableKey, privilege) && !HasTablePrivilege(publicTableKey, privilege) { return pgerror.Newf(pgcode.InsufficientPrivilege, "permission denied for %s %s", relationKind, tableName) } return nil } ``` This path preserves `relationKind == "view"` and constructs an insufficient-privilege error naming the denied view. ### Repository test contract `testing/go/auth_test.go:1461-1497` ```go "CREATE VIEW v_edges AS SELECT src, dst FROM edges;" "CREATE VIEW v_secret AS SELECT x FROM secret;" "CREATE ROLE reader LOGIN PASSWORD '[REDACTED]';" "GRANT SELECT ON edges TO reader;" Query: "SELECT * FROM v_edges;", Username: "reader", ExpectedErr: "permission denied for view v_edges", ExpectedErrCode: "42501", ``` The existing integration contract expects an unauthorized view read to remain SQLSTATE `42501` and identify the relation as a view. ### Result The source authorization path supports a view-specific `42501` response, while the observed denied-view request returned a generic `XX000` parser error before that authorization response. ### Observed execution ### restricted reader session ```sh PGPASSWORD=[REDACTED] psql -h localhost -p 5432 -U reader -d postgres -v VERBOSITY=verbose -X -c "SELECT * FROM bf_v_secret_int;" -c "WITH hidden AS (SELECT x FROM bf_secret_int) SELECT * FROM hidden;" -c "SELECT * FROM (SELECT x FROM bf_secret_int) AS secret_alias;" ``` ```text ERROR: XX000: only a single statement at a time is currently supported ERROR: 42501: permission denied for table bf_secret_int ERROR: 42501: permission denied for table bf_secret_int ``` The first response corresponds to the denied view query in the command sequence; the following denied table forms returned the expected `42501` table errors. ### permitted and denied forms readback ```text SESSION_START current_user -------------- reader@::1 (1 row) PERMITTED_TABLE src | dst -----+----- a | b b | c (2 rows) CTE_PERMITTED_TABLE src | dst -----+----- a | b b | c (2 rows) SUBQUERY_PERMITTED_TABLE src | dst -----+----- a | b b | c (2 rows) ``` ### parser guard `postgres/parser/parser/sql/sql_parser.go:72-80` ```go func (p *PostgresParser) ParseWithOptions(ctx context.Context, query string, delimiter rune, _ bool, _ vitess.ParserOptions) (vitess.Statement, string, string, error) { q := sql.RemoveSpaceAndDelimiter(query, delimiter) stmts, err := parser.Parse(q) if err != nil { return nil, "", "", err } if len(stmts) > 1 { return nil, "", "", fmt.Errorf("only a single statement at a time is currently supported") } ``` The captured `XX000` text matches this generic parser guard rather than the view-specific authorization error. ### Result The integrated reader flow returned the expected rows for permitted table-derived forms and `42501` for denied table forms, but the denied view returned `XX000: only a single statement at a time is currently supported` instead of the expected view-specific `42501` error. ### Test context The target was a local non-production PostgreSQL-wire endpoint. The SQL client output is the authoritative evidence; the browser screenshot only showed the endpoint’s `ERR_EMPTY_RESPONSE` because it is not an HTTP page.