// processAliasedTable produces a builder subtree for the given AliasedTableExpr. // If the expression is a subquery, then the the route built for it will contain // the entire subquery tree in the from clause, as if it was a table. // The symtab entry for the query will be a tabsym where the columns // will be built from the select expressions of the subquery. // Since the table aliases only contain vindex columns, we'll follow // the same rule: only columns from the subquery that are identified as // vindex columns will be added to the tabsym. // A symtab symbol can only point to a route. This means that we canoot // support complex joins in subqueries yet. func processAliasedTable(tableExpr *sqlparser.AliasedTableExpr, vschema VSchema) (builder, error) { switch expr := tableExpr.Expr.(type) { case *sqlparser.TableName: eroute, table, err := getTablePlan(expr, vschema) if err != nil { return nil, err } alias := sqlparser.TableIdent(sqlparser.String(expr)) astName := expr.Name if tableExpr.As != "" { alias = tableExpr.As astName = alias } return newRoute( sqlparser.TableExprs([]sqlparser.TableExpr{tableExpr}), eroute, table, vschema, alias, astName, ), nil case *sqlparser.Subquery: sel, ok := expr.Select.(*sqlparser.Select) if !ok { return nil, errors.New("unsupported: union operator in subqueries") } subplan, err := processSelect(sel, vschema, nil) if err != nil { return nil, err } subroute, ok := subplan.(*route) if !ok { return nil, errors.New("unsupported: complex join in subqueries") } table := &vindexes.Table{ Keyspace: subroute.ERoute.Keyspace, } for _, colsyms := range subroute.Colsyms { if colsyms.Vindex == nil { continue } table.ColumnVindexes = append(table.ColumnVindexes, &vindexes.ColumnVindex{ Column: cistring.CIString(colsyms.Alias), Vindex: colsyms.Vindex, }) } rtb := newRoute( sqlparser.TableExprs([]sqlparser.TableExpr{tableExpr}), subroute.ERoute, table, vschema, tableExpr.As, tableExpr.As, ) subroute.Redirect = rtb return rtb, nil } panic("unreachable") }
// FindVindex returns the vindex if one was found for the column. func (t *tabsym) FindVindex(name sqlparser.ColIdent) vindexes.Vindex { for _, colVindex := range t.ColumnVindexes { if colVindex.Column.Equal(cistring.CIString(name)) { return colVindex.Vindex } } return nil }
// isIndexChanging returns true if any of the update // expressions modify a vindex column. func isIndexChanging(setClauses sqlparser.UpdateExprs, colVindexes []*vindexes.ColumnVindex) bool { for _, assignment := range setClauses { for _, vcol := range colVindexes { if vcol.Column.Equal(cistring.CIString(assignment.Name)) { return true } } } return false }
func findOrInsertPos(ins *sqlparser.Insert, col cistring.CIString, rowNum int) (row sqlparser.ValTuple, pos int) { pos = -1 for i, column := range ins.Columns { if col.Equal(cistring.CIString(column)) { pos = i break } } if pos == -1 { pos = len(ins.Columns) ins.Columns = append(ins.Columns, sqlparser.ColIdent(col)) } if pos == -1 || pos >= len(ins.Rows.(sqlparser.Values)[rowNum].(sqlparser.ValTuple)) { ins.Rows.(sqlparser.Values)[rowNum] = append(ins.Rows.(sqlparser.Values)[rowNum].(sqlparser.ValTuple), &sqlparser.NullVal{}) } return ins.Rows.(sqlparser.Values)[rowNum].(sqlparser.ValTuple), pos }
// EqualString performs a case-insensitive compare with str. func (node ColIdent) EqualString(str string) bool { return cistring.CIString(node).EqualString(str) }
// Equal performs a case-insensitive compare. func (node ColIdent) Equal(in ColIdent) bool { return cistring.CIString(node).Equal(cistring.CIString(in)) }
// Lowered returns a lower-cased column name. // This function should generally be used only for optimizing // comparisons. func (node ColIdent) Lowered() string { return cistring.CIString(node).Lowered() }
func (node ColIdent) String() string { return cistring.CIString(node).String() }
// Original returns the case-preserved column name. func (node ColIdent) Original() string { return cistring.CIString(node).Original() }