func getInsertPKValues(pkColumnNumbers []int, rowList *Node, tableInfo *schema.Table) (pkValues []interface{}) { pkValues = make([]interface{}, len(pkColumnNumbers)) for index, columnNumber := range pkColumnNumbers { if columnNumber == -1 { pkValues[index] = tableInfo.GetPKColumn(index).Default continue } values := make([]interface{}, rowList.Len()) for j := 0; j < rowList.Len(); j++ { if columnNumber >= rowList.At(j).At(0).Len() { // NODE_LIST->'('->NODE_LIST panic(NewParserError("Column count doesn't match value count")) } node := rowList.At(j).At(0).At(columnNumber) // NODE_LIST->'('->NODE_LIST->Value value := node.execAnalyzeValue() if value == nil { log.Warn("insert is too complex %v", node) return nil } values[j] = asInterface(value) } if len(values) == 1 { pkValues[index] = values[0] } else { pkValues[index] = values } } return pkValues }
// buildValueList builds the set of PK reference rows used to drive the next query. // It uses the PK values supplied in the original query and bind variables. // The generated reference rows are validated for type match against the PK of the table. func buildValueList(tableInfo *schema.Table, pkValues []interface{}, bindVars map[string]interface{}) [][]sqltypes.Value { length := -1 for _, pkValue := range pkValues { if list, ok := pkValue.([]interface{}); ok { if length == -1 { if length = len(list); length == 0 { panic(NewTabletError(FAIL, "empty list for values %v", pkValues)) } } else if length != len(list) { panic(NewTabletError(FAIL, "mismatched lengths for values %v", pkValues)) } } } if length == -1 { length = 1 } valueList := make([][]sqltypes.Value, length) for i := 0; i < length; i++ { valueList[i] = make([]sqltypes.Value, len(pkValues)) for j, pkValue := range pkValues { if list, ok := pkValue.([]interface{}); ok { valueList[i][j] = resolveValue(tableInfo.GetPKColumn(j), list[i], bindVars) } else { valueList[i][j] = resolveValue(tableInfo.GetPKColumn(j), pkValue, bindVars) } } } return valueList }
func applyFilterWithPKDefaults(tableInfo *schema.Table, columnNumbers []int, input []sqltypes.Value) (output []sqltypes.Value) { output = make([]sqltypes.Value, len(columnNumbers)) for colIndex, colPointer := range columnNumbers { if colPointer >= 0 { output[colIndex] = input[colPointer] } else { output[colIndex] = tableInfo.GetPKColumn(colIndex).Default } } return output }
// buildINValueList builds the set of PK reference rows used to drive the next query // using an IN clause. This works only for tables with no composite PK columns. // The generated reference rows are validated for type match against the PK of the table. func buildINValueList(tableInfo *schema.Table, pkValues []interface{}, bindVars map[string]interface{}) [][]sqltypes.Value { if len(tableInfo.PKColumns) != 1 { panic("unexpected") } valueList := make([][]sqltypes.Value, len(pkValues)) for i, pkValue := range pkValues { valueList[i] = make([]sqltypes.Value, 1) valueList[i][0] = resolveValue(tableInfo.GetPKColumn(0), pkValue, bindVars) } return valueList }
func testTables() *schema.Table { t := new(schema.Table) t.Name = "user" t.AddColumn("id", "int", sqltypes.NULL, "", true) t.AddColumn("name", "string", sqltypes.NULL, "", false) index := t.AddIndex("PRIMARY") index.AddColumn("id", 0) t.PKColumns = []int{0} return t }
// buildSecondaryList is used for handling ON DUPLICATE DMLs, or those that change the PK. func buildSecondaryList(tableInfo *schema.Table, pkList [][]sqltypes.Value, secondaryList []interface{}, bindVars map[string]interface{}) [][]sqltypes.Value { if secondaryList == nil { return nil } valueList := make([][]sqltypes.Value, len(pkList)) for i, row := range pkList { valueList[i] = make([]sqltypes.Value, len(row)) for j, cell := range row { if secondaryList[j] == nil { valueList[i][j] = cell } else { valueList[i][j] = resolveValue(tableInfo.GetPKColumn(j), secondaryList[j], bindVars) } } } return valueList }
func (node *Node) execAnalyzeSelectExpressions(table *schema.Table) (selects []int) { selects = make([]int, 0, node.Len()) for i := 0; i < node.Len(); i++ { if name := node.At(i).execAnalyzeSelectExpression(); name != "" { if name == "*" { for colIndex := range table.Columns { selects = append(selects, colIndex) } } else if colIndex := table.FindColumn(name); colIndex != -1 { selects = append(selects, colIndex) } else { panic(NewParserError("Column %s not found in table %s", name, table.Name)) } } else { // Complex expression return nil } } return selects }