func (p *planner) fillDefaults( defaultExprs []parser.TypedExpr, cols []sqlbase.ColumnDescriptor, n *parser.Insert, ) (parser.SelectStatement, error) { if n.DefaultValues() { row := make(parser.Exprs, 0, len(cols)) for i := range cols { if defaultExprs == nil { row = append(row, parser.DNull) continue } row = append(row, defaultExprs[i]) } return &parser.ValuesClause{Tuples: []*parser.Tuple{{Exprs: row}}}, nil } values, ok := n.Rows.Select.(*parser.ValuesClause) if !ok { return n.Rows.Select, nil } ret := values for tIdx, tuple := range values.Tuples { tupleCopied := false for eIdx, val := range tuple.Exprs { switch val.(type) { case parser.DefaultVal: if !tupleCopied { if ret == values { ret = &parser.ValuesClause{Tuples: append([]*parser.Tuple(nil), values.Tuples...)} } ret.Tuples[tIdx] = &parser.Tuple{Exprs: append([]parser.Expr(nil), tuple.Exprs...)} tupleCopied = true } if defaultExprs == nil || eIdx >= len(defaultExprs) { // The case where eIdx is too large for defaultExprs will be // transformed into an error by the check on the number of // columns in Insert(). ret.Tuples[tIdx].Exprs[eIdx] = parser.DNull } else { ret.Tuples[tIdx].Exprs[eIdx] = defaultExprs[eIdx] } } } } return ret, nil }
// Insert inserts rows into the database. // Privileges: INSERT on table. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". // Notes: postgres requires INSERT. No "on duplicate key update" option. // mysql requires INSERT. Also requires UPDATE on "ON DUPLICATE KEY UPDATE". func (p *planner) Insert( n *parser.Insert, desiredTypes []parser.Type, autoCommit bool, ) (planNode, error) { tn, err := p.getAliasedTableName(n.Table) if err != nil { return nil, err } en, err := p.makeEditNode(tn, autoCommit, privilege.INSERT) if err != nil { return nil, err } if n.OnConflict != nil { if !n.OnConflict.DoNothing { if err := p.checkPrivilege(en.tableDesc, privilege.UPDATE); err != nil { return nil, err } } // TODO(dan): Support RETURNING in UPSERTs. if n.Returning != nil { return nil, fmt.Errorf("RETURNING is not supported with UPSERT") } } var cols []sqlbase.ColumnDescriptor // Determine which columns we're inserting into. if n.DefaultValues() { cols = en.tableDesc.Columns } else { var err error if cols, err = p.processColumns(en.tableDesc, n.Columns); err != nil { return nil, err } } // Number of columns expecting an input. This doesn't include the // columns receiving a default value. numInputColumns := len(cols) colIDSet := make(map[sqlbase.ColumnID]struct{}, len(cols)) for _, col := range cols { colIDSet[col.ID] = struct{}{} } // Add the column if it has a DEFAULT expression. addIfDefault := func(col sqlbase.ColumnDescriptor) { if col.DefaultExpr != nil { if _, ok := colIDSet[col.ID]; !ok { colIDSet[col.ID] = struct{}{} cols = append(cols, col) } } } // Add any column that has a DEFAULT expression. for _, col := range en.tableDesc.Columns { addIfDefault(col) } // Also add any column in a mutation that is WRITE_ONLY and has // a DEFAULT expression. for _, m := range en.tableDesc.Mutations { if m.State != sqlbase.DescriptorMutation_WRITE_ONLY { continue } if col := m.GetColumn(); col != nil { addIfDefault(*col) } } defaultExprs, err := makeDefaultExprs(cols, &p.parser, &p.evalCtx) if err != nil { return nil, err } // Replace any DEFAULT markers with the corresponding default expressions. insertRows, err := p.fillDefaults(defaultExprs, cols, n) if err != nil { return nil, err } // Analyze the expressions for column information and typing. desiredTypesFromSelect := make([]parser.Type, len(cols)) for i, col := range cols { desiredTypesFromSelect[i] = col.Type.ToDatumType() } // Create the plan for the data source. // This performs type checking on source expressions, collecting // types for placeholders in the process. rows, err := p.newPlan(insertRows, desiredTypesFromSelect, false) if err != nil { return nil, err } if expressions := len(rows.Columns()); expressions > numInputColumns { return nil, fmt.Errorf("INSERT error: table %s has %d columns but %d values were supplied", n.Table, numInputColumns, expressions) } fkTables := tablesNeededForFKs(*en.tableDesc, CheckInserts) if err := p.fillFKTableMap(fkTables); err != nil { return nil, err } ri, err := makeRowInserter(p.txn, en.tableDesc, fkTables, cols, checkFKs) if err != nil { return nil, err } var tw tableWriter if n.OnConflict == nil { tw = &tableInserter{ri: ri, autoCommit: autoCommit} } else { updateExprs, conflictIndex, err := upsertExprsAndIndex(en.tableDesc, *n.OnConflict, ri.insertCols) if err != nil { return nil, err } if n.OnConflict.DoNothing { // TODO(dan): Postgres allows ON CONFLICT DO NOTHING without specifying a // conflict index, which means do nothing on any conflict. Support this if // someone needs it. tw = &tableUpserter{ri: ri, conflictIndex: *conflictIndex} } else { names, err := p.namesForExprs(updateExprs) if err != nil { return nil, err } // Also include columns that are inactive because they should be // updated. updateCols := make([]sqlbase.ColumnDescriptor, len(names)) for i, n := range names { c, err := n.NormalizeUnqualifiedColumnItem() if err != nil { return nil, err } status, idx, err := en.tableDesc.FindColumnByName(c.ColumnName) if err != nil { return nil, err } if status == sqlbase.DescriptorActive { updateCols[i] = en.tableDesc.Columns[idx] } else { updateCols[i] = *en.tableDesc.Mutations[idx].GetColumn() } } helper, err := p.makeUpsertHelper(tn, en.tableDesc, ri.insertCols, updateCols, updateExprs, conflictIndex) if err != nil { return nil, err } fkTables := tablesNeededForFKs(*en.tableDesc, CheckUpdates) if err := p.fillFKTableMap(fkTables); err != nil { return nil, err } tw = &tableUpserter{ri: ri, fkTables: fkTables, updateCols: updateCols, conflictIndex: *conflictIndex, evaler: helper} } } in := &insertNode{ n: n, editNodeBase: en, defaultExprs: defaultExprs, insertCols: ri.insertCols, insertColIDtoRowIndex: ri.insertColIDtoRowIndex, tw: tw, } if err := in.checkHelper.init(p, tn, en.tableDesc); err != nil { return nil, err } if err := in.run.initEditNode(&in.editNodeBase, rows, n.Returning, desiredTypes); err != nil { return nil, err } return in, nil }