func (self *TableInfo) initRowCache(conn *DBConnection, cacheSize uint64) { if self.PKColumns == nil { relog.Warning("Table %s has no primary key. Will not be cached.", self.Name) return } rowInfo, err := conn.ExecuteFetch([]byte(fmt.Sprintf("select * from %s where 1!=1", self.Name)), 10000) if err != nil { relog.Warning("Failed to fetch column info for %s, table will not be cached: %s", self.Name, err.Error()) return } self.Fields = rowInfo.Fields self.CacheType = 1 self.CacheSize = cacheSize self.RowCache = cache.NewLRUCache(self.CacheSize) }
func (self *TableInfo) fetchIndexes(conn *DBConnection) bool { indexes, err := conn.ExecuteFetch([]byte(fmt.Sprintf("show index from %s", self.Name)), 10000) if err != nil { relog.Warning("%s", err.Error()) return false } var currentIndex *schema.Index currentName := "" for _, row := range indexes.Rows { indexName := row[2].(string) if currentName != indexName { currentIndex = self.AddIndex(indexName) currentName = indexName } currentIndex.AddColumn(row[4].(string)) } if len(self.Indexes) == 0 { return true } pkIndex := self.Indexes[0] if pkIndex.Name != "PRIMARY" { return true } self.PKColumns = make([]int, len(pkIndex.Columns)) for i, pkCol := range pkIndex.Columns { self.PKColumns[i] = self.FindColumn(pkCol) } return true }
func Run_server(laddr string) error { listen_sock, err := net.Listen("tcp", laddr) if err != nil { panic(err) } defer listen_sock.Close() sv := new(server) store, err := newLeveldb() if err != nil { panic(err) } sv.s = store sv.kt = make(map[string]chan action) sv.lock = new(sync.RWMutex) defer store.db.Close() for { conn, err := listen_sock.Accept() if err != nil { relog.Warning("%s", err) continue } c := newConn(conn, sv) relog.Info("accept successed, client ip is %s", c.remoteAddr) go c.serve() } panic("not reached") }
func getPKValues(conditions []*Node, pkIndex *schema.Index) (pkValues []interface{}) { if pkIndex.Name != "PRIMARY" { relog.Warning("Table has no primary key") return nil } pkIndexScore := NewIndexScore(pkIndex) pkValues = make([]interface{}, len(pkIndexScore.ColumnMatch)) for _, condition := range conditions { if condition.Type != '=' && condition.Type != IN { return nil } index := pkIndexScore.FindMatch(string(condition.At(0).Value)) if index == -1 { return nil } switch condition.Type { case '=': pkValues[index] = string(condition.At(1).Value) case IN: pkValues[index], _ = condition.At(1).At(0).parseList() } } if pkIndexScore.GetScore() == 1000 { return pkValues } return nil }
func (self *Node) execAnalyzeDelete(getTable TableGetter) (plan *ExecPlan) { // Default plan plan = &ExecPlan{PlanId: PLAN_PASS_DML, FullQuery: self.GenerateFullQuery()} tableName := string(self.At(DELETE_TABLE_OFFSET).Value) tableInfo := plan.setTableInfo(tableName, getTable) if len(tableInfo.Indexes) == 0 || tableInfo.Indexes[0].Name != "PRIMARY" { relog.Warning("no primary key for table %s", tableName) plan.Reason = REASON_TABLE_NOINDEX return plan } plan.PlanId = PLAN_DML_SUBQUERY plan.OuterQuery = self.GenerateDeleteOuterQuery(tableInfo.Indexes[0]) plan.Subquery = self.GenerateDeleteSubquery(tableInfo) conditions := self.At(DELETE_WHERE_OFFSET).execAnalyzeWhere() if conditions == nil { plan.Reason = REASON_WHERE return plan } if pkValues := getPKValues(conditions, tableInfo.Indexes[0]); pkValues != nil { plan.PlanId = PLAN_DML_PK plan.OuterQuery = plan.FullQuery plan.PKValues = pkValues return plan } return plan }
func StartQueryService(poolSize, transactionCap int, transactionTimeout float64, maxResultSize, queryCacheSize int, schemaReloadTime, queryTimeout, idleTimeout float64) { if SqlQueryRpcService != nil { relog.Warning("RPC service already up %v", SqlQueryRpcService) return } SqlQueryRpcService = NewSqlQuery(poolSize, transactionCap, transactionTimeout, maxResultSize, queryCacheSize, schemaReloadTime, queryTimeout, idleTimeout) rpc.Register(SqlQueryRpcService) }
func (self *Node) execAnalyzeInsert(getTable TableGetter) (plan *ExecPlan) { plan = &ExecPlan{PlanId: PLAN_PASS_DML, FullQuery: self.GenerateFullQuery()} tableName := string(self.At(INSERT_TABLE_OFFSET).Value) tableInfo := plan.setTableInfo(tableName, getTable) if len(tableInfo.Indexes) == 0 || tableInfo.Indexes[0].Name != "PRIMARY" { relog.Warning("no primary key for table %s", tableName) plan.Reason = REASON_TABLE_NOINDEX return plan } columns := self.At(INSERT_COLUMN_LIST_OFFSET) if columns.Len() == 0 { relog.Warning("insert column list not specified for table %s", tableName) return plan } if self.At(INSERT_ON_DUP_OFFSET).Len() != 0 { var ok bool if plan.SecondaryPKValues, ok = self.At(INSERT_ON_DUP_OFFSET).At(0).execAnalyzeUpdateExpressions(tableInfo.Indexes[0]); !ok { plan.Reason = REASON_PK_CHANGE return plan } } rowValues := self.At(INSERT_VALUES_OFFSET) // VALUES/SELECT if rowValues.Type == SELECT { plan.PlanId = PLAN_INSERT_SUBQUERY plan.OuterQuery = self.GenerateInsertOuterQuery() plan.Subquery = rowValues.GenerateSelectLimitQuery() // Column list syntax is a subset of select expressions plan.ColumnNumbers = columns.execAnalyzeSelectExpressions(tableInfo) plan.SubqueryPKColumns = getPKValuesFromColumns(columns, tableInfo.Indexes[0]) return plan } rowList := rowValues.At(0) // VALUES->NODE_LIST if pkValues := getInsertPKValues(columns, rowList, tableInfo.Indexes[0]); pkValues != nil { plan.PlanId = PLAN_INSERT_PK plan.OuterQuery = plan.FullQuery plan.PKValues = pkValues } return plan }
func (self *TableInfo) fetchColumns(conn *DBConnection) bool { columns, err := conn.ExecuteFetch([]byte(fmt.Sprintf("describe %s", self.Name)), 10000) if err != nil { relog.Warning("%s", err.Error()) return false } for _, row := range columns.Rows { self.AddColumn(row[0].(string), row[1].(string)) } return true }
func ExecParse(sql string, getTable TableGetter) (plan *ExecPlan, err error) { defer handleError(&err) tree, err := Parse(sql) if err != nil { return nil, err } plan = tree.execAnalyzeSql(getTable) if plan.PlanId == PLAN_PASS_DML { relog.Warning("PASS_DML: %s", sql) } return plan, nil }
func getInsertPKValues(columns *Node, rowList *Node, pkIndex *schema.Index) (pkValues []interface{}) { for i := 0; i < rowList.Len(); i++ { if columns.Len() != rowList.At(i).At(0).Len() { // NODE_LIST->'('->NODE_LIST panic(NewParserError("number of columns does not match number of values")) } } pkValues = make([]interface{}, len(pkIndex.Columns)) for i := 0; i < columns.Len(); i++ { index := pkIndex.FindColumn(string(columns.At(i).Value)) if index == -1 { continue } if rowList.Len() == 1 { // simple node := rowList.At(0).At(0).At(i) // NODE_LIST->'('->NODE_LIST->Value value := node.execAnalyzeValue() if value == nil { relog.Warning("insert is too complex %v", node) return nil } pkValues[index] = string(value.Value) } else { // composite values := make([]interface{}, rowList.Len()) for j := 0; j < rowList.Len(); j++ { node := rowList.At(j).At(0).At(i) // NODE_LIST->'('->NODE_LIST->Value value := node.execAnalyzeValue() if value == nil { relog.Warning("insert is too complex %v", node) return nil } values[j] = string(value.Value) } pkValues[index] = values } } return pkValues }
func signal_init() { c := make(chan os.Signal) signal.Notify(c, os.Interrupt) go func() { for sig := range c { switch sig { case syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: relog.Warning("Terminating on signal", sig) if *cpuprofile != "" { pprof.StopCPUProfile() } os.Exit(0) } } }() }
func (self *Node) execAnalyzeUpdateExpressions(pkIndex *schema.Index) (pkValues []interface{}, ok bool) { for i := 0; i < self.Len(); i++ { columnName := string(self.At(i).At(0).Value) if index := pkIndex.FindColumn(columnName); index != -1 { value := self.At(i).At(1).execAnalyzeValue() if value == nil { relog.Warning("expression is too complex %v", self.At(i).At(0)) return nil, false } if pkValues == nil { pkValues = make([]interface{}, len(pkIndex.Columns)) } pkValues[index] = string(value.Value) } } return pkValues, true }