diff --git a/packages/core/src/db/entity/postgresEntityStore.ts b/packages/core/src/db/entity/postgresEntityStore.ts index d9d1d6234..aeaacdec1 100644 --- a/packages/core/src/db/entity/postgresEntityStore.ts +++ b/packages/core/src/db/entity/postgresEntityStore.ts @@ -4,7 +4,7 @@ import { DerivedField, FieldKind, ScalarField, Schema } from "@/schema/types"; import type { EntityFilter, EntityStore } from "./entityStore"; import { - getColumnStatements, + getColumnValuePairs, getWhereValue, sqlSymbolsForFilterType, } from "./utils"; @@ -68,15 +68,17 @@ export class PostgresEntityStore implements EntityStore { // @ts-ignore instance.id = id; - const columnStatements = getColumnStatements(instance); + const pairs = getColumnValuePairs(instance); - const values = columnStatements.map((s) => s.value); - const insertFragment = `(${columnStatements - .map((s) => s.column) - .join(", ")}) VALUES (${values.map(() => "?").join(", ")})`; + const insertValues = pairs.map(({ value }) => value); + const insertFragment = `(${pairs + .map(({ column }) => column) + .join(", ")}) VALUES (${insertValues + .map((_, idx) => `$${idx + 1}`) + .join(", ")})`; const statement = `INSERT INTO "${entityName}" ${insertFragment} RETURNING *`; - const insertedEntity = await this.db.oneOrNone(statement, values); + const insertedEntity = await this.db.oneOrNone(statement, insertValues); return this.deserialize(entityName, insertedEntity); } @@ -90,21 +92,19 @@ export class PostgresEntityStore implements EntityStore { throw new Error(`EntityStore has not been initialized with a schema yet`); } - const columnStatements = getColumnStatements(instance); + const pairs = getColumnValuePairs(instance); - const updates = columnStatements - // Ignore `instance.id` field for update fragment - .filter(({ column }) => column !== "id"); - const values = updates.map((s) => s.value); - - const updateFragment = updates - .map(({ column }) => `${column} = ?`) + const updatePairs = pairs.filter(({ column }) => column !== "id"); + const updateValues = updatePairs.map(({ value }) => value); + const updateFragment = updatePairs + .map(({ column }, idx) => `${column} = $${idx + 1}`) .join(", "); - const statement = `UPDATE "${entityName}" SET ${updateFragment} WHERE "id" = ? RETURNING *`; - values.push(id); - - const updatedEntity = await this.db.oneOrNone(statement, values); + const statement = `UPDATE "${entityName}" SET ${updateFragment} WHERE "id" = $${ + updatePairs.length + 1 + } RETURNING *`; + updateValues.push(id); + const updatedEntity = await this.db.oneOrNone(statement, updateValues); return this.deserialize(entityName, updatedEntity); } @@ -124,19 +124,19 @@ export class PostgresEntityStore implements EntityStore { // @ts-ignore instance.id = id; - const columnStatements = getColumnStatements(instance); + const pairs = getColumnValuePairs(instance); - const insertValues = columnStatements.map((s) => s.value); - const insertFragment = `(${columnStatements - .map((s) => s.column) - .join(", ")}) VALUES (${insertValues.map(() => "?").join(", ")})`; + const insertValues = pairs.map(({ value }) => value); + const insertFragment = `(${pairs + .map(({ column }) => column) + .join(", ")}) VALUES (${insertValues + .map((_, idx) => `$${idx + 1}`) + .join(", ")})`; - const updates = columnStatements - // Ignore `instance.id` field for update fragment - .filter(({ column }) => column !== "id"); - const updateValues = updates.map((s) => s.value); - const updateFragment = updates - .map(({ column }) => `${column} = ?`) + const updatePairs = pairs.filter(({ column }) => column !== "id"); + const updateValues = updatePairs.map(({ value }) => value); + const updateFragment = updatePairs + .map(({ column }, idx) => `${column} = $${idx + 1 + insertValues.length}`) .join(", "); const statement = `INSERT INTO "${entityName}" ${insertFragment} ON CONFLICT("id") DO UPDATE SET ${updateFragment} RETURNING *`; @@ -191,8 +191,6 @@ export class PostgresEntityStore implements EntityStore { return `"${fieldName}" ${whereValue}`; }); - console.log({ whereFragments }); - fragments.push(`WHERE ${whereFragments.join(" AND ")}`); } diff --git a/packages/core/src/db/entity/sqliteEntityStore.ts b/packages/core/src/db/entity/sqliteEntityStore.ts index f924a70b9..644195544 100644 --- a/packages/core/src/db/entity/sqliteEntityStore.ts +++ b/packages/core/src/db/entity/sqliteEntityStore.ts @@ -5,7 +5,7 @@ import { DerivedField, FieldKind, ScalarField, Schema } from "@/schema/types"; import { EntityFilter, EntityStore } from "./entityStore"; import { - getColumnStatements, + getColumnValuePairs, getWhereValue, sqlSymbolsForFilterType, } from "./utils"; @@ -108,16 +108,16 @@ export class SqliteEntityStore implements EntityStore { // @ts-ignore instance.id = id; - const columnStatements = getColumnStatements(instance); + const pairs = getColumnValuePairs(instance); - const values = columnStatements.map((s) => s.value); - const insertFragment = `(${columnStatements + const insertValues = pairs.map((s) => s.value); + const insertFragment = `(${pairs .map((s) => s.column) - .join(", ")}) VALUES (${values.map(() => "?").join(", ")})`; + .join(", ")}) VALUES (${insertValues.map(() => "?").join(", ")})`; const statement = `INSERT INTO "${entityName}" ${insertFragment} RETURNING *`; - const insertedEntity = this.db.prepare(statement).get(...values); + const insertedEntity = this.db.prepare(statement).get(...insertValues); return this.deserialize(entityName, insertedEntity); } catch (err) { @@ -142,21 +142,18 @@ export class SqliteEntityStore implements EntityStore { ); } - const columnStatements = getColumnStatements(instance); - - const updates = columnStatements - // Ignore `instance.id` field for update fragment - .filter(({ column }) => column !== "id"); - const values = updates.map((s) => s.value); + const pairs = getColumnValuePairs(instance); - const updateFragment = updates + const updatePairs = pairs.filter(({ column }) => column !== "id"); + const updateValues = updatePairs.map(({ value }) => value); + const updateFragment = updatePairs .map(({ column }) => `${column} = ?`) .join(", "); const statement = `UPDATE "${entityName}" SET ${updateFragment} WHERE "id" = ? RETURNING *`; - values.push(id); + updateValues.push(`${id}`); - const updatedEntity = this.db.prepare(statement).get(...values); + const updatedEntity = this.db.prepare(statement).get(...updateValues); return this.deserialize(entityName, updatedEntity); } catch (err) { @@ -187,18 +184,16 @@ export class SqliteEntityStore implements EntityStore { // @ts-ignore instance.id = id; - const columnStatements = getColumnStatements(instance); + const pairs = getColumnValuePairs(instance); - const insertValues = columnStatements.map((s) => s.value); - const insertFragment = `(${columnStatements + const insertValues = pairs.map((s) => s.value); + const insertFragment = `(${pairs .map((s) => s.column) .join(", ")}) VALUES (${insertValues.map(() => "?").join(", ")})`; - const updates = columnStatements - // Ignore `instance.id` field for update fragment - .filter(({ column }) => column !== "id"); - const updateValues = updates.map((s) => s.value); - const updateFragment = updates + const updatePairs = pairs.filter(({ column }) => column !== "id"); + const updateValues = updatePairs.map(({ value }) => value); + const updateFragment = updatePairs .map(({ column }) => `${column} = ?`) .join(", "); diff --git a/packages/core/src/db/entity/utils.ts b/packages/core/src/db/entity/utils.ts index aa76e94d5..05f782168 100644 --- a/packages/core/src/db/entity/utils.ts +++ b/packages/core/src/db/entity/utils.ts @@ -91,7 +91,7 @@ export const getWhereValue = ( // Accepts an instance being passed to `insert`, `update`, or `upsert` and // returns a list of column names and values to be persisted. -export const getColumnStatements = (instance: Record) => { +export const getColumnValuePairs = (instance: Record) => { return Object.entries(instance) .map(([fieldName, value]) => { let persistedValue: number | string | null; @@ -100,7 +100,7 @@ export const getColumnStatements = (instance: Record) => { } else if (typeof value === "undefined") { persistedValue = null; } else { - persistedValue = `'${value}'`; + persistedValue = value as number | string | null; } return { @@ -108,5 +108,12 @@ export const getColumnStatements = (instance: Record) => { value: persistedValue, }; }) - .filter(({ value }) => value !== null); + .filter( + ( + col + ): col is { + column: string; + value: string | number; + } => col.value !== null + ); };