func convertIdentityToValue(n expr.Node) { switch nt := n.(type) { case *expr.BinaryNode: switch rhn := nt.Args[1].(type) { case *expr.IdentityNode: rh2 := expr.NewStringNode(rhn.Text) nt.Args[1] = rh2 } } }
// RewriteShowAsSelect Rewrite Schema SHOW Statements AS SELECT statements // so we only need a Select Planner, not separate planner for show statements func RewriteShowAsSelect(stmt *rel.SqlShow, ctx *Context) (*rel.SqlSelect, error) { raw := strings.ToLower(stmt.Raw) if ctx.Funcs == nil { ctx.Funcs = fr } showType := strings.ToLower(stmt.ShowType) //u.Debugf("showType=%q create=%q from=%q rewrite: %s", showType, stmt.CreateWhat, stmt.From, raw) sqlStatement := "" from := "tables" if stmt.Db != "" { from = fmt.Sprintf("%s.%s", stmt.Db, expr.IdentityMaybeQuote('`', from)) } switch showType { case "tables": if stmt.Full { // SHOW FULL TABLES; = select name, table_type from tables; // TODO: note the stupid "_in_mysql", assuming i don't have to implement /* mysql> show full tables; +---------------------------+------------+ | Tables_in_mysql | Table_type | +---------------------------+------------+ | columns_priv | BASE TABLE | */ sqlStatement = fmt.Sprintf("select Table, Table_Type from %s;", from) } else { // show tables; sqlStatement = fmt.Sprintf("select Table from %s;", from) } case "create": // SHOW CREATE {TABLE | DATABASE | EVENT | VIEW } switch strings.ToLower(stmt.CreateWhat) { case "table": sqlStatement = fmt.Sprintf("select Table , mysql_create as `Create Table` FROM `schema`.`%s`", from) vn := expr.NewStringNode(stmt.Identity) lh := expr.NewIdentityNodeVal("Table") stmt.Where = expr.NewBinaryNode(lex.Token{T: lex.TokenEqual, V: "="}, lh, vn) default: return nil, fmt.Errorf("Unsupported show create %q", stmt.CreateWhat) } case "databases": // SHOW databases; -> select Database from databases; sqlStatement = "select Database from databases;" case "columns": if stmt.Full { /* mysql> show full columns from user; +------------------------+-----------------------------------+-----------------+------+-----+-----------------------+-------+---------------------------------+---------+ | Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment | */ sqlStatement = fmt.Sprintf("select Field, typewriter(Type) AS Type, Collation, `Null`, Key, Default, Extra, Privileges, Comment from `schema`.`%s`;", stmt.Identity) } else { /* mysql> show columns from user; +------------------------+-----------------------------------+------+-----+-----------------------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------------+-----------------------------------+------+-----+-----------------------+-------+ */ sqlStatement = fmt.Sprintf("select Field, typewriter(Type) AS Type, `Null`, Key, Default, Extra from `schema`.`%s`;", stmt.Identity) } case "keys", "indexes", "index": /* mysql> show keys from user; +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ | user | 0 | PRIMARY | 1 | Host | A | NULL | NULL | NULL | | BTREE | | | | user | 0 | PRIMARY | 2 | User | A | 7 | NULL | NULL | | BTREE | | | +-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+ */ sqlStatement = fmt.Sprintf("select Table, Non_unique, Key_name, Seq_in_index, Column_name, Collation, Cardinality, Sub_part, Packed, `Null`, Index_type, Index_comment from `schema`.`%s`;", stmt.Identity) case "variables": // SHOW [GLOBAL | SESSION] VARIABLES [like_or_where] scope := stmt.Scope if scope == "" { scope = "session" } else { } sqlStatement = fmt.Sprintf("select Variable_name, Value from `context`.`%s_variables`;", scope) /* mysql> show variables LIKE 'version'; +---------------+----------+ | Variable_name | Value | +---------------+----------+ | version | 5.7.10-3 | +---------------+----------+ */ default: u.Warnf("unhandled %s", raw) return nil, fmt.Errorf("Unrecognized: %s", raw) } sel, err := rel.ParseSqlSelectResolver(sqlStatement, ctx.Funcs) if err != nil { return nil, err } sel.SetSystemQry() if stmt.Like != nil { // We are going to ReWrite LIKE clause to WHERE clause sel.Where = &rel.SqlWhere{Expr: stmt.Like} bn, ok := stmt.Like.(*expr.BinaryNode) if ok { rhn, ok := bn.Args[1].(*expr.StringNode) // See if the Like Clause has wildcard matching, if so // our internal vm uses * not % if ok && rhn.Text == "%" { rhn.Text = strings.Replace(rhn.Text, "%", "*", -1) } } } else if stmt.Where != nil { //u.Debugf("add where: %s", stmt.Where) sel.Where = &rel.SqlWhere{Expr: stmt.Where} } if ctx.Schema == nil { u.Warnf("missing schema for %s", stmt.Raw) return nil, fmt.Errorf("Must have schema") } ctx.Schema = ctx.Schema.InfoSchema if ctx.Schema == nil { //u.Warnf("WAT? Still nil info schema?") if ctx.Schema.InfoSchema == nil { u.Warnf("WAT? info schema not self referencing?") } } u.Debugf("SHOW rewrite: %q ==> %s", stmt.Raw, sel.String()) return sel, nil }