Feat v0.8.3 vector column (#70)
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Has been skipped
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / test-sqlite (push) Successful in 2m59s
CI/CD / test-go-pg (push) Successful in 2m58s
CI/CD / build-and-deploy (push) Successful in 1m14s
All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Has been skipped
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / test-sqlite (push) Successful in 2m59s
CI/CD / test-go-pg (push) Successful in 2m58s
CI/CD / build-and-deploy (push) Successful in 1m14s
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #70.
This commit is contained in:
@@ -145,7 +145,7 @@ func TestMapColType_SQLite(t *testing.T) {
|
||||
{"unknown", "TEXT"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
got := mapColType(c.in, false)
|
||||
got := mapColType(c.in, false, false)
|
||||
if got != c.want {
|
||||
t.Errorf("mapColType(%q, sqlite) = %q, want %q", c.in, got, c.want)
|
||||
}
|
||||
@@ -153,13 +153,13 @@ func TestMapColType_SQLite(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestMapColType_Postgres(t *testing.T) {
|
||||
if mapColType("bool", true) != "BOOLEAN" {
|
||||
if mapColType("bool", true, false) != "BOOLEAN" {
|
||||
t.Error("expected BOOLEAN for bool in postgres")
|
||||
}
|
||||
if mapColType("timestamp", true) != "TIMESTAMPTZ" {
|
||||
if mapColType("timestamp", true, false) != "TIMESTAMPTZ" {
|
||||
t.Error("expected TIMESTAMPTZ for timestamp in postgres")
|
||||
}
|
||||
if mapColType("int", true) != "INTEGER" {
|
||||
if mapColType("int", true, false) != "INTEGER" {
|
||||
t.Error("expected INTEGER for int in postgres")
|
||||
}
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func TestCreateExtTables_CreatesTable(t *testing.T) {
|
||||
Columns: map[string]string{"message": "text", "count": "int"},
|
||||
},
|
||||
}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "test-pkg", tables); err != nil {
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "test-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ func TestCreateExtTables_WithIndexes(t *testing.T) {
|
||||
Indexes: [][]string{{"user_id"}, {"user_id", "kind"}},
|
||||
},
|
||||
}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "idx-pkg", tables); err != nil {
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "idx-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ func TestCreateExtTables_CatalogRegistration(t *testing.T) {
|
||||
"logs": {Columns: map[string]string{"msg": "text"}},
|
||||
"errors": {Columns: map[string]string{"detail": "text"}},
|
||||
}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "cat-pkg", tables); err != nil {
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "cat-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ func TestCreateExtTables_NilDBIsNoop(t *testing.T) {
|
||||
// Should not panic or error.
|
||||
err := CreateExtTables(ctx, nil, false, storesWithExtData(m), "pkg", map[string]TableDef{
|
||||
"t": {Columns: map[string]string{"x": "text"}},
|
||||
})
|
||||
}, false)
|
||||
if err != nil {
|
||||
t.Errorf("expected nil error for nil db, got: %v", err)
|
||||
}
|
||||
@@ -276,7 +276,7 @@ func TestDropExtTables_DropsAndClearsCatalog(t *testing.T) {
|
||||
tables := map[string]TableDef{
|
||||
"items": {Columns: map[string]string{"name": "text"}},
|
||||
}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "drop-pkg", tables); err != nil {
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "drop-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
@@ -309,7 +309,7 @@ func TestDropExtTables_MultipleTables(t *testing.T) {
|
||||
"alpha": {Columns: map[string]string{"v": "text"}},
|
||||
"beta": {Columns: map[string]string{"v": "text"}},
|
||||
}
|
||||
CreateExtTables(ctx, db, false, storesWithExtData(m), "multi-pkg", tables)
|
||||
CreateExtTables(ctx, db, false, storesWithExtData(m), "multi-pkg", tables, false)
|
||||
DropExtTables(ctx, db, storesWithExtData(m), "multi-pkg")
|
||||
|
||||
for _, name := range []string{"ext_multi_pkg_alpha", "ext_multi_pkg_beta"} {
|
||||
@@ -331,7 +331,7 @@ func TestCreateExtTables_DDLContainsAutoColumns(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
tables := map[string]TableDef{"empty": {Columns: map[string]string{}}}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "auto-pkg", tables); err != nil {
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "auto-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
@@ -348,3 +348,77 @@ func TestCreateExtTables_DDLContainsAutoColumns(t *testing.T) {
|
||||
t.Error("expected created_at to be populated by default")
|
||||
}
|
||||
}
|
||||
|
||||
// ── parseVectorDim ──────────────────────────────────────────────────────────
|
||||
|
||||
func TestParseVectorDim(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
dim int
|
||||
ok bool
|
||||
}{
|
||||
{"vector(384)", 384, true},
|
||||
{"vector(1)", 1, true},
|
||||
{"vector(4096)", 4096, true},
|
||||
{"Vector(128)", 128, true}, // case insensitive
|
||||
{"vector(0)", 0, false},
|
||||
{"vector(5000)", 0, false}, // exceeds 4096
|
||||
{"vector()", 0, false},
|
||||
{"vector(abc)", 0, false},
|
||||
{"text", 0, false},
|
||||
{"vector", 0, false},
|
||||
}
|
||||
for _, c := range cases {
|
||||
dim, ok := parseVectorDim(c.input)
|
||||
if ok != c.ok || dim != c.dim {
|
||||
t.Errorf("parseVectorDim(%q) = (%d, %v), want (%d, %v)", c.input, dim, ok, c.dim, c.ok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── mapColType vector ───────────────────────────────────────────────────────
|
||||
|
||||
func TestMapColType_VectorSQLite(t *testing.T) {
|
||||
got := mapColType("vector(384)", false, false)
|
||||
if got != "TEXT" {
|
||||
t.Errorf("vector on SQLite: got %q, want TEXT", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapColType_VectorPgNoPgvector(t *testing.T) {
|
||||
got := mapColType("vector(384)", true, false)
|
||||
if got != "JSONB" {
|
||||
t.Errorf("vector on PG without pgvector: got %q, want JSONB", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapColType_VectorPgvector(t *testing.T) {
|
||||
got := mapColType("vector(384)", true, true)
|
||||
if got != "vector(384)" {
|
||||
t.Errorf("vector on PG with pgvector: got %q, want vector(384)", got)
|
||||
}
|
||||
}
|
||||
|
||||
// ── CreateExtTables with vector column ──────────────────────────────────────
|
||||
|
||||
func TestCreateExtTables_VectorColumn(t *testing.T) {
|
||||
db := newSchemaTestDB(t)
|
||||
m := newMemExtDataStore()
|
||||
ctx := context.Background()
|
||||
|
||||
tables := map[string]TableDef{
|
||||
"docs": {
|
||||
Columns: map[string]string{"title": "text", "embedding": "vector(384)"},
|
||||
},
|
||||
}
|
||||
if err := CreateExtTables(ctx, db, false, storesWithExtData(m), "vec-pkg", tables, false); err != nil {
|
||||
t.Fatalf("CreateExtTables: %v", err)
|
||||
}
|
||||
|
||||
// Verify table exists and embedding is TEXT (SQLite fallback).
|
||||
_, err := db.ExecContext(ctx,
|
||||
`INSERT INTO ext_vec_pkg_docs (id, title, embedding) VALUES ('1', 'test', '[0.1,0.2]')`)
|
||||
if err != nil {
|
||||
t.Errorf("table not created or wrong schema: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user