github.com/dolthub/go-mysql-server@v0.18.0/sql/plan/ddl.go (about)

     1  // Copyright 2020-2021 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	"github.com/dolthub/go-mysql-server/sql/transform"
    22  
    23  	"github.com/dolthub/go-mysql-server/sql"
    24  	"github.com/dolthub/go-mysql-server/sql/types"
    25  )
    26  
    27  type IfNotExistsOption bool
    28  
    29  const (
    30  	IfNotExists       IfNotExistsOption = true
    31  	IfNotExistsAbsent IfNotExistsOption = false
    32  )
    33  
    34  type TempTableOption bool
    35  
    36  const (
    37  	IsTempTable       TempTableOption = true
    38  	IsTempTableAbsent TempTableOption = false
    39  )
    40  
    41  // Ddl nodes have a reference to a database, but no children and a nil schema.
    42  type ddlNode struct {
    43  	Db sql.Database
    44  }
    45  
    46  // Resolved implements the Resolvable interface.
    47  func (c *ddlNode) Resolved() bool {
    48  	_, ok := c.Db.(sql.UnresolvedDatabase)
    49  	return !ok
    50  }
    51  
    52  // Database implements the sql.Databaser interface.
    53  func (c *ddlNode) Database() sql.Database {
    54  	return c.Db
    55  }
    56  
    57  // Schema implements the Node interface.
    58  func (*ddlNode) Schema() sql.Schema {
    59  	return types.OkResultSchema
    60  }
    61  
    62  // Children implements the Node interface.
    63  func (c *ddlNode) Children() []sql.Node { return nil }
    64  
    65  type IndexDefinition struct {
    66  	IndexName  string
    67  	Using      sql.IndexUsing
    68  	Constraint sql.IndexConstraint
    69  	Columns    []sql.IndexColumn
    70  	Comment    string
    71  }
    72  
    73  func (i *IndexDefinition) String() string {
    74  	return i.IndexName
    75  }
    76  
    77  func (i *IndexDefinition) IsSpatial() bool {
    78  	return i.Constraint == sql.IndexConstraint_Spatial
    79  }
    80  
    81  func (i *IndexDefinition) IsUnique() bool {
    82  	return i.Constraint == sql.IndexConstraint_Unique
    83  }
    84  
    85  func (i *IndexDefinition) IsFullText() bool {
    86  	return i.Constraint == sql.IndexConstraint_Fulltext
    87  }
    88  
    89  // ColumnNames returns each column's name without the length property.
    90  func (i *IndexDefinition) ColumnNames() []string {
    91  	colNames := make([]string, len(i.Columns))
    92  	for i, col := range i.Columns {
    93  		colNames[i] = col.Name
    94  	}
    95  	return colNames
    96  }
    97  
    98  // AsIndexDef returns the IndexDefinition as the other form.
    99  func (i *IndexDefinition) AsIndexDef() sql.IndexDef {
   100  	//TODO: We should get rid of this IndexDefinition and just use the SQL package one
   101  	cols := make([]sql.IndexColumn, len(i.Columns))
   102  	copy(cols, i.Columns)
   103  	return sql.IndexDef{
   104  		Name:       i.IndexName,
   105  		Columns:    cols,
   106  		Constraint: i.Constraint,
   107  		Storage:    i.Using,
   108  		Comment:    i.Comment,
   109  	}
   110  }
   111  
   112  // TableSpec is a node describing the schema of a table.
   113  type TableSpec struct {
   114  	Schema    sql.PrimaryKeySchema
   115  	FkDefs    []*sql.ForeignKeyConstraint
   116  	ChDefs    []*sql.CheckConstraint
   117  	IdxDefs   []*IndexDefinition
   118  	Collation sql.CollationID
   119  	Comment   string
   120  }
   121  
   122  func (c *TableSpec) WithSchema(schema sql.PrimaryKeySchema) *TableSpec {
   123  	nc := *c
   124  	nc.Schema = schema
   125  	return &nc
   126  }
   127  
   128  func (c *TableSpec) WithForeignKeys(fkDefs []*sql.ForeignKeyConstraint) *TableSpec {
   129  	nc := *c
   130  	nc.FkDefs = fkDefs
   131  	return &nc
   132  }
   133  
   134  func (c *TableSpec) WithCheckConstraints(chDefs []*sql.CheckConstraint) *TableSpec {
   135  	nc := *c
   136  	nc.ChDefs = chDefs
   137  	return &nc
   138  }
   139  
   140  func (c *TableSpec) WithIndices(idxDefs []*IndexDefinition) *TableSpec {
   141  	nc := *c
   142  	nc.IdxDefs = idxDefs
   143  	return &nc
   144  }
   145  
   146  // CreateTable is a node describing the creation of some table.
   147  type CreateTable struct {
   148  	ddlNode
   149  	name         string
   150  	CreateSchema sql.PrimaryKeySchema
   151  	ifNotExists  IfNotExistsOption
   152  	FkDefs       []*sql.ForeignKeyConstraint
   153  	fkParentTbls []sql.ForeignKeyTable
   154  	checks       sql.CheckConstraints
   155  	IdxDefs      []*IndexDefinition
   156  	Collation    sql.CollationID
   157  	Comment      string
   158  	like         sql.Node
   159  	temporary    TempTableOption
   160  	selectNode   sql.Node
   161  }
   162  
   163  var _ sql.Databaser = (*CreateTable)(nil)
   164  var _ sql.Node = (*CreateTable)(nil)
   165  var _ sql.Expressioner = (*CreateTable)(nil)
   166  var _ sql.SchemaTarget = (*CreateTable)(nil)
   167  var _ sql.CheckConstraintNode = (*CreateTable)(nil)
   168  var _ sql.CollationCoercible = (*CreateTable)(nil)
   169  
   170  // NewCreateTable creates a new CreateTable node
   171  func NewCreateTable(db sql.Database, name string, ifn IfNotExistsOption, temp TempTableOption, tableSpec *TableSpec) *CreateTable {
   172  	for _, s := range tableSpec.Schema.Schema {
   173  		s.Source = name
   174  	}
   175  
   176  	return &CreateTable{
   177  		ddlNode:      ddlNode{db},
   178  		name:         name,
   179  		CreateSchema: tableSpec.Schema,
   180  		FkDefs:       tableSpec.FkDefs,
   181  		checks:       tableSpec.ChDefs,
   182  		IdxDefs:      tableSpec.IdxDefs,
   183  		Collation:    tableSpec.Collation,
   184  		Comment:      tableSpec.Comment,
   185  		ifNotExists:  ifn,
   186  		temporary:    temp,
   187  	}
   188  }
   189  
   190  // NewCreateTableSelect create a new CreateTable node for CREATE TABLE [AS] SELECT
   191  func NewCreateTableSelect(db sql.Database, name string, selectNode sql.Node, tableSpec *TableSpec, ifn IfNotExistsOption, temp TempTableOption) *CreateTable {
   192  	for _, s := range tableSpec.Schema.Schema {
   193  		s.Source = name
   194  	}
   195  
   196  	return &CreateTable{
   197  		ddlNode:      ddlNode{Db: db},
   198  		CreateSchema: tableSpec.Schema,
   199  		FkDefs:       tableSpec.FkDefs,
   200  		checks:       tableSpec.ChDefs,
   201  		IdxDefs:      tableSpec.IdxDefs,
   202  		name:         name,
   203  		selectNode:   selectNode,
   204  		ifNotExists:  ifn,
   205  		temporary:    temp,
   206  	}
   207  }
   208  
   209  func (c *CreateTable) Checks() sql.CheckConstraints {
   210  	return c.checks
   211  }
   212  
   213  func (c *CreateTable) WithChecks(checks sql.CheckConstraints) sql.Node {
   214  	ret := *c
   215  	ret.checks = checks
   216  	return &ret
   217  }
   218  
   219  // WithTargetSchema  implements the sql.TargetSchema interface.
   220  func (c *CreateTable) WithTargetSchema(schema sql.Schema) (sql.Node, error) {
   221  	return nil, fmt.Errorf("unable to set target schema without primary key info")
   222  }
   223  
   224  // TargetSchema implements the sql.TargetSchema interface.
   225  func (c *CreateTable) TargetSchema() sql.Schema {
   226  	return c.CreateSchema.Schema
   227  }
   228  
   229  // WithDatabase implements the sql.Databaser interface.
   230  func (c *CreateTable) WithDatabase(db sql.Database) (sql.Node, error) {
   231  	nc := *c
   232  	nc.Db = db
   233  	return &nc, nil
   234  }
   235  
   236  // Schema implements the sql.Node interface.
   237  func (c *CreateTable) Schema() sql.Schema {
   238  	return types.OkResultSchema
   239  }
   240  
   241  func (c *CreateTable) PkSchema() sql.PrimaryKeySchema {
   242  	return c.CreateSchema
   243  }
   244  
   245  // Resolved implements the Resolvable interface.
   246  func (c *CreateTable) Resolved() bool {
   247  	if !c.ddlNode.Resolved() || !c.CreateSchema.Schema.Resolved() {
   248  		return false
   249  	}
   250  
   251  	for _, chDef := range c.checks {
   252  		if !chDef.Expr.Resolved() {
   253  			return false
   254  		}
   255  	}
   256  
   257  	if c.like != nil {
   258  		if !c.like.Resolved() {
   259  			return false
   260  		}
   261  	}
   262  
   263  	return true
   264  }
   265  
   266  func (c *CreateTable) IsReadOnly() bool {
   267  	return false
   268  }
   269  
   270  // ForeignKeys returns any foreign keys that will be declared on this table.
   271  func (c *CreateTable) ForeignKeys() []*sql.ForeignKeyConstraint {
   272  	return c.FkDefs
   273  }
   274  
   275  // WithParentForeignKeyTables adds the tables that are referenced in each foreign key. The table indices is assumed
   276  // to match the foreign key indices in their respective slices.
   277  func (c *CreateTable) WithParentForeignKeyTables(refTbls []sql.ForeignKeyTable) (*CreateTable, error) {
   278  	if len(c.FkDefs) != len(refTbls) {
   279  		return nil, fmt.Errorf("table `%s` defines `%d` foreign keys but found `%d` referenced tables",
   280  			c.name, len(c.FkDefs), len(refTbls))
   281  	}
   282  	nc := *c
   283  	nc.fkParentTbls = refTbls
   284  	return &nc, nil
   285  }
   286  
   287  func (c *CreateTable) CreateForeignKeys(ctx *sql.Context, tableNode sql.Table) error {
   288  	fkTbl, ok := tableNode.(sql.ForeignKeyTable)
   289  	if !ok {
   290  		return sql.ErrNoForeignKeySupport.New(c.name)
   291  	}
   292  
   293  	fkChecks, err := ctx.GetSessionVariable(ctx, "foreign_key_checks")
   294  	if err != nil {
   295  		return err
   296  	}
   297  
   298  	for i, fkDef := range c.FkDefs {
   299  		if fkDef.OnUpdate == sql.ForeignKeyReferentialAction_SetDefault || fkDef.OnDelete == sql.ForeignKeyReferentialAction_SetDefault {
   300  			return sql.ErrForeignKeySetDefault.New()
   301  		}
   302  
   303  		if fkChecks.(int8) == 1 {
   304  			fkParentTbl := c.fkParentTbls[i]
   305  			// If a foreign key is self-referential then the analyzer uses a nil since the table does not yet exist
   306  			if fkParentTbl == nil {
   307  				fkParentTbl = fkTbl
   308  			}
   309  			// If foreign_key_checks are true, then the referenced tables will be populated
   310  			err = ResolveForeignKey(ctx, fkTbl, fkParentTbl, *fkDef, true, true, true)
   311  			if err != nil {
   312  				return err
   313  			}
   314  		} else {
   315  			// If foreign_key_checks are true, then the referenced tables will be populated
   316  			err = ResolveForeignKey(ctx, fkTbl, nil, *fkDef, true, false, false)
   317  			if err != nil {
   318  				return err
   319  			}
   320  		}
   321  	}
   322  
   323  	return nil
   324  }
   325  
   326  func (c *CreateTable) CreateChecks(ctx *sql.Context, tableNode sql.Table) error {
   327  	chAlterable, ok := tableNode.(sql.CheckAlterableTable)
   328  	if !ok {
   329  		return ErrNoCheckConstraintSupport.New(c.name)
   330  	}
   331  
   332  	for _, ch := range c.checks {
   333  		check, err := NewCheckDefinition(ctx, ch)
   334  		if err != nil {
   335  			return err
   336  		}
   337  		err = chAlterable.CreateCheck(ctx, check)
   338  		if err != nil {
   339  			return err
   340  		}
   341  	}
   342  
   343  	return nil
   344  }
   345  
   346  // Children implements the Node interface.
   347  func (c *CreateTable) Children() []sql.Node {
   348  	if c.like != nil {
   349  		return []sql.Node{c.like}
   350  	} else if c.selectNode != nil {
   351  		return []sql.Node{c.selectNode}
   352  	}
   353  	return nil
   354  }
   355  
   356  // WithChildren implements the Node interface.
   357  func (c CreateTable) WithChildren(children ...sql.Node) (sql.Node, error) {
   358  	if len(children) == 0 {
   359  		return &c, nil
   360  	} else if len(children) == 1 {
   361  		child := children[0]
   362  
   363  		if c.like != nil {
   364  			c.like = child
   365  		} else {
   366  			c.selectNode = child
   367  		}
   368  
   369  		return &c, nil
   370  	} else {
   371  		return nil, sql.ErrInvalidChildrenNumber.New(c, len(children), 1)
   372  	}
   373  }
   374  
   375  // CheckPrivileges implements the interface sql.Node.
   376  func (c *CreateTable) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
   377  	priv := sql.PrivilegeType_Create
   378  	if c.temporary == IsTempTable {
   379  		priv = sql.PrivilegeType_CreateTempTable
   380  	}
   381  	subject := sql.PrivilegeCheckSubject{Database: CheckPrivilegeNameForDatabase(c.Db)}
   382  	return opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(subject, priv))
   383  }
   384  
   385  // CollationCoercibility implements the interface sql.CollationCoercible.
   386  func (*CreateTable) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) {
   387  	return sql.Collation_binary, 7
   388  }
   389  
   390  func (c *CreateTable) String() string {
   391  	ifNotExists := ""
   392  	if c.ifNotExists {
   393  		ifNotExists = "if not exists "
   394  	}
   395  	return fmt.Sprintf("Create table %s%s", ifNotExists, c.name)
   396  }
   397  
   398  func (c *CreateTable) DebugString() string {
   399  	ifNotExists := ""
   400  	if c.ifNotExists {
   401  		ifNotExists = "if not exists "
   402  	}
   403  	p := sql.NewTreePrinter()
   404  
   405  	if c.selectNode != nil {
   406  		p.WriteNode("Create table %s%s as", ifNotExists, c.name)
   407  		p.WriteChildren(sql.DebugString(c.selectNode))
   408  		return p.String()
   409  	}
   410  
   411  	p.WriteNode("Create table %s%s", ifNotExists, c.name)
   412  
   413  	var children []string
   414  	children = append(children, c.schemaDebugString())
   415  
   416  	if len(c.FkDefs) > 0 {
   417  		children = append(children, c.foreignKeysDebugString())
   418  	}
   419  	if len(c.IdxDefs) > 0 {
   420  		children = append(children, c.indexesDebugString())
   421  	}
   422  	if len(c.checks) > 0 {
   423  		children = append(children, c.checkConstraintsDebugString())
   424  	}
   425  
   426  	p.WriteChildren(children...)
   427  	return p.String()
   428  }
   429  
   430  func (c *CreateTable) foreignKeysDebugString() string {
   431  	p := sql.NewTreePrinter()
   432  	p.WriteNode("ForeignKeys")
   433  	var children []string
   434  	for _, def := range c.FkDefs {
   435  		children = append(children, sql.DebugString(def))
   436  	}
   437  	p.WriteChildren(children...)
   438  	return p.String()
   439  }
   440  
   441  func (c *CreateTable) indexesDebugString() string {
   442  	p := sql.NewTreePrinter()
   443  	p.WriteNode("Indexes")
   444  	var children []string
   445  	for _, def := range c.IdxDefs {
   446  		children = append(children, sql.DebugString(def))
   447  	}
   448  	p.WriteChildren(children...)
   449  	return p.String()
   450  }
   451  
   452  func (c *CreateTable) checkConstraintsDebugString() string {
   453  	p := sql.NewTreePrinter()
   454  	p.WriteNode("CheckConstraints")
   455  	var children []string
   456  	for _, def := range c.checks {
   457  		children = append(children, sql.DebugString(def))
   458  	}
   459  	p.WriteChildren(children...)
   460  	return p.String()
   461  }
   462  
   463  func (c *CreateTable) schemaDebugString() string {
   464  	p := sql.NewTreePrinter()
   465  	p.WriteNode("Columns")
   466  	var children []string
   467  	for _, col := range c.CreateSchema.Schema {
   468  		children = append(children, sql.DebugString(col))
   469  	}
   470  	p.WriteChildren(children...)
   471  	return p.String()
   472  }
   473  
   474  func (c *CreateTable) Expressions() []sql.Expression {
   475  	exprs := transform.WrappedColumnDefaults(c.CreateSchema.Schema)
   476  
   477  	for _, ch := range c.checks {
   478  		exprs = append(exprs, ch.Expr)
   479  	}
   480  
   481  	return exprs
   482  }
   483  
   484  func (c *CreateTable) Like() sql.Node {
   485  	return c.like
   486  }
   487  
   488  func (c *CreateTable) Select() sql.Node {
   489  	return c.selectNode
   490  }
   491  
   492  func (c *CreateTable) TableSpec() *TableSpec {
   493  	tableSpec := TableSpec{}
   494  
   495  	ret := tableSpec.WithSchema(c.CreateSchema)
   496  	ret = ret.WithForeignKeys(c.FkDefs)
   497  	ret = ret.WithIndices(c.IdxDefs)
   498  	ret = ret.WithCheckConstraints(c.checks)
   499  	ret.Collation = c.Collation
   500  	ret.Comment = c.Comment
   501  
   502  	return ret
   503  }
   504  
   505  func (c *CreateTable) Name() string {
   506  	return c.name
   507  }
   508  
   509  func (c *CreateTable) IfNotExists() IfNotExistsOption {
   510  	return c.ifNotExists
   511  }
   512  
   513  func (c *CreateTable) Temporary() TempTableOption {
   514  	return c.temporary
   515  }
   516  
   517  func (c CreateTable) WithExpressions(exprs ...sql.Expression) (sql.Node, error) {
   518  	schemaLen := len(c.CreateSchema.Schema)
   519  	length := schemaLen + len(c.checks)
   520  	if len(exprs) != length {
   521  		return nil, sql.ErrInvalidChildrenNumber.New(c, len(exprs), length)
   522  	}
   523  
   524  	nc := c
   525  
   526  	// Make sure to make a deep copy of any slices here so we aren't modifying the original pointer
   527  	ns, err := transform.SchemaWithDefaults(c.CreateSchema.Schema, exprs[:schemaLen])
   528  	if err != nil {
   529  		return nil, err
   530  	}
   531  
   532  	nc.CreateSchema = sql.NewPrimaryKeySchema(ns, c.CreateSchema.PkOrdinals...)
   533  
   534  	ncd, err := c.checks.FromExpressions(exprs[schemaLen:])
   535  	if err != nil {
   536  		return nil, err
   537  	}
   538  
   539  	nc.checks = ncd
   540  	return &nc, nil
   541  }
   542  
   543  func (c *CreateTable) ValidateDefaultPosition() error {
   544  	colsAfterThis := make(map[string]*sql.Column)
   545  	for i := len(c.CreateSchema.Schema) - 1; i >= 0; i-- {
   546  		col := c.CreateSchema.Schema[i]
   547  		colsAfterThis[col.Name] = col
   548  		if err := inspectDefaultForInvalidColumns(col, colsAfterThis); err != nil {
   549  			return err
   550  		}
   551  	}
   552  
   553  	return nil
   554  }
   555  
   556  // DropTable is a node describing dropping one or more tables
   557  type DropTable struct {
   558  	Tables       []sql.Node
   559  	ifExists     bool
   560  	TriggerNames []string
   561  }
   562  
   563  var _ sql.Node = (*DropTable)(nil)
   564  var _ sql.CollationCoercible = (*DropTable)(nil)
   565  
   566  // NewDropTable creates a new DropTable node
   567  func NewDropTable(tbls []sql.Node, ifExists bool) *DropTable {
   568  	return &DropTable{
   569  		Tables:   tbls,
   570  		ifExists: ifExists,
   571  	}
   572  }
   573  
   574  // WithTriggers returns this node but with the given triggers.
   575  func (d *DropTable) WithTriggers(triggers []string) sql.Node {
   576  	nd := *d
   577  	nd.TriggerNames = triggers
   578  	return &nd
   579  }
   580  
   581  // TableNames returns the names of the tables to drop.
   582  func (d *DropTable) TableNames() ([]string, error) {
   583  	tblNames := make([]string, len(d.Tables))
   584  	for i, t := range d.Tables {
   585  		// either *ResolvedTable OR *UnresolvedTable here
   586  		if uTable, ok := t.(*UnresolvedTable); ok {
   587  			tblNames[i] = uTable.Name()
   588  		} else if rTable, ok := t.(*ResolvedTable); ok {
   589  			tblNames[i] = rTable.Name()
   590  		} else {
   591  			return []string{}, sql.ErrInvalidType.New(t)
   592  		}
   593  	}
   594  	return tblNames, nil
   595  }
   596  
   597  // IfExists returns ifExists variable.
   598  func (d *DropTable) IfExists() bool {
   599  	return d.ifExists
   600  }
   601  
   602  // Children implements the Node interface.
   603  func (d *DropTable) Children() []sql.Node {
   604  	return d.Tables
   605  }
   606  
   607  // Resolved implements the sql.Expression interface.
   608  func (d *DropTable) Resolved() bool {
   609  	for _, table := range d.Tables {
   610  		if !table.Resolved() {
   611  			return false
   612  		}
   613  	}
   614  
   615  	return true
   616  }
   617  
   618  func (d *DropTable) IsReadOnly() bool {
   619  	return false
   620  }
   621  
   622  // Schema implements the sql.Expression interface.
   623  func (d *DropTable) Schema() sql.Schema {
   624  	return types.OkResultSchema
   625  }
   626  
   627  // WithChildren implements the Node interface.
   628  func (d *DropTable) WithChildren(children ...sql.Node) (sql.Node, error) {
   629  	// Number of children can be smaller than original as the non-existent
   630  	// tables get filtered out in some cases
   631  	var newChildren = make([]sql.Node, len(children))
   632  	copy(newChildren, children)
   633  	nd := *d
   634  	nd.Tables = newChildren
   635  	return &nd, nil
   636  }
   637  
   638  // CheckPrivileges implements the interface sql.Node.
   639  func (d *DropTable) CheckPrivileges(ctx *sql.Context, opChecker sql.PrivilegedOperationChecker) bool {
   640  	for _, tbl := range d.Tables {
   641  		subject := sql.PrivilegeCheckSubject{
   642  			Database: CheckPrivilegeNameForDatabase(GetDatabase(tbl)),
   643  			Table:    getTableName(tbl),
   644  		}
   645  
   646  		if !opChecker.UserHasPrivileges(ctx, sql.NewPrivilegedOperation(subject, sql.PrivilegeType_Drop)) {
   647  			return false
   648  		}
   649  	}
   650  	return true
   651  }
   652  
   653  // CollationCoercibility implements the interface sql.CollationCoercible.
   654  func (*DropTable) CollationCoercibility(ctx *sql.Context) (collation sql.CollationID, coercibility byte) {
   655  	return sql.Collation_binary, 7
   656  }
   657  
   658  // String implements the sql.Node interface.
   659  func (d *DropTable) String() string {
   660  	ifExists := ""
   661  	tblNames, _ := d.TableNames()
   662  	names := strings.Join(tblNames, ", ")
   663  	if d.ifExists {
   664  		ifExists = "if exists "
   665  	}
   666  	return fmt.Sprintf("Drop table %s%s", ifExists, names)
   667  }