Skip to content

Commit

Permalink
increments() no longer changes the column type to serial on postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
koskimas committed Nov 23, 2021
1 parent 4285b5c commit 5e70376
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 157 deletions.
53 changes: 43 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,34 +163,67 @@ changes completely. Migrations need to be "frozen in time".
The migrations can use the [Kysely.schema](https://koskimas.github.io/kysely/classes/SchemaModule.html)
module to modify the schema. Migrations can also run normal queries to modify the data.

### PostgreSQL migration example

```ts
import { Kysely } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('person')
.addColumn('id', 'integer', (col) => col.increments().primaryKey())
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('first_name', 'varchar')
.addColumn('last_name', 'varchar')
.addColumn('gender', 'varchar(50)')
.execute()

await db.schema
.createTable('pet')
.addColumn('id', 'integer', (col) => col.increments().primaryKey())
.addColumn('id', 'serial', (col) => col.primaryKey())
.addColumn('name', 'varchar', (col) => col.notNull().unique())
.addColumn('owner_id', 'integer', (col) =>
col.references('person.id').onDelete('cascade')
)
.addColumn('species', 'varchar')
// Older MySQL versions don't support column-level foreign key
// constraint definitions and you need to add them using the table
// builder by uncommenting the following:
//
// .addForeignKeyConstraint(
// 'pet_owner_id_fk', ['owner_id'], 'person', ['id'],
// (cb) => cb.onDelete('cascade')
// )
.execute()

await db.schema
.createIndex('pet_owner_id_index')
.on('pet')
.column('owner_id')
.execute()
}

export async function down(db: Kysely<any>): Promise<void> {
await db.schema.dropTable('pet').execute()
await db.schema.dropTable('person').execute()
}
```

### MySQL migration example

```ts
import { Kysely } from 'kysely'

export async function up(db: Kysely<any>): Promise<void> {
await db.schema
.createTable('person')
.addColumn('id', 'integer', (col) => col.increments().primaryKey())
.addColumn('first_name', 'varchar')
.addColumn('last_name', 'varchar')
.addColumn('gender', 'varchar(50)')
.execute()

await db.schema
.createTable('pet')
.addColumn('id', 'integer', (col) => col.increments().primaryKey())
.addColumn('name', 'varchar', (col) => col.notNull().unique())
.addColumn('owner_id', 'integer')
.addColumn('species', 'varchar')
.addForeignKeyConstraint(
'pet_owner_id_fk', ['owner_id'], 'person', ['id'],
(cb) => cb.onDelete('cascade')
)
.execute()

await db.schema
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kysely",
"version": "0.8.1",
"version": "0.9.0",
"description": "Type safe SQL query builder",
"repository": {
"type": "git",
Expand Down
38 changes: 0 additions & 38 deletions src/dialect/mysql/mysql-query-compiler.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,6 @@
import { ColumnDefinitionNode } from '../../operation-node/column-definition-node.js'
import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'

export class MysqlQueryCompiler extends DefaultQueryCompiler {
protected override visitColumnDefinition(node: ColumnDefinitionNode): void {
this.visitNode(node.column)
this.append(' ')
this.visitNode(node.dataType)

if (node.defaultTo) {
this.append(' default ')
this.visitNode(node.defaultTo)
}

if (!node.isNullable || node.isAutoIncrementing) {
this.append(' not null')
}

if (node.isAutoIncrementing) {
this.append(' auto_increment')
}

if (node.isUnique) {
this.append(' unique')
}

if (node.isPrimaryKey) {
this.append(' primary key')
}

if (node.references) {
this.append(' ')
this.visitNode(node.references)
}

if (node.check) {
this.append(' ')
this.visitNode(node.check)
}
}

protected override visitReturning(): void {
// Do nothing.
}
Expand Down
2 changes: 1 addition & 1 deletion src/operation-node/primitive-value-list-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const PrimitiveValueListNode = freeze({
create(values: ReadonlyArray<PrimitiveValue>): PrimitiveValueListNode {
return freeze({
kind: 'PrimitiveValueListNode',
values: freeze(values),
values: freeze([...values]),
})
},
})
12 changes: 6 additions & 6 deletions src/query-builder/function-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ export class FunctionBuilder<DB, TB extends keyof DB> {
* Calls the `sum` function for the column given as the argument.
*
* If this is used in a `select` statement the type of the selected expression
* will be `number | string` by default. This is because Kysely can't know the
* type the db driver outputs. Sometimes the output can be larger than the
* largest javascript number and a string is returned instead. Most drivers
* will be `number | string | BigInt` by default. This is because Kysely can't
* know the type the db driver outputs. Sometimes the output can be larger than
* the largest javascript number and a string is returned instead. Most drivers
* allow you to configure the output type of large numbers and Kysely can't
* know if you've done so.
*
Expand All @@ -125,9 +125,9 @@ export class FunctionBuilder<DB, TB extends keyof DB> {
* Calls the `count` function for the column given as the argument.
*
* If this is used in a `select` statement the type of the selected expression
* will be `number | string` by default. This is because Kysely can't know the
* type the db driver outputs. Sometimes the output can be larger than the
* largest javascript number and a string is returned instead. Most drivers
* will be `number | string | BigInt` by default. This is because Kysely can't
* know the type the db driver outputs. Sometimes the output can be larger than
* the largest javascript number and a string is returned instead. Most drivers
* allow you to configure the output type of large numbers and Kysely can't
* know if you've done so.
*
Expand Down
32 changes: 14 additions & 18 deletions src/query-compiler/default-query-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ export class DefaultQueryCompiler
extends OperationNodeVisitor
implements QueryCompiler
{
#sqlFragments: string[] = []
#sql = ''
#parameters: any[] = []

protected get numParameters(): number {
return this.#parameters.length
}

compileQuery(node: RootOperationNode): CompiledQuery {
this.#sqlFragments = []
this.#sql = ''
this.#parameters = []

this.visitNode(node)
Expand All @@ -99,7 +99,7 @@ export class DefaultQueryCompiler
}

protected getSql(): string {
return this.#sqlFragments.join('')
return this.#sql
}

protected override visitSelectQuery(node: SelectQueryNode): void {
Expand Down Expand Up @@ -445,20 +445,7 @@ export class DefaultQueryCompiler
protected override visitColumnDefinition(node: ColumnDefinitionNode): void {
this.visitNode(node.column)
this.append(' ')

if (node.isAutoIncrementing) {
// Postgres overrides the data type for autoincrementing columns.
if (
DataTypeNode.is(node.dataType) &&
node.dataType.dataType === 'bigint'
) {
this.append('bigserial')
} else {
this.append('serial')
}
} else {
this.visitNode(node.dataType)
}
this.visitNode(node.dataType)

if (node.defaultTo) {
this.append(' default ')
Expand All @@ -469,6 +456,11 @@ export class DefaultQueryCompiler
this.append(' not null')
}

if (node.isAutoIncrementing) {
this.append(' ')
this.append(this.getAutoIncrement())
}

if (node.isUnique) {
this.append(' unique')
}
Expand All @@ -488,6 +480,10 @@ export class DefaultQueryCompiler
}
}

protected getAutoIncrement() {
return 'auto_increment'
}

protected override visitReferences(node: ReferencesNode): void {
this.append('references ')
this.visitNode(node.table)
Expand Down Expand Up @@ -888,7 +884,7 @@ export class DefaultQueryCompiler
}

protected append(str: string): void {
this.#sqlFragments.push(str)
this.#sql += str
}

protected appendValue(value: PrimitiveValue): void {
Expand Down
3 changes: 3 additions & 0 deletions src/schema/alter-table-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ import { CheckConstraintNode } from '../operation-node/check-constraint-node.js'
import { ForeignKeyConstraintNode } from '../operation-node/foreign-key-constraint-node.js'
import { ColumnNode } from '../operation-node/column-node.js'

/**
* This builder can be used to create a `alter table` query.
*/
export class AlterTableBuilder {
readonly #props: AlterTableBuilderProps

Expand Down
9 changes: 4 additions & 5 deletions src/schema/column-definition-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ import {

export interface ColumnDefinitionBuilderInterface<R> {
/**
* Makes the column automatically incrementing.
* Adds `auto_increment` or `autoincrement` to the column definition
* depending on the dialect.
*
* On some dialects this may change the column type as well. For example
* on postgres this sets the column type to `serial` no matter what you
* have specified before. This is one of the few cases where Kysely does
* something "unexpected".
* Some dialects like PostgreSQL don't support this. On PostgreSQL
* you can use the `serial` or `bigserial` data type instead.
*/
increments(): R

Expand Down
Loading

0 comments on commit 5e70376

Please sign in to comment.