Skip to content
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

release-23.1: sql: add tests for CTAS, CMVAS with every vtable #106191

Merged
merged 3 commits into from
Jul 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/sql/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ go_test(
"copy_test.go",
"copy_to_test.go",
"crdb_internal_test.go",
"create_as_test.go",
"create_function_test.go",
"create_stats_test.go",
"create_test.go",
Expand Down
126 changes: 126 additions & 0 deletions pkg/sql/create_as_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// Copyright 2023 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

package sql

import (
"context"
"fmt"
"strings"
"testing"

"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/sql/parser"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/types"
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
"github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
"github.com/stretchr/testify/require"
)

// TestCreateAsVTable verifies that all vtables can be used as the source of
// CREATE TABLE AS and CREATE MATERIALIZED VIEW AS.
func TestCreateAsVTable(t *testing.T) {
defer leaktest.AfterTest(t)()

// These are the vtables that need to be fixed.
// The map should be empty if all vtables are supported.
brokenTables := map[string]struct{}{
// TODO(sql-foundations): Fix nil pointer dereference.
// See https://github.com/cockroachdb/cockroach/issues/106166.
`pg_catalog.pg_prepared_statements`: {},
// TODO(sql-foundations): Fix nil pointer dereference.
// See https://github.com/cockroachdb/cockroach/issues/106167.
`pg_catalog.pg_cursors`: {},
// TODO(sql-foundations): Fix nil pointer dereference.
// See https://github.com/cockroachdb/cockroach/issues/106168.
`"".crdb_internal.create_statements`: {},
}

ctx := context.Background()
testCluster := serverutils.StartNewTestCluster(t, 1, base.TestClusterArgs{})
defer testCluster.Stopper().Stop(ctx)
sqlRunner := sqlutils.MakeSQLRunner(testCluster.ServerConn(0))
var p parser.Parser

i := 0
for _, vSchema := range virtualSchemas {
for _, vSchemaDef := range vSchema.tableDefs {
if vSchemaDef.isUnimplemented() {
continue
}

var name tree.TableName
var ctasColumns []string
schema := vSchemaDef.getSchema()
statements, err := p.Parse(schema)
require.NoErrorf(t, err, schema)
require.Lenf(t, statements, 1, schema)
switch stmt := statements[0].AST.(type) {
case *tree.CreateTable:
name = stmt.Table
for _, def := range stmt.Defs {
if colDef, ok := def.(*tree.ColumnTableDef); ok {
if colDef.Hidden {
continue
}
// Filter out vector columns to prevent error in CTAS:
// "VECTOR column types are unsupported".
if colDef.Type == types.Int2Vector || colDef.Type == types.OidVector {
continue
}
ctasColumns = append(ctasColumns, colDef.Name.String())
}
}
case *tree.CreateView:
name = stmt.Name
ctasColumns = []string{"*"}
default:
require.Failf(t, "missing case", "unexpected type %T for schema %s", stmt, schema)
}

fqName := name.FQString()
if _, ok := brokenTables[fqName]; ok {
continue
}

// Filter by trace_id to prevent error when selecting from
// crdb_internal.cluster_inflight_traces:
// "pq: a trace_id value needs to be specified".
var where string
if fqName == `"".crdb_internal.cluster_inflight_traces` {
where = " WHERE trace_id = 1"
}

createTableStmt := fmt.Sprintf(
"CREATE TABLE test_table_%d AS SELECT %s FROM %s%s",
i, strings.Join(ctasColumns, ", "), fqName, where,
)
sqlRunner.Exec(t, createTableStmt)
createViewStmt := fmt.Sprintf(
"CREATE MATERIALIZED VIEW test_view_%d AS SELECT * FROM %s%s",
i, fqName, where,
)
sqlRunner.Exec(t, createViewStmt)
i++
}
}

waitForJobsSuccess(t, sqlRunner)
}

func waitForJobsSuccess(t *testing.T, sqlRunner *sqlutils.SQLRunner) {
query := `SELECT job_id, status, error, description
FROM [SHOW JOBS]
WHERE job_type IN ('SCHEMA CHANGE', 'NEW SCHEMA CHANGE')
AND status != 'succeeded'`
sqlRunner.CheckQueryResultsRetry(t, query, [][]string{})
}
11 changes: 9 additions & 2 deletions pkg/sql/sem/tree/table_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

package tree

import "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"

// TableName corresponds to the name of a table in a FROM clause,
// INSERT or UPDATE statement, etc.
//
Expand Down Expand Up @@ -46,8 +48,13 @@ func (t *TableName) objectName() {}
// schema and catalog names. Suitable for logging, etc.
func (t *TableName) FQString() string {
ctx := NewFmtCtx(FmtSimple)
ctx.FormatNode(&t.CatalogName)
ctx.WriteByte('.')
schemaName := t.SchemaName.String()
// The pg_catalog and pg_extension schemas cannot be referenced from inside
// an anonymous ("") database. This makes their FQ string always relative.
if schemaName != catconstants.PgCatalogName && schemaName != catconstants.PgExtensionSchemaName {
ctx.FormatNode(&t.CatalogName)
ctx.WriteByte('.')
}
ctx.FormatNode(&t.SchemaName)
ctx.WriteByte('.')
ctx.FormatNode(&t.ObjectName)
Expand Down
8 changes: 4 additions & 4 deletions pkg/testutils/sqlutils/sql_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ func (sr *SQLRunner) ExecRowsAffected(
func (sr *SQLRunner) ExpectErr(t Fataler, errRE string, query string, args ...interface{}) {
helperOrNoop(t)()
_, err := sr.DB.ExecContext(context.Background(), query, args...)
sr.expectErr(t, err, errRE)
sr.expectErr(t, query, err, errRE)
}

func (sr *SQLRunner) expectErr(t Fataler, err error, errRE string) {
func (sr *SQLRunner) expectErr(t Fataler, query string, err error, errRE string) {
helperOrNoop(t)()
if !testutils.IsError(err, errRE) {
s := "nil"
if err != nil {
s = pgerror.FullError(err)
}
t.Fatalf("expected error '%s', got: %s", errRE, s)
t.Fatalf("expected query '%s' error '%s', got: %s", query, errRE, s)
}
}

Expand All @@ -169,7 +169,7 @@ func (sr *SQLRunner) ExpectErrWithHint(
helperOrNoop(t)()
_, err := sr.DB.ExecContext(context.Background(), query, args...)

sr.expectErr(t, err, errRE)
sr.expectErr(t, query, err, errRE)

if pqErr := (*pq.Error)(nil); errors.As(err, &pqErr) {
matched, merr := regexp.MatchString(hintRE, pqErr.Hint)
Expand Down