{"record":{"id":"0cde275098db7ab9","repo":"cayleygraph/cayley","slug":"not-a-sql-quadstore-t","errorCode":null,"errorMessage":"not a SQL quadstore: %T","messagePattern":"not a SQL quadstore: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/sql/shape.go","lineNumber":309,"sourceCode":"\treturn s.Limit > 0 || s.Offset > 0\n}\n\nfunc (s Select) Columns() []string {\n\tnames := make([]string, 0, len(s.Fields))\n\tfor _, f := range s.Fields {\n\t\tname := f.Alias\n\t\tif name == \"\" {\n\t\t\tname = f.Name\n\t\t}\n\t\tnames = append(names, name)\n\t}\n\treturn names\n}\n\nfunc (s Select) BuildIterator(qs graph.QuadStore) iterator.Shape {\n\tsq, ok := qs.(*QuadStore)\n\tif !ok {\n\t\treturn iterator.NewError(fmt.Errorf(\"not a SQL quadstore: %T\", qs))\n\t}\n\treturn sq.newIterator(s)\n}\n\nfunc (s Select) Optimize(ctx context.Context, r shape.Optimizer) (shape.Shape, bool) {\n\t// TODO: call optimize on sub-tables? but what if it decides to de-optimize our SQL shape?\n\treturn s, false\n}\n\nfunc (s *Select) AppendParam(o Value) Expr {\n\ts.Params = append(s.Params, o)\n\treturn Placeholder{}\n}\n\nfunc (s *Select) WhereEq(tbl, field string, v Value) {\n\ts.Where = append(s.Where, Where{\n\t\tTable: tbl,\n\t\tField: field,","sourceCodeStart":291,"sourceCodeEnd":327,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/sql/shape.go#L291-L327","documentation":"Select (a SQL-specific query shape) can only be executed against a *sql.QuadStore. BuildIterator type-asserts the provided graph.QuadStore; if a different implementation is passed, it returns an iterator that resolves to this error instead of panicking.","triggerScenarios":"Passing a memory, badger, or other non-SQL QuadStore to a query pipeline built with sql.Select, e.g. memstore QS + SQL shape optimizer output.","commonSituations":"Mixing backends: building queries with the SQL package while the application opened a memory store; optimizer pipelines that hand shapes to the wrong QuadStore instance.","solutions":["Ensure the QuadStore passed to the query was opened via graph/sql.New or Init","Check which backend your configuration actually selects; align query-building code with it","Only use sql.Select shapes when the store is the SQL implementation","For other backends, use their native query path (e.g. general iterator shapes)"],"exampleFix":"// before\nqs, _ := graph.NewQuadStore(\"memory\", \"\")\nit := sql.Select{...}.BuildIterator(qs) // error\n// after\nqs, _ := graph.NewQuadStore(\"sql\", addr)\nit := sql.Select{...}.BuildIterator(qs)","handlingStrategy":"type-guard","validationCode":"if _, ok := qs.(*sql.QuadStore); !ok {\n    return errors.New(\"sql.Select requires a sql quadstore\")\n}","typeGuard":"func isSQLQuadStore(qs graph.QuadStore) bool {\n    _, ok := qs.(*sql.QuadStore)\n    return ok\n}","tryCatchPattern":"it := sql.Select{...}.BuildIterator(qs)\n// iterator resolves to error; check on next()\nif it.Next(ctx) {\n    // ok\n} else if err := it.Err(); err != nil && strings.Contains(err.Error(), \"not a SQL quadstore\") {\n    // rebuild query with the correct backend\n}","preventionTips":["Pair sql.Select shapes only with stores opened via sql.New","Verify the backend selected by config matches query-building code","Add an assertion after opening the store"],"tags":["sql","quadstore","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}