Skip to content

Commit

Permalink
packages/modeldb: remove primitive property type
Browse files Browse the repository at this point in the history
  • Loading branch information
joeltg committed Jan 16, 2025
1 parent 7412cc9 commit c18ee7c
Show file tree
Hide file tree
Showing 17 changed files with 158 additions and 537 deletions.
81 changes: 19 additions & 62 deletions packages/modeldb-durable-objects/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,15 @@ import {
WhereCondition,
PrimitiveValue,
RangeExpression,
PrimaryKeyProperty,
isNotExpression,
isLiteralExpression,
isRangeExpression,
isPrimitiveValue,
validateModelValue,
PrimitiveProperty,
} from "@canvas-js/modeldb"

import { zip } from "@canvas-js/utils"

import {
decodePrimaryKeyValue,
decodePrimitiveValue,
decodeRecord,
decodeReferenceValue,
Expand All @@ -45,10 +42,13 @@ const primitiveColumnTypes = {
json: "TEXT",
} satisfies Record<PrimitiveType, string>

function getPropertyColumnType(property: Property): string {
if (property.kind === "primary") {
return "TEXT PRIMARY KEY NOT NULL"
} else if (property.kind === "primitive") {
function getPropertyColumnType(model: Model, property: Property): string {
if (property.kind === "primitive") {
if (property.name === model.primaryKey) {
assert(property.type === "string")
assert(property.nullable === false)
return "TEXT PRIMARY KEY NOT NULL"
}
const type = primitiveColumnTypes[property.type]
return property.nullable ? type : `${type} NOT NULL`
} else if (property.kind === "reference") {
Expand All @@ -60,7 +60,8 @@ function getPropertyColumnType(property: Property): string {
}
}

const getPropertyColumn = (property: Property) => `'${property.name}' ${getPropertyColumnType(property)}`
const getPropertyColumn = (model: Model, property: Property) =>
`'${property.name}' ${getPropertyColumnType(model, property)}`

export class ModelAPI {
// #table = this.model.name
Expand Down Expand Up @@ -92,13 +93,14 @@ export class ModelAPI {
const columns: string[] = []
this.columnNames = [] // quoted column names for non-relation properties
let primaryKeyIndex: number | null = null
let primaryKey: PrimaryKeyProperty | null = null
let primaryKey: PrimitiveProperty | null = null
for (const [i, property] of model.properties.entries()) {
if (property.kind === "primary" || property.kind === "primitive" || property.kind === "reference") {
columns.push(getPropertyColumn(property))
if (property.kind === "primitive" || property.kind === "reference") {
columns.push(getPropertyColumn(model, property))
this.columnNames.push(`"${property.name}"`)

if (property.kind === "primary") {
if (property.name === model.primaryKey) {
assert(property.kind === "primitive")
primaryKeyIndex = i
primaryKey = property
}
Expand Down Expand Up @@ -292,9 +294,7 @@ export class ModelAPI {
const value: ModelValue = {}
for (const [propertyName, propertyValue] of Object.entries(record)) {
const property = this.#properties[propertyName]
if (property.kind === "primary") {
value[propertyName] = decodePrimaryKeyValue(this.model.name, property, propertyValue)
} else if (property.kind === "primitive") {
if (property.kind === "primitive") {
value[propertyName] = decodePrimitiveValue(this.model.name, property, propertyValue)
} else if (property.kind === "reference") {
value[propertyName] = decodeReferenceValue(this.model.name, property, propertyValue)
Expand Down Expand Up @@ -382,7 +382,7 @@ export class ModelAPI {

const property = this.#properties[name]
assert(property !== undefined, "property not found")
if (property.kind === "primary" || property.kind === "primitive" || property.kind === "reference") {
if (property.kind === "primitive" || property.kind === "reference") {
columns.push(`"${name}"`)
} else if (property.kind === "relation") {
relations.push({
Expand Down Expand Up @@ -411,52 +411,9 @@ export class ModelAPI {
return []
}

if (property.kind === "primary") {
if (isLiteralExpression(expression)) {
if (typeof expression !== "string") {
throw new TypeError("invalid primary key value (expected string)")
}

params.push(expression)
return [`"${name}" = ?`]
} else if (isNotExpression(expression)) {
const { neq: value } = expression
if (typeof value !== "string") {
throw new TypeError("invalid primary key value (expected string)")
}

params.push(value)
return [`"${name}" != ?`]
} else if (isRangeExpression(expression)) {
const keys = Object.keys(expression) as (keyof RangeExpression)[]

return keys
.filter((key) => expression[key] !== undefined)
.flatMap((key, j) => {
const value = expression[key]
if (typeof value !== "string") {
throw new TypeError("invalid primary key value (expected string)")
}
if (property.kind === "primitive") {
assert(property.type !== "json", "json properties are not supported in where clauses")

params.push(value)
switch (key) {
case "gt":
return [`"${name}" > ?`]
case "gte":
return [`"${name}" >= ?`]
case "lt":
return [`"${name}" < ?`]
case "lte":
return [`"${name}" <= ?`]
}
})
} else {
signalInvalidType(expression)
}
} else if (property.kind === "primitive") {
if (property.type === "json") {
throw new Error("json properties are not supported in where clauses")
}
if (isLiteralExpression(expression)) {
if (expression === null) {
return [`"${name}" ISNULL`]
Expand Down
29 changes: 2 additions & 27 deletions packages/modeldb-durable-objects/src/encoding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import * as json from "@ipld/dag-json"
import type {
Model,
ModelValue,
PrimaryKeyProperty,
PrimaryKeyValue,
PrimitiveProperty,
PrimitiveValue,
PropertyValue,
Expand Down Expand Up @@ -43,9 +41,7 @@ export function encodeRecordParams(
throw new Error(`missing value for property ${model.name}/${property.name}`)
}

if (property.kind === "primary") {
result.push(encodePrimaryKeyValue(model.name, property, value[property.name]))
} else if (property.kind === "primitive") {
if (property.kind === "primitive") {
result.push(encodePrimitiveValue(model.name, property, value[property.name]))
} else if (property.kind === "reference") {
result.push(encodeReferenceValue(model.name, property, value[property.name]))
Expand All @@ -60,13 +56,6 @@ export function encodeRecordParams(

return result
}
function encodePrimaryKeyValue(modelName: string, property: PrimaryKeyProperty, value: PropertyValue): string {
if (typeof value === "string") {
return value
} else {
throw new TypeError(`${modelName}/${property.name} must be a string`)
}
}

function encodePrimitiveValue(
modelName: string,
Expand Down Expand Up @@ -144,9 +133,7 @@ export function decodeRecord(
const value: ModelValue = {}

for (const property of model.properties) {
if (property.kind === "primary") {
value[property.name] = decodePrimaryKeyValue(model.name, property, record[property.name])
} else if (property.kind === "primitive") {
if (property.kind === "primitive") {
value[property.name] = decodePrimitiveValue(model.name, property, record[property.name])
} else if (property.kind === "reference") {
value[property.name] = decodeReferenceValue(model.name, property, record[property.name])
Expand All @@ -160,18 +147,6 @@ export function decodeRecord(
return value
}

export function decodePrimaryKeyValue(
modelName: string,
property: PrimaryKeyProperty,
value: string | number | Buffer | ArrayBuffer | null,
): PrimaryKeyValue {
if (typeof value !== "string") {
throw new Error(`internal error - invalid ${modelName}/${property.name} value (expected string)`)
}

return value
}

export function decodePrimitiveValue(modelName: string, property: PrimitiveProperty, value: SqlitePrimitiveValue) {
if (value === null) {
if (property.nullable) {
Expand Down
6 changes: 3 additions & 3 deletions packages/modeldb-idb/src/ModelDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ export class ModelDB extends AbstractModelDB {
// create missing object stores
const storeNames = new Set(db.objectStoreNames)
for (const model of config.models) {
const primaryKey = model.properties.find((property) => property.kind === "primary")
assert(primaryKey !== undefined, "expected primaryKey !== undefined")
// const primaryKey = model.properties.find((property) => property.kind === "primary")
// assert(primaryKey !== undefined, "expected primaryKey !== undefined")

if (storeNames.has(model.name)) {
continue
}

const recordObjectStore = db.createObjectStore(model.name, { keyPath: primaryKey.name })
const recordObjectStore = db.createObjectStore(model.name, { keyPath: model.primaryKey })

for (const index of model.indexes) {
const keyPath = index.length === 1 ? index[0] : index
Expand Down
9 changes: 2 additions & 7 deletions packages/modeldb-idb/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,7 @@ export class ModelAPI {
}

function encodePropertyValue(property: Property, propertyValue: PropertyValue): PropertyValue | PropertyValue[] {
if (property.kind === "primary") {
return propertyValue
} else if (property.kind === "primitive") {
if (property.kind === "primitive") {
if (property.nullable) {
assert(property.type !== "json")
return propertyValue === null ? [] : [propertyValue]
Expand All @@ -537,10 +535,7 @@ function encodePropertyValue(property: Property, propertyValue: PropertyValue):
}

function decodePropertyValue(property: Property, objectPropertyValue: PropertyValue | PropertyValue[]): PropertyValue {
if (property.kind === "primary") {
assert(typeof objectPropertyValue === "string", 'expected objectPropertyValue === "string"')
return objectPropertyValue
} else if (property.kind === "primitive") {
if (property.kind === "primitive") {
if (property.nullable) {
assert(property.type !== "json")
assert(Array.isArray(objectPropertyValue))
Expand Down
Loading

0 comments on commit c18ee7c

Please sign in to comment.