func NormalizeTree(tree *sqlparser.Node) (normalized string, bindVars map[string]interface{}, err error) { defer handleError(&err) bindVars = make(map[string]interface{}) counter := 0 NormalizeNode(tree, bindVars, &counter) return tree.String(), bindVars, nil }
//This builds UpdateResponse from the parsed tree, also handles a multi-row update. func createUpdateResponse(eventTree *parser.Node, dmlType string, blpPos BinlogPosition) (response *UpdateResponse) { if eventTree.Len() < 3 { panic(NewBinlogParseError(EVENT_ERROR, fmt.Sprintf("Invalid comment structure, len of tree %v", eventTree.Len()))) } tableName := string(eventTree.At(0).Value) pkColNamesNode := eventTree.At(1) pkColNames := make([]string, 0, pkColNamesNode.Len()) for _, pkCol := range pkColNamesNode.Sub { if pkCol.Type != parser.ID { panic(NewBinlogParseError(EVENT_ERROR, "Error in the stream comment, illegal type for column name.")) } pkColNames = append(pkColNames, string(pkCol.Value)) } pkColLen := pkColNamesNode.Len() response = new(UpdateResponse) response.BinlogPosition = blpPos response.SqlType = dmlType response.TableName = tableName response.PkColNames = pkColNames response.PkValues = make([][]interface{}, 0, len(eventTree.Sub[2:])) rowPk := make([]interface{}, pkColLen) for _, node := range eventTree.Sub[2:] { rowPk = rowPk[:0] if node.Len() != pkColLen { panic(NewBinlogParseError(EVENT_ERROR, "Error in the stream comment, length of pk values doesn't match column names.")) } rowPk = encodePkValues(node.Sub) response.PkValues = append(response.PkValues, rowPk) } return response }
func NormalizeNode(node *sqlparser.Node, bindVars map[string]interface{}, counter *int) { for i := 0; i < node.Len(); i++ { switch node.At(i).Type { case sqlparser.STRING: *counter++ bindVars[fmt.Sprintf("v%d", *counter)] = string(node.At(i).Value) node.Set(i, newArgumentNode(counter)) case sqlparser.NUMBER: *counter++ varname := fmt.Sprintf("v%d", *counter) valstr := string(node.At(i).Value) if ival, err := strconv.ParseInt(valstr, 0, 64); err == nil { bindVars[varname] = ival } else if uval, err := strconv.ParseUint(valstr, 0, 64); err == nil { bindVars[varname] = uval } else if fval, err := strconv.ParseFloat(valstr, 64); err == nil { bindVars[varname] = fval } else { panic(sqlparser.NewParserError("%v", err)) } node.Set(i, newArgumentNode(counter)) default: for i := 0; i < node.Len(); i++ { NormalizeNode(node.At(i), bindVars, counter) } } } }