Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Info schema enhancments #91

Merged
merged 2 commits into from
Jun 18, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions GLOCKFILE
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
github.com/araddon/dateparse 2f41da3eb28d713ca2f45682fae66173fad5e85b
github.com/araddon/gou c4d51044125da629d6f2aa594f25b45c451a7d2a
github.com/bmizerany/assert e17e99893cb6509f428e1728281c2ad60a6b31e3
github.com/araddon/dateparse a19b713c2e31cec89903deb95b4d053e9e7b4db5
github.com/araddon/gou 50a94aa4a3fb69e8fbde05df290fcb49fa685e07
github.com/bmizerany/assert b7ed37b82869576c289d7d97fb2bbd8b64a0cb28
github.com/dataux/dataux 06be63898155e3a23d5794244545e63428943015
github.com/dchest/siphash 6d8617816bb5d8268011ffbfb8720f17ce9af63c
github.com/go-sql-driver/mysql 7ebe0a500653eeb1859664bed5e48dec1e164e73
github.com/gogo/protobuf 4f262e4b0f3a6cea646e15798109335551e21756
github.com/golang/protobuf f0a097ddac24fb00e07d2ac17f8671423f3ea47c
github.com/google/btree f06e229e679911bb31a04e07ac891115822e37c3
github.com/hashicorp/go-immutable-radix 8e8ed81f8f0bf1bdd829593fdd5c29922c1ea990
github.com/go-sql-driver/mysql 3654d25ec346ee8ce71a68431025458d52a38ac0
github.com/gogo/protobuf 2752d97bbd91927dd1c43296dbf8700e50e2708c
github.com/golang/protobuf 0c1f6d65b5a189c2250d10e71a5506f06f9fa0a0
github.com/google/btree 7d79101e329e5a3adf994758c578dab82b90c017
github.com/hashicorp/go-immutable-radix afc5a0dbb18abdf82c277a7bc01533e81fa1d6b8
github.com/hashicorp/go-memdb 98f52f52d7a476958fa9da671354d270c50661a7
github.com/hashicorp/golang-lru a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4
github.com/kr/pretty add1dbc86daf0f983cd4a48ceb39deb95c729b67
github.com/kr/text bb797dc4fb8320488f47bf11de07a733d7233e1f
github.com/kr/text 7cafcd837844e784b526369c9bce262804aebc60
github.com/leekchan/timeutil 28917288c48df3d2c1cfe468c273e0b2adda0aa5
github.com/lytics/datemath 988020f3ad34814005ab10b6c7863e31672b5f63
github.com/mb0/glob 1eb79d2de6c448664e7272f8b9fe1938239e3aaa
github.com/pborman/uuid c55201b036063326c5b1b89ccfe45a184973d073
github.com/surge/sqlparser 6b860f881ddbb9373d7173bdfa1f052ec3e6b215
github.com/zhenjl/sqlparser 6b860f881ddbb9373d7173bdfa1f052ec3e6b215
golang.org/x/net fb93926129b8ec0056f2f458b1f519654814edf0
golang.org/x/net 1961d9def2b2d7a28d7958926d2457d05a178ecd
82 changes: 76 additions & 6 deletions datasource/schemadb.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ var (
_ schema.ConnScanner = (*SchemaSource)(nil)

// normal tables
defaultSchemaTables = []string{"tables", "databases", "columns", "global_variables", "session_variables"}
DialectWriterCols = []string{"mysql"}
DialectWriters = []schema.DialectWriter{&mysqlWriter{}}
defaultSchemaTables = []string{"tables", "databases", "columns", "global_variables", "session_variables",
"functions", "procedures", "engines", "status", "indexes"}
DialectWriterCols = []string{"mysql"}
DialectWriters = []schema.DialectWriter{&mysqlWriter{}}
)

type (
Expand Down Expand Up @@ -68,15 +69,22 @@ func (m *SchemaDb) Close() error { return nil }
func (m *SchemaDb) Tables() []string { return m.tbls }
func (m *SchemaDb) Table(table string) (*schema.Table, error) {

//u.Debugf("Table(%q)", table)
u.Debugf("Table(%q)", table)
switch table {
case "tables":
return m.tableForTables()
case "databases":
return m.tableForDatabases()
case "session_variables", "global_variables":
return m.tableForVariables(table)
case "procedures", "functions":
return m.tableForProcedures(table)
case "engines":
return m.tableForEngines()
case "indexes":

default:
u.Debugf("Table(%q)", table)
return m.tableForTable(table)
}
return nil, schema.ErrNotFound
Expand All @@ -85,14 +93,15 @@ func (m *SchemaDb) Table(table string) (*schema.Table, error) {
// Create a SchemaSource specific to schema object (table, database)
func (m *SchemaDb) Open(schemaObjectName string) (schema.Conn, error) {

//u.Debugf("SchemaDb.Open(%q)", schemaObjectName)
//u.WarnT(8)
u.Debugf("SchemaDb.Open(%q)", schemaObjectName)
tbl, err := m.Table(schemaObjectName)
if err == nil && tbl != nil {

switch schemaObjectName {
case "session_variables", "global_variables":
return &SchemaSource{db: m, tbl: tbl, session: true}, nil
case "engines", "procedures", "functions":
return &SchemaSource{db: m, tbl: tbl, rows: nil}, nil
default:
return &SchemaSource{db: m, tbl: tbl, rows: tbl.AsRows()}, nil
}
Expand Down Expand Up @@ -184,6 +193,67 @@ func (m *SchemaDb) tableForTable(table string) (*schema.Table, error) {
return t, nil
}

func (m *SchemaDb) tableForProcedures(table string) (*schema.Table, error) {

//table := "procedures" // procedures, functions

ss := m.is.SchemaSources["schema"]
tbl, hasTable := m.tableMap[table]

if hasTable {
u.Infof("found existing table %q", table)
return tbl, nil
}

u.Debugf("s:%p infoschema:%p creating schema table for %q", m.s, m.is, table)

// SELECT Db, Name, Type, Definer, Modified, Created, Security_type, Comment,
// character_set_client, `collation_connection`, `Database Collation` from `context`.`procedures`;")

t := schema.NewTable(table, ss)
t.AddField(schema.NewFieldBase("Db", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Name", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Type", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Definer", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Modified", value.TimeType, 8, "datetime"))
t.AddField(schema.NewFieldBase("Created", value.TimeType, 8, "datetime"))
t.AddField(schema.NewFieldBase("Security_type", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Comment", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("character_set_client", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("collation_connection", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Database Collation", value.StringType, 64, "string"))
t.SetColumns(schema.ProdedureFullCols)
ss.AddTable(t)
m.tableMap[table] = t
return t, nil
}

func (m *SchemaDb) tableForEngines() (*schema.Table, error) {

table := "engines"

ss := m.is.SchemaSources["schema"]
tbl, hasTable := m.tableMap[table]
//u.Debugf("s:%p infoschema:%p creating schema table for %q", m.s, m.is, table)
if hasTable {
//u.Infof("found existing table %q", table)
return tbl, nil
}
// Engine, Support, Comment, Transactions, XA, Savepoints

t := schema.NewTable(table, ss)
t.AddField(schema.NewFieldBase("Engine", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Support", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Comment", value.StringType, 255, "string"))
t.AddField(schema.NewFieldBase("Transactions", value.BoolType, 1, "tinyint"))
t.AddField(schema.NewFieldBase("XA", value.StringType, 64, "string"))
t.AddField(schema.NewFieldBase("Savepoints", value.BoolType, 1, "tinyint"))
t.SetColumns(schema.EngineFullCols)
ss.AddTable(t)
m.tableMap[table] = t
return t, nil
}

func (m *SchemaDb) tableForVariables(table string) (*schema.Table, error) {
// This table doesn't belong in schema
ss := m.is.SchemaSources["schema"]
Expand Down
2 changes: 1 addition & 1 deletion exec/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func BuildSqlJobPlanned(planner plan.Planner, executor Executor, ctx *plan.Conte
//u.Debugf("finished exec task plan: %#v", execRoot)

if err != nil {
u.Errorf("error on plan? %v", err)
//u.Errorf("error on plan? %v", err)
return nil, err
}
if execRoot == nil {
Expand Down
2 changes: 1 addition & 1 deletion exec/projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func (m *Projection) projectionEvaluator(isFinal bool) MessageHandler {
} else {
v, ok := vm.Eval(rdr, col.Expr)
if !ok {
u.Warnf("failed eval key=%v val=%#v expr:%s mt:%#v", col.Key(), v, col.Expr, mt)
u.Warnf("failed eval key=%q val=%#v expr:%q mt:%#v", col.Key(), v, col.Expr, mt)
// for k, v := range ctx.Session.Row() {
// u.Infof("%p session? %s: %v", ctx.Session, k, v.Value())
// }
Expand Down
42 changes: 38 additions & 4 deletions lex/dialect_sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var SqlSelect = []*Clause{
{Token: TokenGroupBy, Lexer: LexColumns, Optional: true, Name: "sqlSelect.groupby"},
{Token: TokenHaving, Lexer: LexConditionalClause, Optional: true, Name: "sqlSelect.having"},
{Token: TokenOrderBy, Lexer: LexOrderByColumn, Optional: true, Name: "sqlSelect.orderby"},
{Token: TokenLimit, Lexer: LexNumber, Optional: true},
{Token: TokenLimit, Lexer: LexLimit, Optional: true},
{Token: TokenOffset, Lexer: LexNumber, Optional: true},
{Token: TokenWith, Lexer: LexJsonOrKeyValue, Optional: true},
{Token: TokenAlias, Lexer: LexIdentifier, Optional: true},
Expand Down Expand Up @@ -48,7 +48,8 @@ var fromSource = []*Clause{
{Token: TokenHaving, Lexer: LexConditionalClause, Optional: true},
{Token: TokenGroupBy, Lexer: LexColumns, Optional: true},
{Token: TokenOrderBy, Lexer: LexOrderByColumn, Optional: true},
{Token: TokenLimit, Lexer: LexNumber, Optional: true},
{Token: TokenLimit, Lexer: LexLimit, Optional: true},
{Token: TokenOffset, Lexer: LexNumber, Optional: true},
{Token: TokenAs, Lexer: LexIdentifier, Optional: true},
{Token: TokenOn, Lexer: LexConditionalClause, Optional: true},
}
Expand All @@ -61,7 +62,8 @@ var moreSources = []*Clause{
{Token: TokenHaving, Lexer: LexConditionalClause, Optional: true, Name: "moreSources.Having"},
{Token: TokenGroupBy, Lexer: LexColumns, Optional: true, Name: "moreSources.GroupBy"},
{Token: TokenOrderBy, Lexer: LexOrderByColumn, Optional: true, Name: "moreSources.OrderBy"},
{Token: TokenLimit, Lexer: LexNumber, Optional: true, Name: "moreSources.Limit"},
{Token: TokenLimit, Lexer: LexLimit, Optional: true, Name: "moreSources.Limit"},
{Token: TokenOffset, Lexer: LexNumber, Optional: true, Name: "moreSources.Offset"},
{Token: TokenAs, Lexer: LexIdentifier, Optional: true, Name: "moreSources.As"},
{Token: TokenOn, Lexer: LexConditionalClause, Optional: true, Name: "moreSources.On"},
}
Expand Down Expand Up @@ -264,7 +266,9 @@ func LexShowClause(l *Lexer) StateFn {
l.ConsumeWord(keyWord)
l.Emit(TokenTables)
return LexShowClause
case "columns", "global", "session", "variables":
case "columns", "global", "session", "variables", "status",
"engine", "engines", "procedure", "indexes", "index", "keys",
"function", "functions":
// TODO: these should not be identities but tokens?
l.ConsumeWord(keyWord)
l.Emit(TokenIdentity)
Expand All @@ -291,3 +295,33 @@ func LexShowClause(l *Lexer) StateFn {
}
return LexIdentifier
}

// LexLimit clause
// LIMIT 1000 OFFSET 100
// LIMIT 0, 1000
// LIMIT 1000
func LexLimit(l *Lexer) StateFn {

l.SkipWhiteSpaces()
keyWord := strings.ToLower(l.PeekWord())
//u.Debugf("LexLimit r= '%v'", string(keyWord))

switch keyWord {
case "limit":
l.ConsumeWord(keyWord)
l.Emit(TokenLimit)
return LexLimit
case "offset":
return nil
case "", ";":
return nil
case ",":
l.ConsumeWord(keyWord)
l.Emit(TokenComma)
return LexNumber
default:
l.Push("LexLimit", LexLimit)
return LexNumber
}
return nil
}
4 changes: 3 additions & 1 deletion plan/projection.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ func projectionForSourcePlan(plan *Source) error {
if col.InFinalProjection() {
//u.Infof("col add %v for %s", schemaCol.Type.String(), col)
plan.Proj.AddColumn(col, schemaCol.Type)
} else {
//u.Infof("not in final? %#v", col)
}
} else {
plan.Proj.AddColumn(col, schemaCol.Type)
Expand All @@ -173,7 +175,7 @@ func projectionForSourcePlan(plan *Source) error {
//u.Warnf("count(*) as=%v", col.As)
plan.Proj.AddColumn(col, value.IntType)
} else {
//u.Errorf("schema col not found: vals=%#v", col)
//u.Errorf("schema col not found: SourceField=%q vals=%#v", col.SourceField, col)
}

}
Expand Down
55 changes: 52 additions & 3 deletions plan/sql_rewrite.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func RewriteShowAsSelect(stmt *rel.SqlShow, ctx *Context) (*rel.SqlSelect, error
}

showType := strings.ToLower(stmt.ShowType)
//u.Debugf("showType=%q create=%q from=%q rewrite: %s", showType, stmt.CreateWhat, stmt.From, raw)
u.Debugf("showType=%q create=%q from=%q rewrite: %s", showType, stmt.CreateWhat, stmt.From, raw)
sqlStatement := ""
from := "tables"
if stmt.Db != "" {
Expand Down Expand Up @@ -108,7 +108,7 @@ func RewriteShowAsSelect(stmt *rel.SqlShow, ctx *Context) (*rel.SqlSelect, error
| 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)
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`.`indexes`;")

case "variables":
// SHOW [GLOBAL | SESSION] VARIABLES [like_or_where]
Expand All @@ -128,8 +128,57 @@ func RewriteShowAsSelect(stmt *rel.SqlShow, ctx *Context) (*rel.SqlSelect, error
+---------------+----------+
*/

case "status":
// Status is a subset of just some variables
// http://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html

// SHOW [GLOBAL | SESSION | SLAVE ] STATUS [like_or_where]
scope := stmt.Scope
switch scope {
case "session", "":
scope = "session"
}
sqlStatement = fmt.Sprintf("select Variable_name, Value from `context`.`%s_variables`;", scope)
/*
mysql> show global status;
+--------------------------------+-----------------+
| Variable_name | Value
+--------------------------------+------------------
| Aborted_clients | 0
| Aborted_connects | 0
| Binlog_snapshot_file |
| Binlog_snapshot_position | 0
*/
case "engines":
sqlStatement = fmt.Sprintf("select Engine, Support, Comment, Transactions, XA, Savepoints from `context`.`engines`;")
/*
show engines;
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
| InnoDB | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| CSV | YES | CSV storage engine | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
*/
case "procedure", "function":
/*
show procuedure status;
show function status;

| Db | Name | Type | Definer | Modified | Created | Security_type | Comment| character_set_client | collation_connection | Database Collation |
*/
sqlStatement = fmt.Sprintf("SELECT Db, Name, Type, Definer, Modified, Created, Security_type, Comment, character_set_client, `collation_connection`, `Database Collation` from `context`.`%ss`;", showType)

default:
u.Warnf("unhandled %s", raw)
u.Warnf("unhandled sql rewrite statement %s", raw)
return nil, fmt.Errorf("Unrecognized: %s", raw)
}
sel, err := rel.ParseSqlSelectResolver(sqlStatement, ctx.Funcs)
Expand Down
Loading