From 3447ac2f554a1fb113eabc048497637b3e32346e Mon Sep 17 00:00:00 2001 From: xia Date: Thu, 22 Oct 2015 17:57:59 +0800 Subject: [PATCH] stmt: add replace statment --- stmt/stmts/replace.go | 99 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 stmt/stmts/replace.go diff --git a/stmt/stmts/replace.go b/stmt/stmts/replace.go new file mode 100644 index 0000000000..0494f9e722 --- /dev/null +++ b/stmt/stmts/replace.go @@ -0,0 +1,99 @@ +// Copyright 2015 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package stmts + +import ( + "github.com/juju/errors" + "github.com/pingcap/tidb/context" + "github.com/pingcap/tidb/expression" + "github.com/pingcap/tidb/plan" + "github.com/pingcap/tidb/rset" + "github.com/pingcap/tidb/table" + "github.com/pingcap/tidb/util/format" +) + +// ReplaceIntoStmt is a statement works exactly like insert, except that if +// an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, +// the old row is deleted before the new row is inserted. +// See: https://dev.mysql.com/doc/refman/5.7/en/replace.html +type ReplaceIntoStmt struct { + ColNames []string + Lists [][]expression.Expression + Sel plan.Planner + TableIdent table.Ident + SetList []*expression.Assignment + Priority int + + Text string +} + +// Explain implements the stmt.Statement Explain interface. +func (s *ReplaceIntoStmt) Explain(ctx context.Context, w format.Formatter) { + w.Format("%s\n", s.Text) +} + +// IsDDL implements the stmt.Statement IsDDL interface. +func (s *ReplaceIntoStmt) IsDDL() bool { + return false +} + +// OriginText implements the stmt.Statement OriginText interface. +func (s *ReplaceIntoStmt) OriginText() string { + return s.Text +} + +// SetText implements the stmt.Statement SetText interface. +func (s *ReplaceIntoStmt) SetText(text string) { + s.Text = text +} + +// Exec implements the stmt.Statement Exec interface. +func (s *ReplaceIntoStmt) Exec(ctx context.Context) (_ rset.Recordset, err error) { + stmt := &InsertIntoStmt{ColNames: s.ColNames, Lists: s.Lists, Priority: s.Priority, + Sel: s.Sel, Setlist: s.SetList, TableIdent: s.TableIdent, Text: s.Text} + t, err := getTable(ctx, stmt.TableIdent) + if err != nil { + return nil, errors.Trace(err) + } + cols, err := stmt.getColumns(t.Cols()) + if err != nil { + return nil, errors.Trace(err) + } + + // Process `replace ... (select ...)` + if stmt.Sel != nil { + return stmt.execSelect(t, cols, ctx) + } + // Process `replace ... set x=y ...` + if err = stmt.getSetList(); err != nil { + return nil, errors.Trace(err) + } + m, err := stmt.getDefaultValues(ctx, t.Cols()) + if err != nil { + return nil, errors.Trace(err) + } + replaceValueCount := len(stmt.Lists[0]) + + for i, list := range stmt.Lists { + if err = stmt.checkValueCount(replaceValueCount, len(list), i, cols); err != nil { + return nil, errors.Trace(err) + } + // TODO: remove that has the same value as a new row for a PRIMARY KEY or a UNIQUE index. + if _, _, err = stmt.addRecord(ctx, t, cols, list, m); err != nil { + return nil, errors.Trace(err) + } + } + + return nil, nil +}