use a more predictable scheme of obtaining field info for selects

This commit is contained in:
Sugu Sougoumarane 2012-12-05 15:22:24 -08:00
Родитель 8c198382d4
Коммит 4dab186aca
10 изменённых файлов: 279 добавлений и 121 удалений

Просмотреть файл

@ -99,6 +99,9 @@ type ExecPlan struct {
Reason ReasonType
TableName string
// Query to fetch field info
FieldQuery *ParsedQuery
// PLAN_PASS_*
FullQuery *ParsedQuery
@ -217,7 +220,7 @@ func (node *Node) execAnalyzeSql(getTable TableGetter) (plan *ExecPlan) {
func (node *Node) execAnalyzeSelect(getTable TableGetter) (plan *ExecPlan) {
// Default plan
plan = &ExecPlan{PlanId: PLAN_PASS_SELECT, FullQuery: node.GenerateSelectLimitQuery()}
plan = &ExecPlan{PlanId: PLAN_PASS_SELECT, FieldQuery: node.GenerateFieldQuery(), FullQuery: node.GenerateSelectLimitQuery()}
if !node.execAnalyzeSelectStructure() {
plan.Reason = REASON_SELECT
@ -908,6 +911,29 @@ func (node *Node) GenerateFullQuery() *ParsedQuery {
return NewParsedQuery(buf)
}
func (node *Node) GenerateFieldQuery() *ParsedQuery {
buf := NewTrackedBuffer()
node.generateImpossibleQuery(buf)
if len(buf.bind_locations) != 0 {
panic(NewParserError("Syntax error: Bind variables not allowed in select expressions"))
}
return NewParsedQuery(buf)
}
func (node *Node) generateImpossibleQuery(buf *TrackedBuffer) {
switch node.Type {
case UNION, UNION_ALL, MINUS, EXCEPT:
node.At(0).generateImpossibleQuery(buf)
fmt.Fprintf(buf, " %s ", node.Value)
node.At(1).generateImpossibleQuery(buf)
case SELECT:
Fprintf(buf, "select %v from %v where 1 != 1",
node.At(SELECT_EXPR_OFFSET),
node.At(SELECT_FROM_OFFSET),
)
}
}
func (node *Node) GenerateSelectLimitQuery() *ParsedQuery {
buf := NewTrackedBuffer()
if node.Type == SELECT {

Просмотреть файл

@ -37,7 +37,7 @@ func NewParsedQuery(buf *TrackedBuffer) *ParsedQuery {
type EncoderFunc func(value interface{}) ([]byte, error)
func (self *ParsedQuery) GenerateQuery(bindVariables map[string]interface{}, listVariables []sqltypes.Value) ([]byte, error) {
if bindVariables == nil || len(self.BindLocations) == 0 {
if len(self.BindLocations) == 0 {
return []byte(self.Query), nil
}
buf := bytes.NewBuffer(make([]byte, 0, len(self.Query)))

Просмотреть файл

@ -4,6 +4,7 @@ select * from a union select * from b
"PlanId": "PASS_SELECT",
"Reason": "SELECT",
"TableName": "",
"FieldQuery": "select * from a where 1 != 1 union select * from b where 1 != 1",
"FullQuery": "select * from a union select * from b",
"OuterQuery": null,
"Subquery": null,
@ -22,6 +23,7 @@ select distinct * from a
"PlanId": "PASS_SELECT",
"Reason": "SELECT",
"TableName": "",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select distinct * from a limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -40,6 +42,7 @@ select * from a group by b
"PlanId": "PASS_SELECT",
"Reason": "SELECT",
"TableName": "",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a group by b limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -58,6 +61,7 @@ select * from a having b=1
"PlanId": "PASS_SELECT",
"Reason": "SELECT",
"TableName": "",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a having b = 1 limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -76,6 +80,7 @@ select * from a limit 5
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a limit 5",
"OuterQuery": "select eid, id, name, foo from a limit 5",
"Subquery": null,
@ -99,6 +104,7 @@ select * from a,b
"PlanId": "PASS_SELECT",
"Reason": "TABLE",
"TableName": "",
"FieldQuery": "select * from a, b where 1 != 1",
"FullQuery": "select * from a, b limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -117,6 +123,7 @@ select * from a join b
"PlanId": "PASS_SELECT",
"Reason": "TABLE",
"TableName": "",
"FieldQuery": "select * from a join b where 1 != 1",
"FullQuery": "select * from a join b limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -135,6 +142,7 @@ select * from b
"PlanId": "PASS_SELECT",
"Reason": "NOCACHE",
"TableName": "b",
"FieldQuery": "select * from b where 1 != 1",
"FullQuery": "select * from b limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -153,6 +161,7 @@ select eid+1 from a
"PlanId": "PASS_SELECT",
"Reason": "SELECT_LIST",
"TableName": "a",
"FieldQuery": "select eid+1 from a where 1 != 1",
"FullQuery": "select eid+1 from a limit :_vtMaxResultSize",
"OuterQuery": null,
"Subquery": null,
@ -171,6 +180,7 @@ select eid from a
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select eid from a where 1 != 1",
"FullQuery": "select eid from a limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a limit :_vtMaxResultSize",
"Subquery": null,
@ -191,6 +201,7 @@ select * from a
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a limit :_vtMaxResultSize",
"Subquery": null,
@ -214,6 +225,7 @@ select c.eid from a as c
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select c.eid from a as c where 1 != 1",
"FullQuery": "select c.eid from a as c limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a as c limit :_vtMaxResultSize",
"Subquery": null,
@ -234,6 +246,7 @@ select (eid) from a as c
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select eid from a as c where 1 != 1",
"FullQuery": "select eid from a as c limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a as c limit :_vtMaxResultSize",
"Subquery": null,
@ -254,6 +267,7 @@ select eid from a for update
"PlanId": "PASS_SELECT",
"Reason": "FOR_UPDATE",
"TableName": "a",
"FieldQuery": "select eid from a where 1 != 1",
"FullQuery": "select eid from a limit :_vtMaxResultSize for update",
"OuterQuery": null,
"Subquery": null,
@ -272,6 +286,7 @@ select * from a where eid=1
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid = 1 limit :_vtMaxResultSize",
@ -295,6 +310,7 @@ select * from a where eid+1 = 1
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid+1 = 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid+1 = 1 limit :_vtMaxResultSize",
"Subquery": null,
@ -318,6 +334,7 @@ select * from a where eid = id
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = id limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = id limit :_vtMaxResultSize",
"Subquery": null,
@ -341,6 +358,7 @@ select * from a where eid=1 and foo='b'
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "PKINDEX",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and foo = 'b' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = 1 and foo = 'b' limit :_vtMaxResultSize",
"Subquery": null,
@ -364,6 +382,7 @@ select * from a where (eid=1)
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where (eid = 1) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where (eid = 1) limit :_vtMaxResultSize",
@ -387,6 +406,7 @@ select * from a where eid=1 and id=1
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id = 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -413,6 +433,7 @@ select * from d where name='foo'
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "d",
"FieldQuery": "select * from d where 1 != 1",
"FullQuery": "select * from d where name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select name, id from d where name = :0",
"Subquery": null,
@ -436,6 +457,7 @@ select * from a where eid=1 and id in (1, 2)
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id in (1, 2) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -465,6 +487,7 @@ select * from a where eid=1 and id in (:a, :b)
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id in (:a, :b) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -494,6 +517,7 @@ select * from a where eid=1 and id in (1)
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id in (1) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -522,6 +546,7 @@ select * from a where eid in (1) and id in (1, 2)
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid in (1) and id in (1, 2) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid in (1) and id in (1, 2) limit :_vtMaxResultSize",
"Subquery": null,
@ -545,6 +570,7 @@ select * from a where eid in (1, 2) and id in (1, 2)
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid in (1, 2) and id in (1, 2) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid in (1, 2) and id in (1, 2) limit :_vtMaxResultSize",
"Subquery": null,
@ -568,6 +594,7 @@ select * from a where (eid, id) in ((1, 1), (2, 2))
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where (eid, id) in ((1, 1), (2, 2)) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -600,6 +627,7 @@ select * from a where eid=1 and id in (:a)
"PlanId": "SELECT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id in (:a) limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": null,
@ -628,6 +656,7 @@ select * from a where eid=1 and id>1
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "PKINDEX",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id \u003e 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = 1 and id \u003e 1 limit :_vtMaxResultSize",
"Subquery": null,
@ -651,6 +680,7 @@ select * from a where eid=1 and name='foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid = 1 and name = 'foo' limit :_vtMaxResultSize",
@ -674,6 +704,7 @@ select * from a where eid=1 and name='foo' limit 10
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and name = 'foo' limit 10",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid = 1 and name = 'foo' limit 10",
@ -697,6 +728,7 @@ select * from a where foo='bar'
"PlanId":"SELECT_CACHE_RESULT",
"Reason":"NOINDEX_MATCH",
"TableName":"a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery":"select * from a where foo = 'bar' limit :_vtMaxResultSize",
"OuterQuery":"select eid, id, name, foo from a where foo = 'bar' limit :_vtMaxResultSize",
"Subquery":null,
@ -720,6 +752,7 @@ select * from a where name = 'foo' and id = 1
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where name = 'foo' and id = 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (b_name) where name = 'foo' and id = 1 limit :_vtMaxResultSize",
@ -743,6 +776,7 @@ select * from a as c where c.eid=1 and name='foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a as c where 1 != 1",
"FullQuery": "select * from a as c where c.eid = 1 and name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a as c where eid = :0 and id = :1",
"Subquery": "select eid, id from a as c use index (a_name) where c.eid = 1 and name = 'foo' limit :_vtMaxResultSize",
@ -766,6 +800,7 @@ select * from a where eid=1 and name<'foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and name \u003c 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid = 1 and name \u003c 'foo' limit :_vtMaxResultSize",
@ -789,6 +824,7 @@ select * from a where eid in (1, 2) and name='foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid in (1, 2) and name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid in (1, 2) and name = 'foo' limit :_vtMaxResultSize",
@ -812,6 +848,7 @@ select * from a where eid in (1, id) and name='foo'
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid in (1, id) and name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid in (1, id) and name = 'foo' limit :_vtMaxResultSize",
"Subquery": null,
@ -835,6 +872,7 @@ select * from a where eid between 1 and 2 and name='foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid between 1 and 2 and name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid between 1 and 2 and name = 'foo' limit :_vtMaxResultSize",
@ -858,6 +896,7 @@ select * from a where eid=1 and id=1 order by name
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "PKINDEX",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 and id = 1 order by name asc limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = 1 and id = 1 order by name asc limit :_vtMaxResultSize",
"Subquery": null,
@ -881,6 +920,7 @@ select * from a where eid=1 order by name
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where eid = 1 order by name asc limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (a_name) where eid = 1 order by name asc limit :_vtMaxResultSize",
@ -904,6 +944,7 @@ select * from a where name='foo'
"PlanId": "SELECT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": "select * from a where 1 != 1",
"FullQuery": "select * from a where name = 'foo' limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a use index (b_name) where name = 'foo' limit :_vtMaxResultSize",
@ -927,6 +968,7 @@ select * from a use index(a_name) where eid = 1
"PlanId": "SELECT_CACHE_RESULT",
"Reason": "HAS_HINTS",
"TableName": "a",
"FieldQuery": "select * from a use index (a_name) where 1 != 1",
"FullQuery": "select * from a use index (a_name) where eid = 1 limit :_vtMaxResultSize",
"OuterQuery": "select eid, id, name, foo from a use index (a_name) where eid = 1 limit :_vtMaxResultSize",
"Subquery": null,
@ -950,6 +992,7 @@ insert into a (eid, id) values (1, :a)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(eid, id) values (1, :a)",
"OuterQuery": "insert into a(eid, id) values (1, :a)",
"Subquery": null,
@ -971,6 +1014,7 @@ insert into a (id) values (1)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(id) values (1)",
"OuterQuery": "insert into a(id) values (1)",
"Subquery": null,
@ -992,6 +1036,7 @@ insert into d(id) values(1)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "d",
"FieldQuery": null,
"FullQuery": "insert into d(id) values (1)",
"OuterQuery": "insert into d(id) values (1)",
"Subquery": null,
@ -1016,6 +1061,7 @@ insert into a (eid, id) values (-1, 2)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(eid, id) values (-1, 2)",
"OuterQuery": "insert into a(eid, id) values (-1, 2)",
"Subquery": null,
@ -1037,6 +1083,7 @@ insert into a (eid, id) values (+1, 2)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(eid, id) values (1, 2)",
"OuterQuery": "insert into a(eid, id) values (1, 2)",
"Subquery": null,
@ -1058,6 +1105,7 @@ insert into a (eid, id) values (~1, 2)
"PlanId": "PASS_DML",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(eid, id) values (~1, 2)",
"OuterQuery": null,
"Subquery": null,
@ -1076,6 +1124,7 @@ insert into a (eid, id) values (1+1, 2)
"PlanId": "PASS_DML",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a(eid, id) values (1+1, 2)",
"OuterQuery": null,
"Subquery": null,
@ -1094,6 +1143,7 @@ insert into c (eid, id) values (1, 2)
"PlanId": "PASS_DML",
"Reason": "TABLE_NOINDEX",
"TableName": "c",
"FieldQuery": null,
"FullQuery": "insert into c(eid, id) values (1, 2)",
"OuterQuery": null,
"Subquery": null,
@ -1112,6 +1162,7 @@ insert into a values (1, 2)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "insert into a values (1, 2)",
"OuterQuery": "insert into a values (1, 2)",
"Subquery": null,
@ -1133,6 +1184,7 @@ insert into b (eid, id) values (1, 2) on duplicate key update name = values(a)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "insert into b(eid, id) values (1, 2) on duplicate key update name = values(a)",
"OuterQuery": "insert into b(eid, id) values (1, 2) on duplicate key update name = values(a)",
"Subquery": null,
@ -1154,6 +1206,7 @@ insert into b (eid, id) values (1, 2) on duplicate key update eid = 2
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "insert into b(eid, id) values (1, 2) on duplicate key update eid = 2",
"OuterQuery": "insert into b(eid, id) values (1, 2) on duplicate key update eid = 2",
"Subquery": null,
@ -1178,6 +1231,7 @@ insert into b (id, eid) values (1, 2) on duplicate key update eid = values(a)
"PlanId": "PASS_DML",
"Reason": "PK_CHANGE",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "insert into b(id, eid) values (1, 2) on duplicate key update eid = values(a)",
"OuterQuery": null,
"Subquery": null,
@ -1196,6 +1250,7 @@ insert into b (eid, id) select * from a
"PlanId": "INSERT_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "insert into b(eid, id) select * from a",
"OuterQuery": "insert into b(eid, id) values :_rowValues",
"Subquery": "select * from a limit :_vtMaxResultSize",
@ -1220,6 +1275,7 @@ insert into b (eid, id) values (1, 2), (3, 4)
"PlanId": "INSERT_PK",
"Reason": "DEFAULT",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "insert into b(eid, id) values (1, 2), (3, 4)",
"OuterQuery": "insert into b(eid, id) values (1, 2), (3, 4)",
"Subquery": null,
@ -1247,6 +1303,7 @@ update b set eid=1
"PlanId": "DML_SUBQUERY",
"Reason": "WHERE",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "update b set eid = 1",
"OuterQuery": "update b set eid = 1 where eid = :0 and id = :1",
"Subquery": "select eid, id from b limit :_vtMaxResultSize for update",
@ -1268,6 +1325,7 @@ update b set eid=foo()
"PlanId": "PASS_DML",
"Reason": "PK_CHANGE",
"TableName": "b",
"FieldQuery": null,
"FullQuery": "update b set eid = foo()",
"OuterQuery": null,
"Subquery": null,
@ -1285,6 +1343,7 @@ update a set name='foo'
"PlanId": "DML_SUBQUERY",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo'",
"OuterQuery": "update a set name = 'foo' where eid = :0 and id = :1",
"Subquery": "select eid, id from a limit :_vtMaxResultSize for update",
@ -1302,6 +1361,7 @@ update a set name='foo' where eid+1=1
"PlanId": "DML_SUBQUERY",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo' where eid+1 = 1",
"OuterQuery": "update a set name = 'foo' where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid+1 = 1 limit :_vtMaxResultSize for update",
@ -1320,6 +1380,7 @@ update a set name='foo' where eid=1 and id=1
"PlanId": "DML_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo' where eid = 1 and id = 1",
"OuterQuery": "update a set name = 'foo' where eid = 1 and id = 1",
"Subquery": "select eid, id from a where eid = 1 and id = 1 limit :_vtMaxResultSize for update",
@ -1341,6 +1402,7 @@ update a set name='foo' where eid=1
"PlanId": "DML_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo' where eid = 1",
"OuterQuery": "update a set name = 'foo' where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid = 1 limit :_vtMaxResultSize for update",
@ -1359,6 +1421,7 @@ update a set name='foo' where eid=1 limit 10
"PlanId": "DML_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo' where eid = 1 limit 10",
"OuterQuery": "update a set name = 'foo' where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid = 1 limit 10 for update",
@ -1377,6 +1440,7 @@ update a set name='foo' where eid=1 and name='foo'
"PlanId": "DML_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "update a set name = 'foo' where eid = 1 and name = 'foo'",
"OuterQuery": "update a set name = 'foo' where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid = 1 and name = 'foo' limit :_vtMaxResultSize for update",
@ -1395,6 +1459,7 @@ update c set eid=1
"PlanId": "PASS_DML",
"Reason": "TABLE_NOINDEX",
"TableName": "c",
"FieldQuery": null,
"FullQuery": "update c set eid = 1",
"OuterQuery": null,
"Subquery": null,
@ -1412,6 +1477,7 @@ delete from a
"PlanId": "DML_SUBQUERY",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "delete from a",
"OuterQuery": "delete from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a limit :_vtMaxResultSize for update",
@ -1429,6 +1495,7 @@ delete from a where eid+1=1
"PlanId": "DML_SUBQUERY",
"Reason": "WHERE",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "delete from a where eid+1 = 1",
"OuterQuery": "delete from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid+1 = 1 limit :_vtMaxResultSize for update",
@ -1447,6 +1514,7 @@ delete from a where eid=1 and id=1
"PlanId": "DML_PK",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "delete from a where eid = 1 and id = 1",
"OuterQuery": "delete from a where eid = 1 and id = 1",
"Subquery": "select eid, id from a where eid = 1 and id = 1 limit :_vtMaxResultSize for update",
@ -1468,6 +1536,7 @@ delete from a where eid=1
"PlanId": "DML_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "delete from a where eid = 1",
"OuterQuery": "delete from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid = 1 limit :_vtMaxResultSize for update",
@ -1486,6 +1555,7 @@ delete from a where eid=1 and name='foo'
"PlanId": "DML_SUBQUERY",
"Reason": "DEFAULT",
"TableName": "a",
"FieldQuery": null,
"FullQuery": "delete from a where eid = 1 and name = 'foo'",
"OuterQuery": "delete from a where eid = :0 and id = :1",
"Subquery": "select eid, id from a where eid = 1 and name = 'foo' limit :_vtMaxResultSize for update",
@ -1504,6 +1574,7 @@ delete from c
"PlanId": "PASS_DML",
"Reason": "TABLE_NOINDEX",
"TableName": "c",
"FieldQuery": null,
"FullQuery": "delete from c",
"OuterQuery": null,
"Subquery": null,
@ -1522,6 +1593,7 @@ set a=1
"PlanId": "SET",
"Reason": "DEFAULT",
"TableName": "",
"FieldQuery": null,
"FullQuery": "set a = 1",
"OuterQuery": null,
"Subquery": null,
@ -1540,6 +1612,7 @@ set a='b'
"PlanId": "SET",
"Reason": "DEFAULT",
"TableName": "",
"FieldQuery": null,
"FullQuery": "set a = 'b'",
"OuterQuery": null,
"Subquery": null,
@ -1558,6 +1631,7 @@ set a=1, b=2
"PlanId": "SET",
"Reason": "DEFAULT",
"TableName": "",
"FieldQuery": null,
"FullQuery": "set a = 1, b = 2",
"OuterQuery": null,
"Subquery": null,

Просмотреть файл

@ -24,6 +24,7 @@ func init() {
type PoolConnection interface {
ExecuteFetch(query []byte, maxrows int, wantfields bool) (*proto.QueryResult, error)
ExecuteStreamFetch(query []byte, callback func(interface{}) error, streamBufferSize int) error
VerifyStrict() bool
Id() int64
Close()
IsClosed() bool

Просмотреть файл

@ -65,7 +65,7 @@ type CacheInvalidator interface {
func NewQueryEngine(config Config) *QueryEngine {
qe := &QueryEngine{}
qe.cachePool = NewCachePool(config.CachePoolCap, time.Duration(config.QueryTimeout*1e9), time.Duration(config.IdleTimeout*1e9))
qe.schemaInfo = NewSchemaInfo(config.QueryCacheSize, time.Duration(config.SchemaReloadTime*1e9))
qe.schemaInfo = NewSchemaInfo(config.QueryCacheSize, time.Duration(config.SchemaReloadTime*1e9), time.Duration(config.IdleTimeout*1e9))
qe.connPool = NewConnectionPool(config.PoolSize, time.Duration(config.IdleTimeout*1e9))
qe.streamConnPool = NewConnectionPool(config.StreamPoolSize, time.Duration(config.IdleTimeout*1e9))
qe.reservedPool = NewReservedPool()
@ -196,7 +196,7 @@ func (qe *QueryEngine) Execute(logStats *sqlQueryStats, query *proto.Query) (rep
logStats.OriginalSql = query.Sql
// cheap hack: strip trailing comment into a special bind var
stripTrailing(query)
basePlan := qe.schemaInfo.GetPlan(query.Sql, len(query.BindVariables) != 0)
basePlan := qe.schemaInfo.GetPlan(logStats, query.Sql)
if basePlan.PlanId == sqlparser.PLAN_DDL {
defer queryStats.Record("DDL", time.Now())
return qe.execDDL(logStats, query.Sql)
@ -240,6 +240,20 @@ func (qe *QueryEngine) Execute(logStats *sqlQueryStats, query *proto.Query) (rep
defer queryStats.Record("PASS_SELECT", time.Now())
reply = qe.fullFetch(logStats, conn, plan.FullQuery, plan.BindVars, nil, nil)
}
} else if plan.ConnectionId != 0 {
conn := qe.reservedPool.Get(plan.ConnectionId)
defer conn.Recycle()
if plan.PlanId.IsSelect() {
logStats.PlanType = "PASS_SELECT"
defer queryStats.Record("PASS_SELECT", time.Now())
reply = qe.fullFetch(logStats, conn, plan.FullQuery, plan.BindVars, nil, nil)
} else if plan.PlanId == sqlparser.PLAN_SET {
logStats.PlanType = "SET"
defer queryStats.Record("SET", time.Now())
reply = qe.fullFetch(logStats, conn, plan.FullQuery, plan.BindVars, nil, nil)
} else {
panic(NewTabletError(FAIL, "DMLs not allowed outside of transactions"))
}
} else {
switch plan.PlanId {
case sqlparser.PLAN_PASS_SELECT:
@ -263,9 +277,13 @@ func (qe *QueryEngine) Execute(logStats *sqlQueryStats, query *proto.Query) (rep
// It may not be worth caching the results. So, just pass through.
reply = qe.execSelect(logStats, plan)
case sqlparser.PLAN_SET:
waitingForConnectionStart := time.Now()
conn := qe.connPool.Get()
logStats.WaitingForConnection += time.Now().Sub(waitingForConnectionStart)
defer conn.Recycle()
logStats.PlanType = "SET"
defer queryStats.Record("SET", time.Now())
reply = qe.execSet(logStats, plan)
reply = qe.execSet(logStats, conn, plan)
default:
panic(NewTabletError(FAIL, "DMLs not allowed outside of transactions"))
}
@ -399,9 +417,6 @@ func (qe *QueryEngine) execSubquery(logStats *sqlQueryStats, plan *CompiledPlan)
func (qe *QueryEngine) fetchPKRows(logStats *sqlQueryStats, plan *CompiledPlan, pkRows [][]sqltypes.Value) (result *mproto.QueryResult) {
result = &mproto.QueryResult{}
tableInfo := plan.TableInfo
if plan.Fields == nil {
panic("unexpected")
}
result.Fields = plan.Fields
rows := make([][]sqltypes.Value, 0, len(pkRows))
var hits, absent, misses int64
@ -466,23 +481,9 @@ func (qe *QueryEngine) compareRow(logStats *sqlQueryStats, plan *CompiledPlan, c
}
func (qe *QueryEngine) execSelect(logStats *sqlQueryStats, plan *CompiledPlan) (result *mproto.QueryResult) {
if plan.Fields != nil {
result = qe.qFetch(logStats, plan, plan.FullQuery, nil)
result.Fields = plan.Fields
return
}
var conn PoolConnection
waitingForConnectionStart := time.Now()
if plan.ConnectionId != 0 {
conn = qe.reservedPool.Get(plan.ConnectionId)
} else {
conn = qe.connPool.Get()
}
logStats.WaitingForConnection += time.Now().Sub(waitingForConnectionStart)
defer conn.Recycle()
result = qe.fullFetch(logStats, conn, plan.FullQuery, plan.BindVars, nil, nil)
qe.schemaInfo.SetFields(plan.Query, plan.ExecPlan, result.Fields)
return result
result = qe.qFetch(logStats, plan, plan.FullQuery, nil)
result.Fields = plan.Fields
return
}
func (qe *QueryEngine) execInsertPK(logStats *sqlQueryStats, conn PoolConnection, plan *CompiledPlan, invalidator CacheInvalidator) (result *mproto.QueryResult) {
@ -563,7 +564,7 @@ func (qe *QueryEngine) execDMLPKRows(logStats *sqlQueryStats, conn PoolConnectio
return &mproto.QueryResult{RowsAffected: rowsAffected}
}
func (qe *QueryEngine) execSet(logStats *sqlQueryStats, plan *CompiledPlan) (result *mproto.QueryResult) {
func (qe *QueryEngine) execSet(logStats *sqlQueryStats, conn PoolConnection, plan *CompiledPlan) (result *mproto.QueryResult) {
switch plan.SetKey {
case "vt_pool_size":
qe.connPool.SetCapacity(int(plan.SetValue.(float64)))
@ -608,20 +609,15 @@ func (qe *QueryEngine) execSet(logStats *sqlQueryStats, plan *CompiledPlan) (res
qe.activePool.SetIdleTimeout(time.Duration(t))
return &mproto.QueryResult{}
}
return qe.qFetch(logStats, plan, plan.FullQuery, nil)
return qe.fullFetch(logStats, conn, plan.FullQuery, plan.BindVars, nil, nil)
}
func (qe *QueryEngine) qFetch(logStats *sqlQueryStats, plan *CompiledPlan, parsed_query *sqlparser.ParsedQuery, listVars []sqltypes.Value) (result *mproto.QueryResult) {
sql := qe.generateFinalSql(parsed_query, plan.BindVars, listVars, nil)
q, ok := qe.consolidator.Create(string(sql))
if ok {
var conn PoolConnection
waitingForConnectionStart := time.Now()
if plan.ConnectionId != 0 {
conn = qe.reservedPool.Get(plan.ConnectionId)
} else {
conn = qe.connPool.Get()
}
conn := qe.connPool.Get()
logStats.WaitingForConnection += time.Now().Sub(waitingForConnectionStart)
defer conn.Recycle()
q.Result, q.Err = qe.executeSql(logStats, conn, sql, false)

Просмотреть файл

@ -38,16 +38,17 @@ type SchemaInfo struct {
tables map[string]*TableInfo
queryCacheSize int
queries *cache.LRUCache
connFactory CreateConnectionFunc
connPool *ConnectionPool
cachePool *CachePool
reloadTime time.Duration
lastChange time.Time
ticks *timer.Timer
}
func NewSchemaInfo(queryCacheSize int, reloadTime time.Duration) *SchemaInfo {
func NewSchemaInfo(queryCacheSize int, reloadTime time.Duration, idleTimeout time.Duration) *SchemaInfo {
si := &SchemaInfo{
queryCacheSize: queryCacheSize,
connPool: NewConnectionPool(2, idleTimeout),
reloadTime: reloadTime,
ticks: timer.NewTimer(reloadTime),
}
@ -56,11 +57,9 @@ func NewSchemaInfo(queryCacheSize int, reloadTime time.Duration) *SchemaInfo {
}
func (si *SchemaInfo) Open(connFactory CreateConnectionFunc, cachePool *CachePool) {
conn, err := connFactory()
if err != nil {
panic(NewTabletError(FATAL, "Could not get connection: %v", err))
}
defer conn.Close()
si.connPool.Open(connFactory)
conn := si.connPool.Get()
defer conn.Recycle()
if !conn.VerifyStrict() {
panic(NewTabletError(FATAL, "Could not verify strict mode"))
@ -90,7 +89,6 @@ func (si *SchemaInfo) Open(connFactory CreateConnectionFunc, cachePool *CachePoo
si.tables[tableName] = tableInfo
}
si.queries = cache.NewLRUCache(uint64(si.queryCacheSize))
si.connFactory = connFactory
si.ticks.Start(func() { si.Reload() })
}
@ -110,18 +108,14 @@ func (si *SchemaInfo) updateLastChange(createTime sqltypes.Value) {
func (si *SchemaInfo) Close() {
si.ticks.Stop()
si.connPool.Close()
si.tables = nil
si.queries = nil
si.connFactory = nil
}
func (si *SchemaInfo) Reload() {
conn, err := si.connFactory()
if err != nil {
relog.Error("Could not get connection for reload: %v", err)
return
}
defer conn.Close()
conn := si.connPool.Get()
defer conn.Recycle()
tables, err := conn.ExecuteFetch([]byte(fmt.Sprintf("%s and unix_timestamp(create_time) > %v", base_show_tables, si.lastChange.Unix())), 1000, false)
if err != nil {
relog.Warning("Could not get table list for reload: %v", err)
@ -147,15 +141,12 @@ func (si *SchemaInfo) triggerReload() {
}
func (si *SchemaInfo) CreateTable(tableName string) {
conn, err := si.connFactory()
if err != nil {
panic(NewTabletError(FATAL, "Could not get connection for create table %s: %v", tableName, err))
}
defer conn.Close()
conn := si.connPool.Get()
defer conn.Recycle()
si.createTable(conn, tableName)
}
func (si *SchemaInfo) createTable(conn *DBConnection, tableName string) {
func (si *SchemaInfo) createTable(conn PoolConnection, tableName string) {
tables, err := conn.ExecuteFetch([]byte(fmt.Sprintf("%s and table_name = '%s'", base_show_tables, tableName)), 1, false)
if err != nil {
panic(NewTabletError(FAIL, "Error fetching table %s: %v", tableName, err))
@ -195,7 +186,7 @@ func (si *SchemaInfo) DropTable(tableName string) {
relog.Info("Table %s forgotten", tableName)
}
func (si *SchemaInfo) GetPlan(sql string, mustCache bool) (plan *ExecPlan) {
func (si *SchemaInfo) GetPlan(logStats *sqlQueryStats, sql string) (plan *ExecPlan) {
si.mu.Lock()
defer si.mu.Unlock()
if plan := si.getQuery(sql); plan != nil {
@ -215,15 +206,22 @@ func (si *SchemaInfo) GetPlan(sql string, mustCache bool) (plan *ExecPlan) {
panic(NewTabletError(FAIL, "%s", err))
}
plan = &ExecPlan{splan, tableInfo, nil}
if plan.PlanId.IsSelect() && plan.ColumnNumbers != nil {
plan.Fields = applyFieldFilter(plan.ColumnNumbers, tableInfo.Fields)
}
if plan.PlanId == sqlparser.PLAN_DDL {
if plan.PlanId.IsSelect() {
conn := si.connPool.Get()
defer conn.Recycle()
sql := []byte(plan.FieldQuery.Query)
r, err := conn.ExecuteFetch(sql, 1, true)
logStats.QuerySources |= QUERY_SOURCE_MYSQL
logStats.NumberOfQueries += 1
logStats.AddRewrittenSql(sql)
if err != nil {
panic(NewTabletError(FAIL, "Error fetching fields: %v", err))
}
plan.Fields = r.Fields
} else if plan.PlanId == sqlparser.PLAN_DDL || plan.PlanId == sqlparser.PLAN_SET {
return plan
}
if mustCache {
si.queries.Set(sql, plan)
}
si.queries.Set(sql, plan)
return plan
}
@ -237,13 +235,6 @@ func (si *SchemaInfo) GetStreamPlan(sql string) *sqlparser.ParsedQuery {
return fullQuery
}
func (si *SchemaInfo) SetFields(sql string, plan *ExecPlan, fields []mproto.Field) {
si.mu.Lock()
defer si.mu.Unlock()
newPlan := &ExecPlan{plan.ExecPlan, plan.TableInfo, fields}
si.queries.Set(sql, newPlan)
}
func (si *SchemaInfo) GetTable(tableName string) *TableInfo {
si.mu.Lock()
defer si.mu.Unlock()

Просмотреть файл

@ -14,7 +14,6 @@ import (
"strings"
"sync/atomic"
"code.google.com/p/vitess/go/mysql/proto"
"code.google.com/p/vitess/go/relog"
"code.google.com/p/vitess/go/sqltypes"
"code.google.com/p/vitess/go/vt/schema"
@ -24,13 +23,12 @@ var hashRegistry map[string]string = make(map[string]string)
type TableInfo struct {
*schema.Table
Cache *RowCache
Fields []proto.Field
Cache *RowCache
// stats updated by sqlquery.go
hits, absent, misses, invalidations int64
}
func NewTableInfo(conn *DBConnection, tableName string, tableType string, createTime sqltypes.Value, comment string, cachePool *CachePool) (self *TableInfo) {
func NewTableInfo(conn PoolConnection, tableName string, tableType string, createTime sqltypes.Value, comment string, cachePool *CachePool) (self *TableInfo) {
if tableName == "dual" {
return &TableInfo{Table: schema.NewTable(tableName)}
}
@ -39,7 +37,7 @@ func NewTableInfo(conn *DBConnection, tableName string, tableType string, create
return self
}
func loadTableInfo(conn *DBConnection, tableName string) (self *TableInfo) {
func loadTableInfo(conn PoolConnection, tableName string) (self *TableInfo) {
self = &TableInfo{Table: schema.NewTable(tableName)}
if !self.fetchColumns(conn) {
return nil
@ -50,7 +48,7 @@ func loadTableInfo(conn *DBConnection, tableName string) (self *TableInfo) {
return self
}
func (self *TableInfo) fetchColumns(conn *DBConnection) bool {
func (self *TableInfo) fetchColumns(conn PoolConnection) bool {
columns, err := conn.ExecuteFetch([]byte(fmt.Sprintf("describe %s", self.Name)), 10000, false)
if err != nil {
relog.Warning("%s", err.Error())
@ -62,7 +60,7 @@ func (self *TableInfo) fetchColumns(conn *DBConnection) bool {
return true
}
func (self *TableInfo) fetchIndexes(conn *DBConnection) bool {
func (self *TableInfo) fetchIndexes(conn PoolConnection) bool {
indexes, err := conn.ExecuteFetch([]byte(fmt.Sprintf("show index from %s", self.Name)), 10000, false)
if err != nil {
relog.Warning("%s", err.Error())
@ -107,7 +105,7 @@ func (self *TableInfo) fetchIndexes(conn *DBConnection) bool {
return true
}
func (self *TableInfo) initRowCache(conn *DBConnection, tableType string, createTime sqltypes.Value, comment string, cachePool *CachePool) {
func (self *TableInfo) initRowCache(conn PoolConnection, tableType string, createTime sqltypes.Value, comment string, cachePool *CachePool) {
if cachePool.IsClosed() {
return
}
@ -133,24 +131,18 @@ func (self *TableInfo) initRowCache(conn *DBConnection, tableType string, create
}
}
rowInfo, err := conn.ExecuteFetch([]byte(fmt.Sprintf("select * from %s where 1!=1", self.Name)), 10000, true)
if err != nil {
relog.Warning("Failed to fetch column info for %s, table will not be cached: %s", self.Name, err.Error())
return
}
thash := self.computePrefix(conn, createTime)
if thash == "" {
return
}
self.Fields = rowInfo.Fields
self.CacheType = 1
self.Cache = NewRowCache(self, thash, cachePool)
}
var autoIncr = regexp.MustCompile("auto_increment=\\d+")
func (self *TableInfo) computePrefix(conn *DBConnection, createTime sqltypes.Value) string {
func (self *TableInfo) computePrefix(conn PoolConnection, createTime sqltypes.Value) string {
if createTime.IsNull() {
relog.Warning("%s has no time stamp. Will not be cached.", self.Name)
return ""

Просмотреть файл

@ -10,14 +10,18 @@ cases = [
sql="select * from vtocc_cached where eid = 2 and bid = %(bid)s",
bindings={"bid": None},
result=[],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = null",
rewritten=[
"select * from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = null"],
cache_absent=1),
Case(doc="SELECT_PK (empty cache)",
query_plan="SELECT_PK",
sql="select * from vtocc_cached where eid = 2 and bid = 'foo'",
result=[(2, 'foo', 'abcd2', 'efgh')],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = 'foo'",
rewritten=[
"select * from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = 'foo'"],
cache_misses=1),
# (2.foo) is in cache
@ -25,7 +29,7 @@ cases = [
query_plan="SELECT_PK",
sql="select bid, eid, name, foo from vtocc_cached where eid = 2 and bid = 'foo'",
result=[('foo', 2, 'abcd2', 'efgh')],
rewritten=[],
rewritten=["select bid, eid, name, foo from vtocc_cached where 1 != 1"],
cache_hits=1),
# (2.foo) is in cache
@ -33,7 +37,9 @@ cases = [
query_plan="SELECT_PK",
sql="select bid, eid, name, foo from vtocc_cached where eid = 3 and bid = 'foo'",
result=[],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 3 and bid = 'foo'",
rewritten=[
"select bid, eid, name, foo from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 3 and bid = 'foo'"],
cache_absent=1),
# (2.foo)
@ -41,8 +47,9 @@ cases = [
sql="select * from vtocc_cached where eid = 2 and name = 'abcd2'",
result=[(2L, 'bar', 'abcd2', 'efgh'), (2L, 'foo', 'abcd2', 'efgh')],
rewritten=[
"select eid, bid from vtocc_cached use index (aname) where eid = 2 and name = 'abcd2' limit 10001",
"select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = 'bar'"],
"select * from vtocc_cached where 1 != 1",
"select eid, bid from vtocc_cached use index (aname) where eid = 2 and name = 'abcd2' limit 10001",
"select eid, bid, name, foo from vtocc_cached where eid = 2 and bid = 'bar'"],
cache_hits=1,
cache_misses=1),
# (2.bar, 2.foo)
@ -57,7 +64,9 @@ cases = [
Case(doc="out of order columns list",
sql="select bid, eid from vtocc_cached where eid = 1 and bid = 'foo'",
result=[('foo', 1)],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'foo'",
rewritten=[
"select bid, eid from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'foo'"],
cache_misses=1),
# (1.foo, 2.bar, 2.foo)
@ -73,7 +82,9 @@ cases = [
['select * from vtocc_cached',
Case(query_plan="SELECT_CACHE_RESULT",
sql="select eid, bid, name, foo from vtocc_cached",
rewritten="select eid, bid, name, foo from vtocc_cached limit 10001",
rewritten=[
"select eid, bid, name, foo from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached limit 10001"],
cache_hits=0,
cache_misses=0,
cache_absent=0,
@ -84,7 +95,9 @@ cases = [
Case(doc="verify 1.bar is not cached",
sql="select bid, eid from vtocc_cached where eid = 1 and bid = 'bar'",
result=[('bar', 1)],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'bar'",
rewritten=[
"select bid, eid from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'bar'"],
cache_misses=1),
# (1.foo, 1.bar, 2.foo, 2.bar)
@ -163,7 +176,7 @@ cases = [
Case(doc="Verify 1.foo is in cache",
sql="select * from vtocc_cached where eid = 1 and bid = 'foo'",
result=[(1, 'foo', 'abcd1', 'efgh')],
rewritten=[],
rewritten=["select * from vtocc_cached where 1 != 1"],
cache_hits=1),
# (1.foo) is in cache
@ -173,7 +186,9 @@ cases = [
Case(doc="Verify cache is empty after DDL",
sql="select * from vtocc_cached where eid = 1 and bid = 'foo'",
result=[(1, 'foo', 'abcd1', 'efgh')],
rewritten="select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'foo'",
rewritten=[
"select * from vtocc_cached where 1 != 1",
"select eid, bid, name, foo from vtocc_cached where eid = 1 and bid = 'foo'"],
cache_misses=1),
# (1.foo)
@ -194,7 +209,9 @@ cases = [
'commit',
Case(sql="select * from vtocc_ints where tiny = -128",
result=[(-128, 255, -32768, 65535, -8388608, 16777215, -2147483648L, 4294967295L, -9223372036854775808L, 18446744073709551615L, 2012)],
rewritten="select tiny, tinyu, small, smallu, medium, mediumu, normal, normalu, big, bigu, y from vtocc_ints where tiny = -128"),
rewritten=[
"select * from vtocc_ints where 1 != 1",
"select tiny, tinyu, small, smallu, medium, mediumu, normal, normalu, big, bigu, y from vtocc_ints where tiny = -128"]),
Case(sql="select * from vtocc_ints where tiny = -128",
result=[(-128, 255, -32768, 65535, -8388608, 16777215, -2147483648L, 4294967295L, -9223372036854775808L, 18446744073709551615L, 2012)],
rewritten=[]),
@ -217,7 +234,9 @@ cases = [
'commit',
Case(sql="select * from vtocc_fracts where id = 1",
result=[(1L, Decimal('1.99'), Decimal('2.99'), 3.9900000000000002, 4.9900000000000002)],
rewritten="select id, deci, num, f, d from vtocc_fracts where id = 1"),
rewritten=[
"select * from vtocc_fracts where 1 != 1",
"select id, deci, num, f, d from vtocc_fracts where id = 1"]),
Case(sql="select * from vtocc_fracts where id = 1",
result=[(1L, Decimal('1.99'), Decimal('2.99'), 3.9900000000000002, 4.9900000000000002)],
rewritten=[]),
@ -240,7 +259,9 @@ cases = [
'commit',
Case(sql="select * from vtocc_strings where vb = 'a'",
result=[('a', 'b', 'c', 'd\x00\x00\x00', 'e', 'f', 'g', 'h', 'a', 'a,b')],
rewritten="select vb, c, vc, b, tb, bl, ttx, tx, en, s from vtocc_strings where vb = 'a'"),
rewritten=[
"select * from vtocc_strings where 1 != 1",
"select vb, c, vc, b, tb, bl, ttx, tx, en, s from vtocc_strings where vb = 'a'"]),
Case(sql="select * from vtocc_strings where vb = 'a'",
result=[('a', 'b', 'c', 'd\x00\x00\x00', 'e', 'f', 'g', 'h', 'a', 'a,b')],
rewritten=[]),
@ -263,7 +284,9 @@ cases = [
'commit',
Case(sql="select * from vtocc_misc where id = 1",
result=[(1L, '\x01', datetime.date(2012, 1, 1), datetime.datetime(2012, 1, 1, 15, 45, 45), datetime.timedelta(0, 56745))],
rewritten="select id, b, d, dt, t from vtocc_misc where id = 1"),
rewritten=[
"select * from vtocc_misc where 1 != 1",
"select id, b, d, dt, t from vtocc_misc where id = 1"]),
Case(sql="select * from vtocc_misc where id = 1",
result=[(1L, '\x01', datetime.date(2012, 1, 1), datetime.datetime(2012, 1, 1, 15, 45, 45), datetime.timedelta(0, 56745))],
rewritten=[]),

Просмотреть файл

@ -4,100 +4,142 @@ cases = [
Case(doc='union',
sql='select /* union */ eid, id from vtocc_a union select eid, id from vtocc_b',
result=[(1L, 1L), (1L, 2L)],
rewritten='select /* union */ eid, id from vtocc_a union select eid, id from vtocc_b'),
rewritten=[
'select eid, id from vtocc_a where 1 != 1 union select eid, id from vtocc_b where 1 != 1',
'select /* union */ eid, id from vtocc_a union select eid, id from vtocc_b']),
Case(doc='double union',
sql='select /* double union */ eid, id from vtocc_a union select eid, id from vtocc_b union select eid, id from vtocc_d',
result=[(1L, 1L), (1L, 2L)],
rewritten=[
'select eid, id from vtocc_a where 1 != 1 union select eid, id from vtocc_b where 1 != 1 union select eid, id from vtocc_d where 1 != 1',
'select /* double union */ eid, id from vtocc_a union select eid, id from vtocc_b union select eid, id from vtocc_d']),
Case(doc="distinct",
sql='select /* distinct */ distinct * from vtocc_a',
result=[(1L, 1L, 'abcd', 'efgh'), (1L, 2L, 'bcde', 'fghi')],
rewritten='select /* distinct */ distinct * from vtocc_a limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* distinct */ distinct * from vtocc_a limit 10001']),
Case(doc='group by',
sql='select /* group by */ eid, sum(id) from vtocc_a group by eid',
result=[(1L, 3L)],
rewritten='select /* group by */ eid, sum(id) from vtocc_a group by eid limit 10001'),
rewritten=[
'select eid, sum(id) from vtocc_a where 1 != 1',
'select /* group by */ eid, sum(id) from vtocc_a group by eid limit 10001']),
Case(doc='having',
sql='select /* having */ sum(id) from vtocc_a having sum(id) = 3',
result=[(3L,)],
rewritten='select /* having */ sum(id) from vtocc_a having sum(id) = 3 limit 10001',),
rewritten=[
'select sum(id) from vtocc_a where 1 != 1',
'select /* having */ sum(id) from vtocc_a having sum(id) = 3 limit 10001']),
Case(doc='limit',
sql='select /* limit */ eid, id from vtocc_a limit %(a)s',
bindings={"a": 1},
result=[(1L, 1L)],
rewritten='select /* limit */ eid, id from vtocc_a limit 1'),
rewritten=[
'select eid, id from vtocc_a where 1 != 1',
'select /* limit */ eid, id from vtocc_a limit 1']),
Case(doc='multi-table',
sql='select /* multi-table */ a.eid, a.id, b.eid, b.id from vtocc_a as a, vtocc_b as b',
result=[(1L, 1L, 1L, 1L), (1L, 2L, 1L, 1L), (1L, 1L, 1L, 2L), (1L, 2L, 1L, 2L)],
rewritten='select /* multi-table */ a.eid, a.id, b.eid, b.id from vtocc_a as a, vtocc_b as b limit 10001'),
rewritten=[
'select a.eid, a.id, b.eid, b.id from vtocc_a as a, vtocc_b as b where 1 != 1',
'select /* multi-table */ a.eid, a.id, b.eid, b.id from vtocc_a as a, vtocc_b as b limit 10001']),
Case(doc='multi-table join',
sql='select /* multi-table join */ a.eid, a.id, b.eid, b.id from vtocc_a as a join vtocc_b as b on a.eid = b.eid and a.id = b.id',
result=[(1L, 1L, 1L, 1L), (1L, 2L, 1L, 2L)],
rewritten='select /* multi-table join */ a.eid, a.id, b.eid, b.id from vtocc_a as a join vtocc_b as b on a.eid = b.eid and a.id = b.id limit 10001'),
rewritten=[
'select a.eid, a.id, b.eid, b.id from vtocc_a as a join vtocc_b as b on a.eid = b.eid and a.id = b.id where 1 != 1',
'select /* multi-table join */ a.eid, a.id, b.eid, b.id from vtocc_a as a join vtocc_b as b on a.eid = b.eid and a.id = b.id limit 10001']),
Case(doc='complex select list',
sql='select /* complex select list */ eid+1, id from vtocc_a',
result=[(2L, 1L), (2L, 2L)],
rewritten='select /* complex select list */ eid+1, id from vtocc_a limit 10001'),
rewritten=[
'select eid+1, id from vtocc_a where 1 != 1',
'select /* complex select list */ eid+1, id from vtocc_a limit 10001']),
Case(doc="*",
sql='select /* * */ * from vtocc_a',
result=[(1L, 1L, 'abcd', 'efgh'), (1L, 2L, 'bcde', 'fghi')],
rewritten='select /* * */ * from vtocc_a limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* * */ * from vtocc_a limit 10001']),
Case(doc='table alias',
sql='select /* table alias */ a.eid from vtocc_a as a where a.eid=1',
result=[(1L,), (1L,)],
rewritten='select /* table alias */ a.eid from vtocc_a as a where a.eid = 1 limit 10001'),
rewritten=[
'select a.eid from vtocc_a as a where 1 != 1',
'select /* table alias */ a.eid from vtocc_a as a where a.eid = 1 limit 10001']),
Case(doc='parenthesised col',
sql='select /* parenthesised col */ (eid) from vtocc_a where eid = 1 and id = 1',
result=[(1L,)],
rewritten='select /* parenthesised col */ eid from vtocc_a where eid = 1 and id = 1 limit 10001'),
rewritten=[
'select eid from vtocc_a where 1 != 1',
'select /* parenthesised col */ eid from vtocc_a where eid = 1 and id = 1 limit 10001']),
MultiCase('for update',
['begin',
Case(sql='select /* for update */ eid from vtocc_a where eid = 1 and id = 1 for update',
result=[(1L,)],
rewritten='select /* for update */ eid from vtocc_a where eid = 1 and id = 1 limit 10001 for update'),
rewritten=[
'select eid from vtocc_a where 1 != 1',
'select /* for update */ eid from vtocc_a where eid = 1 and id = 1 limit 10001 for update']),
'commit']),
Case(doc='complex where',
sql='select /* complex where */ id from vtocc_a where id+1 = 2',
result=[(1L,)],
rewritten='select /* complex where */ id from vtocc_a where id+1 = 2 limit 10001'),
rewritten=[
'select id from vtocc_a where 1 != 1',
'select /* complex where */ id from vtocc_a where id+1 = 2 limit 10001']),
Case(doc='complex where (non-value operand)',
sql='select /* complex where (non-value operand) */ eid, id from vtocc_a where eid = id',
result=[(1L, 1L)],
rewritten='select /* complex where (non-value operand) */ eid, id from vtocc_a where eid = id limit 10001'),
rewritten=[
'select eid, id from vtocc_a where 1 != 1',
'select /* complex where (non-value operand) */ eid, id from vtocc_a where eid = id limit 10001']),
Case(doc='(condition)',
sql='select /* (condition) */ * from vtocc_a where (eid = 1)',
result=[(1L, 1L, 'abcd', 'efgh'), (1L, 2L, 'bcde', 'fghi')],
rewritten='select /* (condition) */ * from vtocc_a where (eid = 1) limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* (condition) */ * from vtocc_a where (eid = 1) limit 10001']),
Case(doc='inequality',
sql='select /* inequality */ * from vtocc_a where id > 1',
result=[(1L, 2L, 'bcde', 'fghi')],
rewritten='select /* inequality */ * from vtocc_a where id > 1 limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* inequality */ * from vtocc_a where id > 1 limit 10001']),
Case(doc='in',
sql='select /* in */ * from vtocc_a where id in (1, 2)',
result=[(1L, 1L, 'abcd', 'efgh'), (1L, 2L, 'bcde', 'fghi')],
rewritten='select /* in */ * from vtocc_a where id in (1, 2) limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* in */ * from vtocc_a where id in (1, 2) limit 10001']),
Case(doc='between',
sql='select /* between */ * from vtocc_a where id between 1 and 2',
result=[(1L, 1L, 'abcd', 'efgh'), (1L, 2L, 'bcde', 'fghi')],
rewritten='select /* between */ * from vtocc_a where id between 1 and 2 limit 10001'),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* between */ * from vtocc_a where id between 1 and 2 limit 10001']),
Case(doc='order',
sql='select /* order */ * from vtocc_a order by id desc',
result=[(1L, 2L, 'bcde', 'fghi'), (1L, 1L, 'abcd', 'efgh')],
rewritten='select /* order */ * from vtocc_a order by id desc limit 10001'),
Case(doc='string in bindings are not shown in logs',
sql='select /* limit */ %(somestring)s, eid, id from vtocc_a limit %(a)s',
bindings={"somestring": "Ala ma kota.", "a": 1}),
rewritten=[
'select * from vtocc_a where 1 != 1',
'select /* order */ * from vtocc_a order by id desc limit 10001']),
MultiCase(
'simple insert',

Просмотреть файл

@ -202,6 +202,11 @@ class TestNocache(framework.TestCase):
self.assertEqual(vend.Voltron.QueryCache.Length, 2)
self.assertEqual(vend.Voltron.QueryCache.Size, 2)
self.assertEqual(vend.Voltron.QueryCache.Capacity, 5000)
self.env.execute("select * from vtocc_test where intval=1")
vend = self.env.debug_vars()
self.assertEqual(vend.Voltron.QueryCache.Length, 3)
self.assertEqual(vend.Voltron.QueryCache.Size, 3)
self.assertEqual(vend.Voltron.QueryCache.Capacity, 5000)
def test_schema_reload_time(self):
mcu = self.env.mysql_conn.cursor()
@ -306,6 +311,14 @@ class TestNocache(framework.TestCase):
results = self.env.conn._execute_batch(queries, bvars)
self.assertEqual(results, [([(1L, 2L, 'bcde', 'fghi')], 1, 0, [('eid', 8), ('id', 3), ('name', 253), ('foo', 253)]), ([(1L, 2L)], 1, 0, [('eid', 8), ('id', 3)])])
def test_bind_in_select(self):
try:
bv = {}
bv['bv'] = 1
self.env.execute('select %(bv)s from vtocc_test', bv)
except (db.MySQLErrors.DatabaseError, db.dbexceptions.OperationalError), e:
self.assertContains(e[1], "error: Syntax error")
def test_types(self):
self._verify_mismatch("insert into vtocc_ints(tiny) values('str')")
self._verify_mismatch("insert into vtocc_ints(tiny) values(%(str)s)", {"str": "str"})