Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: reduce operations when syncTable using schema #1

Merged
merged 42 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
520695a
wip
subframe7536 Oct 7, 2024
9e4816c
wip: updates sql
subframe7536 Oct 8, 2024
25477db
wip: improve parse exist db
subframe7536 Oct 8, 2024
96e0901
wip: index
subframe7536 Oct 8, 2024
f399c18
wip: tsdown config
subframe7536 Oct 8, 2024
8fed888
wip: extract parseDefaultValue
subframe7536 Oct 10, 2024
72c175a
wip: todo
subframe7536 Oct 10, 2024
07c1f9e
wip: remove constraint and upgrade deps
subframe7536 Oct 10, 2024
e538909
wip: index
subframe7536 Oct 10, 2024
1e65c61
wip: parse exists
subframe7536 Oct 11, 2024
6f7b8d9
Merge branch 'main' into fix-schema
subframe7536 Oct 11, 2024
96ef05b
wip
subframe7536 Oct 11, 2024
fd67650
chore: rollback to tsup
subframe7536 Oct 11, 2024
876052a
wip: reuse parseDefaultValue
subframe7536 Oct 12, 2024
0b2a7ad
wip: handle unique, index, trigger
subframe7536 Oct 14, 2024
165f0c4
wip: test
subframe7536 Oct 15, 2024
ac06bfe
wip: improve column definition type
subframe7536 Oct 17, 2024
5643ea6
wip
subframe7536 Oct 17, 2024
bb412fd
wip
subframe7536 Oct 17, 2024
fc9a107
wip: optimize trigger
subframe7536 Oct 18, 2024
b43ab07
wip: always use rowid as trigger key, throw error when multiple pk
subframe7536 Oct 18, 2024
52d3d6c
wip: logs
subframe7536 Oct 18, 2024
08c532b
wip: test pass
subframe7536 Oct 18, 2024
0b9d05d
wip: tests
subframe7536 Oct 18, 2024
11b07f0
wip: improve types
subframe7536 Oct 18, 2024
524cd57
wip: check multi auto increment
subframe7536 Oct 18, 2024
414003d
wip
subframe7536 Oct 19, 2024
f97fd17
wip
subframe7536 Oct 19, 2024
c7db3be
wip
subframe7536 Oct 20, 2024
a440f32
wip
subframe7536 Oct 20, 2024
104a763
wip: update jsdoc
subframe7536 Oct 20, 2024
1bd8f2d
wip: optimizeDB
subframe7536 Oct 21, 2024
2b256f0
wip: exports
subframe7536 Oct 22, 2024
2244196
wip
subframe7536 Oct 23, 2024
822533d
wip: fix pk check
subframe7536 Oct 23, 2024
e812a3a
wip
subframe7536 Oct 23, 2024
e9e4cd5
wip: more exports
subframe7536 Oct 23, 2024
9edd33d
wip: fix restore data
subframe7536 Oct 25, 2024
bc61011
wip: improve logs
subframe7536 Oct 25, 2024
ede3e75
wip: structure
subframe7536 Oct 25, 2024
7b4ce15
wip: replaceInto
subframe7536 Oct 25, 2024
9033eda
wip: docs
subframe7536 Oct 25, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
190 changes: 155 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ const testTable = defineTable({
literal: column.string().$cast<'l1' | 'l2'>(),
buffer: column.blob(),
},
primary: 'id',
primary: 'id', // optional
index: ['person', ['id', 'gender']],
timeTrigger: { create: true, update: true },
unique: [['id', 'gender']],
// these params will auto add columns into table
createAt: true, // `createTime` column
updateAt: true, // `updateTime` column
softDelete: true, // `isDeleted` column
})

const DBSchema = {
Expand All @@ -79,44 +83,93 @@ sync options type:
```ts
export type SyncOptions<T extends Schema> = {
/**
* whether to enable debug logger
* Whether to enable debug logger
*/
log?: boolean
/**
* version control
* Version control
*/
version?: {
/**
* current version
* Current version
*/
current: number
/**
* whether to skip sync when the db's `user_version` is same with `version.current`
* Whether to skip sync when the db's `user_version` is same with `version.current`
*/
skipSyncWhenSame: boolean
}
/**
* exclude table prefix list, append with `%`
* Exclude table prefix list, append with `%`
*
* `sqlite_%` by default
*/
excludeTablePrefix?: string[]
/**
* do not restore data from old table to new table
* Do not restore data from old table to new table
*/
truncateIfExists?: boolean | Array<StringKeys<T> | string & {}>
/**
* trigger on sync success
* Function to determine default values for migrated columns,
* default is {@link defaultFallbackFunction}
*/
fallback?: ColumnFallbackFn
/**
* Trigger on sync success
* @param db kysely instance
* @param oldSchema old database schema
* @param oldVersion old database version
*/
onSyncSuccess?: (db: Kysely<InferDatabase<T>>) => Promisable<void>
onSuccess?: (
db: Kysely<InferDatabase<T>>,
oldSchema: ParsedSchema,
oldVersion: number | undefined
) => Promisable<void>
/**
* trigger on sync fail
* Trigger on sync fail
* @param err error
* @param sql failed sql, if `undefined`, there exists some errors in schema
* @param existSchema old database schema
* @param targetSchema new database schema
*/
onSyncFail?: (err: unknown) => Promisable<void>
onError?: (err: unknown, sql: string | undefined, existSchema: ParsedSchema, targetSchema: T) => Promisable<void>
}

type ColumnFallbackFn = (data: ColumnFallbackInfo) => RawBuilder<unknown>

export type ColumnFallbackInfo = {
/**
* Table name
*/
table: string
/**
* Column name
*/
column: string
/**
* Exist column info, `undefined` if there is no exising column with same target name
*/
exist: ParsedColumnProperty | undefined
/**
* Target column info
*/
target: Omit<ParsedColumnProperty, 'type'> & {
/**
* {@link DataType} in schema
*/
type: DataTypeValue
/**
* DataType in SQLite
*/
parsedType: ParsedColumnType
}
}
```

#### Limitation of Schema

No `check` or `foreign key` support

### Execute Queries

```ts
Expand All @@ -134,7 +187,7 @@ db.transaction(async (trx) => {
})
})

// use origin instance: Kysely or Transaction
// use origin instance: Kysely or current Transaction
await db.kysely.insertInto('test').values({ gender: false }).execute()

// run raw sql
Expand Down Expand Up @@ -192,7 +245,7 @@ const softDeleteTable = defineTable({
const softDeleteSchema = {
testSoftDelete: softDeleteTable,
}
const { executor, withNoDelete } = createSoftDeleteExecutor()
const { executor, whereExists, whereDeleted } = createSoftDeleteExecutor()

const db = new SqliteBuilder<InferDatabase<typeof softDeleteSchema>>({
dialect: new SqliteDialect({
Expand All @@ -205,16 +258,17 @@ const db = new SqliteBuilder<InferDatabase<typeof softDeleteSchema>>({
await db.deleteFrom('testSoftDelete').where('id', '=', 1).execute()
// update "testSoftDelete" set "isDeleted" = 1 where "id" = 1

await db.kysely.selectFrom('testSoftDelete').selectAll().$call(withNoDelete).execute()
// If you are using original kysely instance:
await db.kysely.selectFrom('testSoftDelete').selectAll().$call(whereExists).execute()
```

### Page Query

page query, using offset

if num <= 0 or size <= 0, return all records
if `num <= 0` or `size <= 0`, return all records

inspired by Mybatis-Plus PaginationInnerInterceptor
inspired by Mybatis-Plus `PaginationInnerInterceptor`

```ts
import { pageQuery } from 'kysely-sqlite-builder'
Expand All @@ -233,27 +287,19 @@ const page = await pageQuery(db.selectFrom('test').selectAll(), { num: 1, size:
console.log(page.convertRecords(p => p.literal).records)
```

### Util

```ts
import { createSoftDeleteSqliteBuilder, createSqliteBuilder } from 'kysely-sqlite-builder'

const db = await createSqliteBuilder({
dialect,
schema: { test: testTable },
// other options
})

const [softDeleteDB, withNoDelete] = createSoftDeleteSqliteBuilder({
dialect,
schema: { test: testTable },
})
```

### Pragma
### Pragma / Utils

```ts
type KyselyInstance = DatabaseConnection | Kysely<any> | Transaction<any>
/**
* Execute compiled query and return result list
*/
function executeSQL<O>(kysely: KyselyInstance, query: CompiledQuery<O>): Promise<QueryResult<O>>
/**
* Execute sql string
*/
function executeSQL<O>(kysely: KyselyInstance, rawSql: string, parameters?: unknown[]): Promise<QueryResult<O>>

/**
* check integrity_check pragma
*/
Expand All @@ -264,6 +310,8 @@ function checkIntegrity(db: KyselyInstance): Promise<boolean>
function foreignKeys(db: KyselyInstance, enable: boolean): Promise<void>
/**
* get or set user_version pragma, **no param check**
*
* `version` must be integer
*/
function getOrSetDBVersion(db: KyselyInstance, version?: number): Promise<number>

Expand Down Expand Up @@ -319,6 +367,78 @@ function optimizePragma(db: KyselyInstance, options?: OptimizePragmaOptions): Pr
function optimizeSize(db: KyselyInstance, rebuild?: boolean): Promise<QueryResult<unknown>>
```

#### Generate Migrate SQL

```ts
import { generateMigrateSQL } from 'kysely-sqlite-buidler/schema'

const db = new Kysely({/* options */})
const testTable = defineTable({
columns: {
id: column.increments(),
person: column.object({ defaultTo: { name: 'test' } }),
gender: column.boolean({ notNull: true }),
// or just object
manual: { type: DataType.boolean },
array: column.object().$cast<string[]>(),
literal: column.string().$cast<'l1' | 'l2'>(),
buffer: column.blob(),
},
primary: 'id', // optional
index: ['person', ['id', 'gender']],
createAt: true, // `createTime` column
updateAt: true, // `updateTime` column
})

await generateMigrateSQL(db, { test: testTable }, {/* options */})
```

More cases: [tests/sync-sql.test.ts](tests/sync-sql.test.ts)

#### Parse Exist Database

```ts
import { parseExistSchema } from 'kysely-sqlite-builder/schema'

const schema = await parseExistSchema(db.kysely)
```

type:

```ts
type ParsedSchema = Record<string, ParsedTableInfo>

type ParsedTableInfo = {
columns: Record<string, ParsedColumnProperty>
/**
* Primary key constraint
*/
primary: string[]
/**
* Unique constraint
*/
unique: string[][]
/**
* Index
*/
index: string[][]
/**
* Trigger
*/
trigger: string[]
/**
* Auto increment column name
*/
increment?: string
}

type ParsedColumnProperty = {
type: ParsedColumnType
notNull: boolean
defaultTo: string | null
}
```

### Migrate By Code

```ts
Expand Down
Binary file modified bun.lockb
100644 → 100755
Binary file not shown.
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@
"kysely-plugin-serialize": "^0.6.3"
},
"devDependencies": {
"@subframe7536/eslint-config": "^0.9.4",
"@subframe7536/eslint-config": "^0.9.5",
"@subframe7536/type-utils": "^0.1.6",
"@types/bun": "^1.1.10",
"bumpp": "^9.5.2",
"eslint": "^9.11.1",
"@types/bun": "^1.1.11",
"bumpp": "^9.7.1",
"eslint": "^9.13.0",
"kysely": "^0.27.4",
"kysely-wasm": "^0.6.3",
"node-sqlite3-wasm": "^0.8.24",
"tsup": "^8.3.0",
"typescript": "^5.6.2"
"typescript": "^5.6.3"
}
}
Loading