func (si *SchemaInfo) GetPlan(logStats *SQLQueryStats, sql string, queryRuleInfo *QueryRuleInfo) *ExecPlan { // Fastpath if plan already exists. if plan := si.getQuery(sql); plan != nil { return plan } si.mu.Lock() defer si.mu.Unlock() // Recheck. A plan might have been built by someone else. if plan := si.getQuery(sql); plan != nil { return plan } var tableInfo *TableInfo GetTable := func(tableName string) (table *schema.Table, ok bool) { tableInfo, ok = si.tables[tableName] if !ok { return nil, false } return tableInfo.Table, true } splan, err := planbuilder.GetExecPlan(sql, GetTable) if err != nil { panic(NewTabletError(FAIL, "%s", err)) } plan := &ExecPlan{ExecPlan: splan, TableInfo: tableInfo} plan.Rules = queryRuleInfo.filterByPlan(sql, plan.PlanId, plan.TableName) plan.Authorized = tableacl.Authorized(plan.TableName, plan.PlanId.MinRole()) if plan.PlanId.IsSelect() { if plan.FieldQuery == nil { log.Warningf("Cannot cache field info: %s", sql) } else { conn := getOrPanic(si.connPool) defer conn.Recycle() sql := plan.FieldQuery.Query start := time.Now() r, err := conn.ExecuteFetch(sql, 1, true) logStats.AddRewrittenSql(sql, start) if err != nil { panic(NewTabletError(FAIL, "Error fetching fields: %v", err)) } plan.Fields = r.Fields } } else if plan.PlanId == planbuilder.PLAN_DDL || plan.PlanId == planbuilder.PLAN_SET { return plan } si.queries.Set(sql, plan) return plan }
// GetStreamPlan is similar to GetPlan, but doesn't use the cache // and doesn't enforce a limit. It just returns the parsed query. func (si *SchemaInfo) GetStreamPlan(sql string, queryRuleInfo *QueryRuleInfo) *ExecPlan { var tableInfo *TableInfo GetTable := func(tableName string) (table *schema.Table, ok bool) { si.mu.Lock() defer si.mu.Unlock() tableInfo, ok = si.tables[tableName] if !ok { return nil, false } return tableInfo.Table, true } splan, err := planbuilder.GetStreamExecPlan(sql, GetTable) if err != nil { panic(NewTabletError(FAIL, "%s", err)) } plan := &ExecPlan{ExecPlan: splan, TableInfo: tableInfo} plan.Rules = queryRuleInfo.filterByPlan(sql, plan.PlanId, plan.TableName) plan.Authorized = tableacl.Authorized(plan.TableName, plan.PlanId.MinRole()) return plan }