Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
benmerckx committed Sep 10, 2024
2 parents 596512d + a1bcef3 commit 3aa0be0
Show file tree
Hide file tree
Showing 35 changed files with 579 additions and 392 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: ci

on:
push:
branches: [main, v1]
branches: [main]
tags: [v*]
pull_request:
branches: [main]
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[![npm](https://img.shields.io/npm/v/rado.svg)](https://npmjs.org/package/rado)
[![jsr](https://jsr.io/badges/@rado/rado)](https://jsr.io/@rado/rado)

# rado

Expand Down
4 changes: 2 additions & 2 deletions build.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {build, type Plugin} from 'esbuild'
import glob from 'glob'
import {type Plugin, build} from 'esbuild'
import {glob} from 'glob'
import {readFileSync, writeFileSync} from 'node:fs'

const entryPoints = process.env.PROFILE ? '{src,test}/**/*.ts' : 'src/**/*.ts'
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rado/rado",
"version": "1.0.8",
"version": "1.0.9",
"publish": {
"include": ["README.md", "LICENSE", "src"]
},
Expand Down
35 changes: 16 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rado",
"version": "1.0.8",
"version": "1.0.9",
"license": "MIT",
"type": "module",
"scripts": {
Expand All @@ -26,30 +26,27 @@
},
"files": ["dist"],
"devDependencies": {
"@benmerckx/suite": "^0.3.0",
"@biomejs/biome": "^1.8.3",
"@cloudflare/workers-types": "^4.20230628.0",
"@electric-sql/pglite": "^0.1.5",
"@sqlite.org/sqlite-wasm": "^3.42.0-build4",
"@types/better-sqlite3": "^5.4.1",
"@types/bun": "^1.1.6",
"@types/glob": "^8.0.0",
"@types/pg": "^8.11.5",
"@types/sql.js": "^1.4.2",
"better-sqlite3": "^11.0.0",
"esbuild": "^0.18.11",
"glob": "^8.0.3",
"@types/better-sqlite3": "^7.6.11",
"@types/bun": "^1.1.8",
"@types/glob": "^8.1.0",
"@types/pg": "^8.11.8",
"@types/sql.js": "^1.4.9",
"better-sqlite3": "^11.2.1",
"esbuild": "^0.23.1",
"glob": "^11.0.0",
"madge": "^8.0.0",
"mysql2": "^3.9.7",
"pg": "^8.11.5",
"rimraf": "^4.1.2",
"sade": "^1.8.1",
"mysql2": "^3.11.0",
"pg": "^8.12.0",
"speedscope": "^1.15.0",
"sql.js": "^1.8.0",
"sqlite3": "^5.1.6",
"tsx": "^4.7.2",
"typescript": "^5.4.5",
"uvu": "^0.5.6",
"sql.js": "^1.11.0",
"sqlite3": "^5.1.7",
"tsx": "^4.19.0",
"typescript": "^5.5.4",
"@alinea/suite": "^0.4.0",
"@db/sqlite": "npm:@jsr/db__sqlite"
}
}
8 changes: 5 additions & 3 deletions src/core/Column.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type {DriverSpecs} from './Driver.ts'
import {getData, getField, internalData} from './Internal.ts'
import {type Sql, sql} from './Sql.ts'
import {sql, type Sql} from './Sql.ts'
import type {Field, FieldData} from './expr/Field.ts'
import {type Input, input} from './expr/Input.ts'
import {input, type Input} from './expr/Input.ts'

export interface ColumnData {
type: Sql
Expand Down Expand Up @@ -107,7 +107,9 @@ export interface Columns {
export const column: Columns = new Proxy(createColumn as any, {
get(target: Record<string, Function>, method: string) {
return (target[method] ??= (...args: Array<Input<unknown>>) => {
while (args.length > 0) if (args.at(-1) === undefined) args.pop()
while (args.length > 0)
if (args.at(-1) === undefined) args.pop()
else break
if (args.length === 0) return sql.unsafe(method)
return sql`${sql.unsafe(method)}(${sql.join(
args.map(sql.inline),
Expand Down
9 changes: 5 additions & 4 deletions src/core/expr/Json.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {type HasSql, getSql} from '../Internal.ts'
import {type Sql, sql} from '../Sql.ts'
import {getSql, type HasSql} from '../Internal.ts'
import {sql, type Sql} from '../Sql.ts'
import {callFunction} from './Functions.ts'
import type {Input} from './Input.ts'

Expand Down Expand Up @@ -52,8 +52,9 @@ export function jsonExpr<Value>(e: HasSql<Value>): JsonExpr<Value> {
export function jsonAggregateArray(...args: Array<Input<unknown>>) {
return callFunction(
sql.universal({
// Once sqlite 3.45+ is more commonplace we can use jsonb_group_array
sqlite: sql`json_group_array`,
postgres: sql`json_agg`,
postgres: sql`jsonb_agg`,
mysql: sql`json_arrayagg`
}),
args
Expand All @@ -63,7 +64,7 @@ export function jsonAggregateArray(...args: Array<Input<unknown>>) {
export function jsonArray(...args: Array<Input<unknown>>) {
return callFunction(
sql.universal({
postgres: sql`json_build_array`,
postgres: sql`jsonb_build_array`,
default: sql`json_array`
}),
args
Expand Down
5 changes: 3 additions & 2 deletions src/driver/better-sqlite3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {execTransaction} from '../sqlite/transactions.ts'

class PreparedStatement implements SyncStatement {
constructor(
private stmt: Statement<Array<unknown>>,
private stmt: Statement,
private isSelection: boolean
) {}

Expand All @@ -29,7 +29,8 @@ class PreparedStatement implements SyncStatement {
}

values(params: Array<unknown>) {
if (this.isSelection) return this.stmt.raw(true).all(...params)
if (this.isSelection)
return this.stmt.raw(true).all(...params) as Array<Array<unknown>>
this.stmt.run(...params)
return []
}
Expand Down
15 changes: 12 additions & 3 deletions src/driver/mysql2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,19 @@ class PreparedStatement implements AsyncStatement {
private name?: string
) {}

#transformParam = (param: unknown) => {
if (param instanceof Uint8Array) return Buffer.from(param)
return param
}

all(params: Array<unknown>): Promise<Array<object>> {
return this.client
.query(this.sql, params)
.query(this.sql, params.map(this.#transformParam))
.then(res => res[0] as Array<object>)
}

async run(params: Array<unknown>) {
await this.client.query(this.sql, params)
await this.client.query(this.sql, params.map(this.#transformParam))
}

get(params: Array<unknown>): Promise<object> {
Expand All @@ -40,7 +45,11 @@ class PreparedStatement implements AsyncStatement {

values(params: Array<unknown>): Promise<Array<Array<unknown>>> {
return this.client
.query({sql: this.sql, values: params, rowsAsArray: true})
.query({
sql: this.sql,
values: params.map(this.#transformParam),
rowsAsArray: true
})
.then(res => res[0] as Array<Array<unknown>>)
}

Expand Down
6 changes: 5 additions & 1 deletion src/mysql/columns.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type Column, JsonColumn, column} from '../core/Column.ts'
import {JsonColumn, column, type Column} from '../core/Column.ts'

type Precision = 0 | 1 | 2 | 3 | 4 | 5 | 6

Expand Down Expand Up @@ -32,6 +32,10 @@ export function boolean(name?: string): Column<boolean | null> {
return column({name, type: column.boolean()})
}

export function blob(name?: string): Column<Uint8Array | null> {
return column({name, type: column.blob()})
}

export function char(
name?: string,
options?: {length: number}
Expand Down
6 changes: 3 additions & 3 deletions src/postgres/columns.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type Column, JsonColumn, column} from '../core/Column.ts'
import {JsonColumn, column, type Column} from '../core/Column.ts'

type Precision = 0 | 1 | 2 | 3 | 4 | 5 | 6
type IntervalFields =
Expand Down Expand Up @@ -121,8 +121,8 @@ export function boolean(name?: string): Column<boolean | null> {
return column({name, type: column.boolean()})
}

export function blob(name?: string): Column<Uint8Array | null> {
return column({name, type: column.blob()})
export function bytea(name?: string): Column<Uint8Array | null> {
return column({name, type: column.bytea()})
}

export function text(name?: string): Column<string | null> {
Expand Down
50 changes: 45 additions & 5 deletions src/universal/columns.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type Column, JsonColumn, column} from '../core/Column.ts'
import {JsonColumn, column, type Column} from '../core/Column.ts'
import {sql} from '../core/Sql.ts'

const idType = sql.universal({
Expand All @@ -7,6 +7,21 @@ const idType = sql.universal({
mysql: sql`int not null auto_increment`
})

const blobType = sql.universal({
postgres: sql`bytea`,
default: sql`blob`
})

const numberType = sql.universal({
mysql: sql`double`,
default: sql`numeric`
})

const jsonbType = sql.universal({
mysql: sql`json`,
default: sql`jsonb`
})

export function id(name?: string): Column<number> {
return column({
name,
Expand All @@ -19,18 +34,26 @@ export function text(name?: string): Column<string | null> {
return column({name, type: column.text()})
}

export function varchar(
name?: string,
options?: {length: number}
): Column<string | null> {
return column({name, type: column.varchar(options?.length)})
}

export function integer(name?: string): Column<number | null> {
return column({name, type: column.integer()})
}

export function number(name?: string): Column<number | null> {
return column({name, type: numberType, mapFromDriverValue: Number})
}

export function boolean(name?: string): Column<boolean | null> {
return column({
name,
type: column.boolean(),
mapFromDriverValue(value: unknown): boolean {
if (typeof value === 'number') return value === 1
return Boolean(value)
}
mapFromDriverValue: Boolean
})
}

Expand All @@ -46,3 +69,20 @@ export function json<T>(name?: string): JsonColumn<T> {
}
})
}

export function jsonb<T>(name?: string): JsonColumn<T> {
return new JsonColumn({
name,
type: jsonbType,
mapToDriverValue(value: T): string {
return JSON.stringify(value)
},
mapFromDriverValue(value: unknown, {parsesJson}) {
return parsesJson ? value : JSON.parse(value as string)
}
})
}

export function blob(name?: string): Column<Uint8Array | null> {
return column({name, type: blobType})
}
33 changes: 14 additions & 19 deletions test/TestDriver.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import {type DefineTest, suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import type {Database} from '../src/core/Database.ts'
import {testBasic} from './integration/TestBasic.ts'
import {testCTE} from './integration/TestCTE.ts'
import {testColumns} from './integration/TestColumns.ts'
import {testConstraints} from './integration/TestConstraints.ts'
import {testInclude} from './integration/TestInclude.ts'
import {testJoins} from './integration/TestJoins.ts'
import {testJson} from './integration/TestJson.ts'
import {testMigration} from './integration/TestMigration.ts'
import {testPreparedQuery} from './integration/TestPreparedQuery.ts'
import {testSubquery} from './integration/TestSubquery.ts'
import {
testGeneratorTransactions,
testTransactions
} from './integration/TestTransactions.ts'
import {testTransactions} from './integration/TestTransactions.ts'

export async function testDriver(
meta: ImportMeta,
Expand All @@ -21,20 +19,17 @@ export async function testDriver(
) {
const db = await createDb()
suite(meta, test => {
const bind = (fn: (db: Database, test: DefineTest) => void) =>
fn.bind(null, db, test)
testBasic(db, test)
testColumns(db, test)
testSubquery(db, test)
testPreparedQuery(db, test)
testJoins(db, test)
testJson(db, test)
testTransactions(db, test)
testConstraints(db, test)
testCTE(db, test)
testInclude(db, test)

test('basics', bind(testBasic))
test('subquery', bind(testSubquery))
test('prepared queries', bind(testPreparedQuery))
test('joins', bind(testJoins))
test('json fields', bind(testJson))
test('transactions', bind(testTransactions))
test('generator transactions', bind(testGeneratorTransactions))
test('constraints and indexes', bind(testConstraints))
test('recursive cte', bind(testCTE))
test('include', bind(testInclude))

if (supportsDiff) test('migrate', bind(testMigration))
if (supportsDiff) testMigration(db, test)
})
}
2 changes: 1 addition & 1 deletion test/core/Expr.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as e from '@/core/expr/Conditions.ts'
import {jsonExpr} from '@/core/expr/Json.ts'
import {sql} from '@/index.ts'
import {suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import {builder, emit} from '../TestUtils.ts'

suite(import.meta, test => {
Expand Down
2 changes: 1 addition & 1 deletion test/core/Selection.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {selection, sql} from '@/index.ts'
import {suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import {emit} from '../TestUtils.ts'

suite(import.meta, test => {
Expand Down
2 changes: 1 addition & 1 deletion test/core/Sql.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {sql} from '@/core/Sql.ts'
import {suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import {emit} from '../TestUtils.ts'

suite(import.meta, test => {
Expand Down
2 changes: 1 addition & 1 deletion test/core/SqliteFunctions.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {table} from '@/index.ts'
import {integer} from '@/sqlite/columns.ts'
import {bm25, cast} from '@/sqlite/functions.ts'
import {suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import {emit} from '../TestUtils.ts'

suite(import.meta, test => {
Expand Down
2 changes: 1 addition & 1 deletion test/core/Table.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {table} from '@/core/Table.ts'
import {integer} from '@/sqlite/columns.ts'
import {suite} from '@benmerckx/suite'
import {suite} from '@alinea/suite'
import {emit} from '../TestUtils.ts'

suite(import.meta, test => {
Expand Down
Loading

0 comments on commit 3aa0be0

Please sign in to comment.