github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/testutils/testcat/create_table.go (about)

     1  // Copyright 2018 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  package testcat
    12  
    13  import (
    14  	"fmt"
    15  	"strings"
    16  
    17  	"github.com/cockroachdb/cockroach/pkg/config/zonepb"
    18  	"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
    19  	"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
    20  	"github.com/cockroachdb/cockroach/pkg/sql/types"
    21  	"github.com/cockroachdb/cockroach/pkg/util"
    22  )
    23  
    24  type indexType int
    25  
    26  const (
    27  	primaryIndex indexType = iota
    28  	uniqueIndex
    29  	nonUniqueIndex
    30  )
    31  
    32  type colType int
    33  
    34  const (
    35  	// keyCol is part of both lax and strict keys.
    36  	keyCol colType = iota
    37  	// strictKeyCol is only part of strict key.
    38  	strictKeyCol
    39  	// nonKeyCol is not part of lax or strict key.
    40  	nonKeyCol
    41  )
    42  
    43  var uniqueRowIDString = "unique_rowid()"
    44  
    45  // CreateTable creates a test table from a parsed DDL statement and adds it to
    46  // the catalog. This is intended for testing, and is not a complete (and
    47  // probably not fully correct) implementation. It just has to be "good enough".
    48  func (tc *Catalog) CreateTable(stmt *tree.CreateTable) *Table {
    49  	stmt.HoistConstraints()
    50  
    51  	// Update the table name to include catalog and schema if not provided.
    52  	tc.qualifyTableName(&stmt.Table)
    53  
    54  	// Assume that every table in the "system" or "information_schema" catalog
    55  	// is a virtual table. This is a simplified assumption for testing purposes.
    56  	if stmt.Table.CatalogName == "system" || stmt.Table.SchemaName == "information_schema" {
    57  		return tc.createVirtualTable(stmt)
    58  	}
    59  
    60  	tab := &Table{TabID: tc.nextStableID(), TabName: stmt.Table, Catalog: tc}
    61  
    62  	// TODO(andyk): For now, just remember that the table was interleaved. In the
    63  	// future, it may be necessary to extract additional metadata.
    64  	if stmt.Interleave != nil {
    65  		tab.interleaved = true
    66  	}
    67  
    68  	// Add non-mutation columns.
    69  	for _, def := range stmt.Defs {
    70  		switch def := def.(type) {
    71  		case *tree.ColumnTableDef:
    72  			if !isMutationColumn(def) {
    73  				tab.addColumn(def)
    74  			}
    75  		}
    76  	}
    77  
    78  	// If there is no primary index, add the hidden rowid column.
    79  	hasPrimaryIndex := false
    80  	for _, def := range stmt.Defs {
    81  		switch def := def.(type) {
    82  		case *tree.ColumnTableDef:
    83  			if def.PrimaryKey.IsPrimaryKey {
    84  				hasPrimaryIndex = true
    85  			}
    86  
    87  		case *tree.UniqueConstraintTableDef:
    88  			if def.PrimaryKey {
    89  				hasPrimaryIndex = true
    90  			}
    91  		}
    92  	}
    93  
    94  	if !hasPrimaryIndex {
    95  		rowid := &Column{
    96  			Ordinal:     tab.ColumnCount(),
    97  			Name:        "rowid",
    98  			Type:        types.Int,
    99  			Hidden:      true,
   100  			DefaultExpr: &uniqueRowIDString,
   101  		}
   102  		tab.Columns = append(tab.Columns, rowid)
   103  	}
   104  
   105  	// Add any mutation columns (after any hidden rowid column).
   106  	for _, def := range stmt.Defs {
   107  		switch def := def.(type) {
   108  		case *tree.ColumnTableDef:
   109  			if isMutationColumn(def) {
   110  				tab.addColumn(def)
   111  			}
   112  		}
   113  	}
   114  
   115  	// Add the primary index.
   116  	if hasPrimaryIndex {
   117  		for _, def := range stmt.Defs {
   118  			switch def := def.(type) {
   119  			case *tree.ColumnTableDef:
   120  				if def.PrimaryKey.IsPrimaryKey {
   121  					// Add the primary index over the single column.
   122  					tab.addPrimaryColumnIndex(string(def.Name))
   123  				}
   124  
   125  			case *tree.UniqueConstraintTableDef:
   126  				if def.PrimaryKey {
   127  					tab.addIndex(&def.IndexTableDef, primaryIndex)
   128  				}
   129  			}
   130  		}
   131  	} else {
   132  		tab.addPrimaryColumnIndex("rowid")
   133  	}
   134  	if stmt.PartitionBy != nil {
   135  		tab.Indexes[0].partitionBy = stmt.PartitionBy
   136  	}
   137  
   138  	// Add check constraints.
   139  	for _, def := range stmt.Defs {
   140  		switch def := def.(type) {
   141  		case *tree.CheckConstraintTableDef:
   142  			tab.Checks = append(tab.Checks, cat.CheckConstraint{
   143  				Constraint: serializeTableDefExpr(def.Expr),
   144  				Validated:  validatedCheckConstraint(def),
   145  			})
   146  		}
   147  	}
   148  
   149  	// Search for index and family definitions.
   150  	for _, def := range stmt.Defs {
   151  		switch def := def.(type) {
   152  		case *tree.UniqueConstraintTableDef:
   153  			if !def.PrimaryKey {
   154  				tab.addIndex(&def.IndexTableDef, uniqueIndex)
   155  			}
   156  
   157  		case *tree.IndexTableDef:
   158  			tab.addIndex(def, nonUniqueIndex)
   159  
   160  		case *tree.FamilyTableDef:
   161  			tab.addFamily(def)
   162  
   163  		case *tree.ColumnTableDef:
   164  			if def.Unique {
   165  				tab.addIndex(
   166  					&tree.IndexTableDef{
   167  						Name:    tree.Name(fmt.Sprintf("%s_%s_key", stmt.Table.ObjectName, def.Name)),
   168  						Columns: tree.IndexElemList{{Column: def.Name}},
   169  					},
   170  					uniqueIndex,
   171  				)
   172  			}
   173  		}
   174  	}
   175  
   176  	// If there are columns missing from explicit family definitions, add them
   177  	// to family 0 (ensure that one exists).
   178  	if len(tab.Families) == 0 {
   179  		tab.Families = []*Family{{FamName: "primary", Ordinal: 0, table: tab}}
   180  	}
   181  OuterLoop:
   182  	for colOrd, col := range tab.Columns {
   183  		for _, fam := range tab.Families {
   184  			for _, famCol := range fam.Columns {
   185  				if col.Name == string(famCol.ColName()) {
   186  					continue OuterLoop
   187  				}
   188  			}
   189  		}
   190  		tab.Families[0].Columns = append(tab.Families[0].Columns,
   191  			cat.FamilyColumn{Column: col, Ordinal: colOrd})
   192  	}
   193  
   194  	// Search for foreign key constraints. We want to process them after first
   195  	// processing all the indexes (otherwise the foreign keys could add
   196  	// unnecessary indexes).
   197  	for _, def := range stmt.Defs {
   198  		switch def := def.(type) {
   199  		case *tree.ForeignKeyConstraintTableDef:
   200  			tc.resolveFK(tab, def)
   201  		}
   202  	}
   203  
   204  	// Add the new table to the catalog.
   205  	tc.AddTable(tab)
   206  
   207  	return tab
   208  }
   209  
   210  func (tc *Catalog) createVirtualTable(stmt *tree.CreateTable) *Table {
   211  	tab := &Table{
   212  		TabID:     tc.nextStableID(),
   213  		TabName:   stmt.Table,
   214  		Catalog:   tc,
   215  		IsVirtual: true,
   216  	}
   217  
   218  	// Add the dummy PK column.
   219  	tab.Columns = []*Column{{
   220  		Ordinal:  0,
   221  		Hidden:   true,
   222  		Nullable: false,
   223  		Name:     "crdb_internal_vtable_pk",
   224  		Type:     types.Int,
   225  	}}
   226  
   227  	for _, def := range stmt.Defs {
   228  		switch def := def.(type) {
   229  		case *tree.ColumnTableDef:
   230  			tab.addColumn(def)
   231  		}
   232  	}
   233  
   234  	tab.Families = []*Family{{FamName: "primary", Ordinal: 0, table: tab}}
   235  	for colOrd, col := range tab.Columns {
   236  		tab.Families[0].Columns = append(tab.Families[0].Columns,
   237  			cat.FamilyColumn{Column: col, Ordinal: colOrd})
   238  	}
   239  
   240  	tab.addPrimaryColumnIndex(tab.Columns[0].Name)
   241  	return tab
   242  }
   243  
   244  // CreateTableAs creates a table in the catalog with the given name and
   245  // columns. It should be used for creating a table from the CREATE TABLE <name>
   246  // AS <query> syntax. In addition to the provided columns, CreateTableAs adds a
   247  // unique rowid column as the primary key. It returns a pointer to the new
   248  // table.
   249  func (tc *Catalog) CreateTableAs(name tree.TableName, columns []*Column) *Table {
   250  	// Update the table name to include catalog and schema if not provided.
   251  	tc.qualifyTableName(&name)
   252  
   253  	tab := &Table{TabID: tc.nextStableID(), TabName: name, Catalog: tc, Columns: columns}
   254  
   255  	rowid := &Column{
   256  		Ordinal:     tab.ColumnCount(),
   257  		Name:        "rowid",
   258  		Type:        types.Int,
   259  		Hidden:      true,
   260  		DefaultExpr: &uniqueRowIDString,
   261  	}
   262  	tab.Columns = append(tab.Columns, rowid)
   263  	tab.addPrimaryColumnIndex("rowid")
   264  
   265  	// Add the new table to the catalog.
   266  	tc.AddTable(tab)
   267  
   268  	return tab
   269  }
   270  
   271  // resolveFK processes a foreign key constraint.
   272  func (tc *Catalog) resolveFK(tab *Table, d *tree.ForeignKeyConstraintTableDef) {
   273  	fromCols := make([]int, len(d.FromCols))
   274  	for i, c := range d.FromCols {
   275  		fromCols[i] = tab.FindOrdinal(string(c))
   276  	}
   277  
   278  	var targetTable *Table
   279  	if d.Table.ObjectName == tab.Name() {
   280  		targetTable = tab
   281  	} else {
   282  		targetTable = tc.Table(&d.Table)
   283  	}
   284  
   285  	toCols := make([]int, len(d.ToCols))
   286  	for i, c := range d.ToCols {
   287  		toCols[i] = targetTable.FindOrdinal(string(c))
   288  	}
   289  
   290  	constraintName := string(d.Name)
   291  	if constraintName == "" {
   292  		constraintName = fmt.Sprintf(
   293  			"fk_%s_ref_%s", string(d.FromCols[0]), targetTable.TabName.Table(),
   294  		)
   295  	}
   296  
   297  	// Foreign keys require indexes in both tables:
   298  	//
   299  	//  1. In the target table, we need an index because adding a new row to the
   300  	//     source table requires looking up whether there is a matching value in
   301  	//     the target table. This index should already exist because a unique
   302  	//     constraint is required on the target table (it's a foreign *key*).
   303  	//
   304  	//  2. In the source table, we need an index because removing a row from the
   305  	//     target table requires looking up whether there would be orphan values
   306  	//     left in the source table. This index does not need to be unique; in
   307  	//     fact, if an existing index has the relevant columns as a prefix, that
   308  	//     is good enough.
   309  
   310  	// matches returns true if the key columns in the given index match the given
   311  	// columns. If strict is false, it is acceptable if the given columns are a
   312  	// prefix of the index key columns.
   313  	matches := func(idx *Index, cols []int, strict bool) bool {
   314  		if idx.LaxKeyColumnCount() < len(cols) {
   315  			return false
   316  		}
   317  		if strict && idx.LaxKeyColumnCount() > len(cols) {
   318  			return false
   319  		}
   320  		for i := range cols {
   321  			if idx.Column(i).Ordinal != cols[i] {
   322  				return false
   323  			}
   324  		}
   325  		return true
   326  	}
   327  
   328  	// 1. Verify that the target table has a unique index.
   329  	var targetIndex *Index
   330  	for _, idx := range targetTable.Indexes {
   331  		if matches(idx, toCols, true /* strict */) {
   332  			targetIndex = idx
   333  			break
   334  		}
   335  	}
   336  	if targetIndex == nil {
   337  		panic(fmt.Errorf(
   338  			"there is no unique constraint matching given keys for referenced table %s",
   339  			targetTable.Name(),
   340  		))
   341  	}
   342  
   343  	// 2. Search for an existing index in the source table; add it if necessary.
   344  	found := false
   345  	for _, idx := range tab.Indexes {
   346  		if matches(idx, fromCols, false /* strict */) {
   347  			found = true
   348  			break
   349  		}
   350  	}
   351  	if !found {
   352  		// Add a non-unique index on fromCols.
   353  		idx := tree.IndexTableDef{
   354  			Name:    tree.Name(fmt.Sprintf("%s_auto_index_%s", tab.TabName.Table(), constraintName)),
   355  			Columns: make(tree.IndexElemList, len(fromCols)),
   356  		}
   357  		for i, c := range fromCols {
   358  			idx.Columns[i].Column = tab.Columns[c].ColName()
   359  			idx.Columns[i].Direction = tree.Ascending
   360  		}
   361  		tab.addIndex(&idx, nonUniqueIndex)
   362  	}
   363  
   364  	fk := ForeignKeyConstraint{
   365  		name:                     constraintName,
   366  		originTableID:            tab.ID(),
   367  		referencedTableID:        targetTable.ID(),
   368  		originColumnOrdinals:     fromCols,
   369  		referencedColumnOrdinals: toCols,
   370  		validated:                true,
   371  		matchMethod:              d.Match,
   372  		deleteAction:             d.Actions.Delete,
   373  		updateAction:             d.Actions.Update,
   374  	}
   375  	tab.outboundFKs = append(tab.outboundFKs, fk)
   376  	targetTable.inboundFKs = append(targetTable.inboundFKs, fk)
   377  }
   378  
   379  func (tt *Table) addColumn(def *tree.ColumnTableDef) {
   380  	nullable := !def.PrimaryKey.IsPrimaryKey && def.Nullable.Nullability != tree.NotNull
   381  	col := &Column{
   382  		Ordinal:  tt.ColumnCount(),
   383  		Name:     string(def.Name),
   384  		Type:     tree.MustBeStaticallyKnownType(def.Type),
   385  		Nullable: nullable,
   386  	}
   387  
   388  	// Look for name suffixes indicating this is a mutation column.
   389  	if name, ok := extractWriteOnlyColumn(def); ok {
   390  		col.Name = name
   391  		tt.writeOnlyColCount++
   392  	} else if name, ok := extractDeleteOnlyColumn(def); ok {
   393  		col.Name = name
   394  		tt.deleteOnlyColCount++
   395  	}
   396  
   397  	if def.DefaultExpr.Expr != nil {
   398  		s := serializeTableDefExpr(def.DefaultExpr.Expr)
   399  		col.DefaultExpr = &s
   400  	}
   401  
   402  	if def.Computed.Expr != nil {
   403  		s := serializeTableDefExpr(def.Computed.Expr)
   404  		col.ComputedExpr = &s
   405  	}
   406  
   407  	tt.Columns = append(tt.Columns, col)
   408  }
   409  
   410  func (tt *Table) addIndex(def *tree.IndexTableDef, typ indexType) *Index {
   411  	idx := &Index{
   412  		IdxName:     tt.makeIndexName(def.Name, typ),
   413  		Unique:      typ != nonUniqueIndex,
   414  		Inverted:    def.Inverted,
   415  		IdxZone:     &zonepb.ZoneConfig{},
   416  		table:       tt,
   417  		partitionBy: def.PartitionBy,
   418  	}
   419  
   420  	// Look for name suffixes indicating this is a mutation index.
   421  	if name, ok := extractWriteOnlyIndex(def); ok {
   422  		idx.IdxName = name
   423  		tt.writeOnlyIdxCount++
   424  	} else if name, ok := extractDeleteOnlyIndex(def); ok {
   425  		idx.IdxName = name
   426  		tt.deleteOnlyIdxCount++
   427  	}
   428  
   429  	// Add explicit columns and mark primary key columns as not null.
   430  	notNullIndex := true
   431  	for _, colDef := range def.Columns {
   432  		col := idx.addColumn(tt, string(colDef.Column), colDef.Direction, keyCol)
   433  
   434  		if typ == primaryIndex {
   435  			col.Nullable = false
   436  		}
   437  
   438  		if col.Nullable {
   439  			notNullIndex = false
   440  		}
   441  	}
   442  
   443  	if typ == primaryIndex {
   444  		var pkOrdinals util.FastIntSet
   445  		for _, c := range idx.Columns {
   446  			pkOrdinals.Add(c.Ordinal)
   447  		}
   448  		// Add the rest of the columns in the table.
   449  		for i, n := 0, tt.DeletableColumnCount(); i < n; i++ {
   450  			if !pkOrdinals.Contains(i) {
   451  				idx.addColumnByOrdinal(tt, i, tree.Ascending, nonKeyCol)
   452  			}
   453  		}
   454  		if len(tt.Indexes) != 0 {
   455  			panic("primary index should always be 0th index")
   456  		}
   457  		idx.ordinal = len(tt.Indexes)
   458  		tt.Indexes = append(tt.Indexes, idx)
   459  		return idx
   460  	}
   461  
   462  	// Add implicit key columns from primary index.
   463  	pkCols := tt.Indexes[cat.PrimaryIndex].Columns[:tt.Indexes[cat.PrimaryIndex].KeyCount]
   464  	for _, pkCol := range pkCols {
   465  		// Only add columns that aren't already part of index.
   466  		found := false
   467  		for _, colDef := range def.Columns {
   468  			if pkCol.ColName() == colDef.Column {
   469  				found = true
   470  			}
   471  		}
   472  
   473  		if !found {
   474  			name := string(pkCol.ColName())
   475  
   476  			if typ == uniqueIndex {
   477  				// If unique index has no NULL columns, then the implicit columns
   478  				// are added as storing columns. Otherwise, they become part of the
   479  				// strict key, since they're needed to ensure uniqueness (but they
   480  				// are not part of the lax key).
   481  				if notNullIndex {
   482  					idx.addColumn(tt, name, tree.Ascending, nonKeyCol)
   483  				} else {
   484  					idx.addColumn(tt, name, tree.Ascending, strictKeyCol)
   485  				}
   486  			} else {
   487  				// Implicit columns are always added to the key for a non-unique
   488  				// index. In addition, there is no separate lax key, so the lax
   489  				// key column count = key column count.
   490  				idx.addColumn(tt, name, tree.Ascending, keyCol)
   491  			}
   492  		}
   493  	}
   494  
   495  	// Add storing columns.
   496  	for _, name := range def.Storing {
   497  		// Only add storing columns that weren't added as part of adding implicit
   498  		// key columns.
   499  		found := false
   500  		for _, pkCol := range pkCols {
   501  			if name == pkCol.ColName() {
   502  				found = true
   503  			}
   504  		}
   505  		if !found {
   506  			idx.addColumn(tt, string(name), tree.Ascending, nonKeyCol)
   507  		}
   508  	}
   509  
   510  	// Add partial index predicate.
   511  	if def.Predicate != nil {
   512  		idx.predicate = tree.Serialize(def.Predicate)
   513  	}
   514  
   515  	idx.ordinal = len(tt.Indexes)
   516  	tt.Indexes = append(tt.Indexes, idx)
   517  
   518  	return idx
   519  }
   520  
   521  func (tt *Table) makeIndexName(defName tree.Name, typ indexType) string {
   522  	name := string(defName)
   523  	if name == "" {
   524  		if typ == primaryIndex {
   525  			name = "primary"
   526  		} else {
   527  			name = "secondary"
   528  		}
   529  	}
   530  	return name
   531  }
   532  
   533  func (tt *Table) addFamily(def *tree.FamilyTableDef) {
   534  	// Synthesize name if one was not provided.
   535  	name := string(def.Name)
   536  	if name == "" {
   537  		name = fmt.Sprintf("family%d", len(tt.Families)+1)
   538  	}
   539  
   540  	family := &Family{
   541  		FamName: name,
   542  		Ordinal: tt.FamilyCount(),
   543  		table:   tt,
   544  	}
   545  
   546  	// Add columns to family.
   547  	for _, defCol := range def.Columns {
   548  		ord := tt.FindOrdinal(string(defCol))
   549  		col := tt.Column(ord)
   550  		family.Columns = append(family.Columns, cat.FamilyColumn{Column: col, Ordinal: ord})
   551  	}
   552  
   553  	tt.Families = append(tt.Families, family)
   554  }
   555  
   556  func (ti *Index) addColumn(
   557  	tt *Table, name string, direction tree.Direction, colType colType,
   558  ) *Column {
   559  	return ti.addColumnByOrdinal(tt, tt.FindOrdinal(name), direction, colType)
   560  }
   561  
   562  func (ti *Index) addColumnByOrdinal(
   563  	tt *Table, ord int, direction tree.Direction, colType colType,
   564  ) *Column {
   565  	col := tt.Column(ord)
   566  	idxCol := cat.IndexColumn{
   567  		Column:     col,
   568  		Ordinal:    ord,
   569  		Descending: direction == tree.Descending,
   570  	}
   571  	ti.Columns = append(ti.Columns, idxCol)
   572  
   573  	// Update key column counts.
   574  	switch colType {
   575  	case keyCol:
   576  		// Column is part of both any lax key, as well as the strict key.
   577  		ti.LaxKeyCount++
   578  		ti.KeyCount++
   579  
   580  	case strictKeyCol:
   581  		// Column is only part of the strict key.
   582  		ti.KeyCount++
   583  	}
   584  
   585  	return col.(*Column)
   586  }
   587  
   588  func (tt *Table) addPrimaryColumnIndex(colName string) {
   589  	def := tree.IndexTableDef{
   590  		Columns: tree.IndexElemList{{Column: tree.Name(colName), Direction: tree.Ascending}},
   591  	}
   592  	tt.addIndex(&def, primaryIndex)
   593  }
   594  
   595  func extractWriteOnlyColumn(def *tree.ColumnTableDef) (name string, ok bool) {
   596  	if !strings.HasSuffix(string(def.Name), ":write-only") {
   597  		return "", false
   598  	}
   599  	return strings.TrimSuffix(string(def.Name), ":write-only"), true
   600  }
   601  
   602  func extractDeleteOnlyColumn(def *tree.ColumnTableDef) (name string, ok bool) {
   603  	if !strings.HasSuffix(string(def.Name), ":delete-only") {
   604  		return "", false
   605  	}
   606  	return strings.TrimSuffix(string(def.Name), ":delete-only"), true
   607  }
   608  
   609  func isMutationColumn(def *tree.ColumnTableDef) bool {
   610  	if _, ok := extractWriteOnlyColumn(def); ok {
   611  		return true
   612  	}
   613  	if _, ok := extractDeleteOnlyColumn(def); ok {
   614  		return true
   615  	}
   616  	return false
   617  }
   618  
   619  func extractWriteOnlyIndex(def *tree.IndexTableDef) (name string, ok bool) {
   620  	if !strings.HasSuffix(string(def.Name), ":write-only") {
   621  		return "", false
   622  	}
   623  	return strings.TrimSuffix(string(def.Name), ":write-only"), true
   624  }
   625  
   626  func extractDeleteOnlyIndex(def *tree.IndexTableDef) (name string, ok bool) {
   627  	if !strings.HasSuffix(string(def.Name), ":delete-only") {
   628  		return "", false
   629  	}
   630  	return strings.TrimSuffix(string(def.Name), ":delete-only"), true
   631  }
   632  
   633  func validatedCheckConstraint(def *tree.CheckConstraintTableDef) bool {
   634  	return !strings.HasSuffix(string(def.Name), ":unvalidated")
   635  }
   636  
   637  func serializeTableDefExpr(expr tree.Expr) string {
   638  	// Disallow any column references that are qualified with the table. The
   639  	// production table creation code verifies them and strips them away, so the
   640  	// stored expressions contain only unqualified column references.
   641  	preFn := func(expr tree.Expr) (recurse bool, newExpr tree.Expr, err error) {
   642  		if vBase, ok := expr.(tree.VarName); ok {
   643  			v, err := vBase.NormalizeVarName()
   644  			if err != nil {
   645  				return false, nil, err
   646  			}
   647  			if c, ok := v.(*tree.ColumnItem); ok && c.TableName != nil {
   648  				return false, nil, fmt.Errorf(
   649  					"expressions in table definitions must not contain qualified column references: %s", c,
   650  				)
   651  			}
   652  		}
   653  		return true, expr, nil
   654  	}
   655  	_, err := tree.SimpleVisit(expr, preFn)
   656  	if err != nil {
   657  		panic(err)
   658  	}
   659  	return tree.Serialize(expr)
   660  }