Skip to content

Commit 7775fea

Browse files
committed
feat: bigint mode for integer, that supports full 64-bit values
1 parent 47ba9c8 commit 7775fea

File tree

3 files changed

+55
-3
lines changed

3 files changed

+55
-3
lines changed

drizzle-orm/src/sqlite-core/columns/integer.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,52 @@ export class SQLiteBoolean<T extends ColumnBaseConfig<'boolean', 'SQLiteBoolean'
201201
}
202202
}
203203

204+
export type SQLiteIntegerBigIntBuilderInitial<TName extends string> = SQLiteIntegerBigIntBuilder<{
205+
name: TName;
206+
dataType: 'bigint';
207+
columnType: 'SQLiteIntegerBigInt';
208+
data: bigint;
209+
driverParam: string;
210+
enumValues: undefined;
211+
}>;
212+
213+
export class SQLiteIntegerBigIntBuilder<T extends ColumnBuilderBaseConfig<'bigint', 'SQLiteIntegerBigInt'>>
214+
extends SQLiteBaseIntegerBuilder<T>
215+
{
216+
static override readonly [entityKind]: string = 'SQLiteIntegerBigIntBuilder';
217+
218+
constructor(name: T['name']) {
219+
super(name, 'bigint', 'SQLiteIntegerBigInt');
220+
}
221+
222+
/** @internal */
223+
override build<TTableName extends string>(
224+
table: AnySQLiteTable<{ name: TTableName }>,
225+
): SQLiteIntegerBigInt<MakeColumnConfig<T, TTableName>> {
226+
return new SQLiteIntegerBigInt<MakeColumnConfig<T, TTableName>>(
227+
table,
228+
this.config as ColumnBuilderRuntimeConfig<any, any>,
229+
);
230+
}
231+
}
232+
233+
export class SQLiteIntegerBigInt<T extends ColumnBaseConfig<'bigint', 'SQLiteIntegerBigInt'>>
234+
extends SQLiteBaseInteger<T>
235+
{
236+
static override readonly [entityKind]: string = 'SQLiteIntegerBigInt';
237+
238+
override mapFromDriverValue = BigInt;
239+
240+
override mapToDriverValue = String;
241+
}
242+
204243
export interface IntegerConfig<
205-
TMode extends 'number' | 'timestamp' | 'timestamp_ms' | 'boolean' =
244+
TMode extends 'number' | 'timestamp' | 'timestamp_ms' | 'boolean' | 'bigint' =
206245
| 'number'
207246
| 'timestamp'
208247
| 'timestamp_ms'
209-
| 'boolean',
248+
| 'boolean'
249+
| 'bigint',
210250
> {
211251
mode: TMode;
212252
}
@@ -216,12 +256,14 @@ export function integer<TMode extends IntegerConfig['mode']>(
216256
config?: IntegerConfig<TMode>,
217257
): Or<Equal<TMode, 'timestamp'>, Equal<TMode, 'timestamp_ms'>> extends true ? SQLiteTimestampBuilderInitial<''>
218258
: Equal<TMode, 'boolean'> extends true ? SQLiteBooleanBuilderInitial<''>
259+
: Equal<TMode, 'bigint'> extends true ? SQLiteIntegerBigIntBuilderInitial<''>
219260
: SQLiteIntegerBuilderInitial<''>;
220261
export function integer<TName extends string, TMode extends IntegerConfig['mode']>(
221262
name: TName,
222263
config?: IntegerConfig<TMode>,
223264
): Or<Equal<TMode, 'timestamp'>, Equal<TMode, 'timestamp_ms'>> extends true ? SQLiteTimestampBuilderInitial<TName>
224265
: Equal<TMode, 'boolean'> extends true ? SQLiteBooleanBuilderInitial<TName>
266+
: Equal<TMode, 'bigint'> extends true ? SQLiteIntegerBigIntBuilderInitial<TName>
225267
: SQLiteIntegerBuilderInitial<TName>;
226268
export function integer(a?: string | IntegerConfig, b?: IntegerConfig) {
227269
const { name, config } = getColumnNameAndConfig<IntegerConfig | undefined>(a, b);
@@ -231,6 +273,9 @@ export function integer(a?: string | IntegerConfig, b?: IntegerConfig) {
231273
if (config?.mode === 'boolean') {
232274
return new SQLiteBooleanBuilder(name, config.mode);
233275
}
276+
if (config?.mode === 'bigint') {
277+
return new SQLiteIntegerBigIntBuilder(name);
278+
}
234279
return new SQLiteIntegerBuilder(name);
235280
}
236281

drizzle-orm/src/sqlite-core/dialect.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export abstract class SQLiteDialect {
185185
}
186186
} else if (is(field, Column)) {
187187
const tableName = field.table[Table.Symbol.Name];
188-
if (field.columnType === 'SQLiteNumericBigInt') {
188+
if (field.columnType === 'SQLiteNumericBigInt' || field.columnType === 'SQLiteIntegerBigInt') {
189189
if (isSingleTable) {
190190
chunk.push(sql`cast(${sql.identifier(this.casing.getColumnCasing(field))} as text)`);
191191
} else {

integration-tests/tests/sqlite/sqlite-common.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ const allTypesTable = sqliteTable('all_types', {
7070
timeMs: integer('time_ms', {
7171
mode: 'timestamp_ms',
7272
}),
73+
integerBig: integer('integer_big', {
74+
mode: 'bigint',
75+
}),
7376
bigint: blob('bigint', {
7477
mode: 'bigint',
7578
}),
@@ -3283,6 +3286,7 @@ export function tests() {
32833286
\`bool\` integer,
32843287
\`time\` integer,
32853288
\`time_ms\` integer,
3289+
\`integer_big\` integer,
32863290
\`bigint\` blob,
32873291
\`buffer\` blob,
32883292
\`json\` blob,
@@ -3336,6 +3340,7 @@ export function tests() {
33363340
text: 'TEXT STRING',
33373341
time: new Date(1741743161623),
33383342
timeMs: new Date(1741743161623),
3343+
integerBig: 5044565289845416380n,
33393344
});
33403345

33413346
const rawRes = await db.select().from(allTypesTable);
@@ -3347,6 +3352,7 @@ export function tests() {
33473352
bool: boolean | null;
33483353
time: Date | null;
33493354
timeMs: Date | null;
3355+
integerBig: bigint | null;
33503356
bigint: bigint | null;
33513357
buffer: Buffer | null;
33523358
json: unknown;
@@ -3364,6 +3370,7 @@ export function tests() {
33643370
bool: true,
33653371
time: new Date('2025-03-12T01:32:41.000Z'),
33663372
timeMs: new Date('2025-03-12T01:32:41.623Z'),
3373+
integerBig: 5044565289845416380n,
33673374
bigint: 5044565289845416380n,
33683375
buffer: Buffer.from([
33693376
0x44,

0 commit comments

Comments
 (0)