diff --git a/packages/sql/src/modules/type-mapping.test.ts b/packages/sql/src/modules/type-mapping.test.ts index bf81139c..3e577ebd 100644 --- a/packages/sql/src/modules/type-mapping.test.ts +++ b/packages/sql/src/modules/type-mapping.test.ts @@ -55,7 +55,12 @@ describe('cross-dialect type translation', () => { it('Oracle → Postgres', () => { expect(xlate(oracle, pg, 'VARCHAR2(100)').sql).toBe('varchar(100)'); - expect(xlate(oracle, pg, 'NUMBER(10,0)').sql).toBe('integer'); + // NUMBER(p,0): width picks the integer family (int32 / int64 / decimal). + expect(xlate(oracle, pg, 'NUMBER(9,0)').sql).toBe('integer'); + expect(xlate(oracle, pg, 'NUMBER(10,0)').sql).toBe('bigint'); + expect(xlate(oracle, pg, 'NUMBER(18,0)').sql).toBe('bigint'); + expect(xlate(oracle, pg, 'NUMBER(19,0)').sql).toBe('numeric(19,0)'); + expect(xlate(oracle, pg, 'NUMBER(38,0)').sql).toBe('numeric(38,0)'); expect(xlate(oracle, pg, 'NUMBER(10,2)').sql).toBe('numeric(10,2)'); expect(xlate(oracle, pg, 'CLOB').sql).toBe('text'); }); diff --git a/packages/sql/src/providers/oracle/oracle.sql-dialect.ts b/packages/sql/src/providers/oracle/oracle.sql-dialect.ts index 1c6e52fc..b8f05c3b 100644 --- a/packages/sql/src/providers/oracle/oracle.sql-dialect.ts +++ b/packages/sql/src/providers/oracle/oracle.sql-dialect.ts @@ -5,8 +5,18 @@ import { makeDialectTypeFns, plain, sized, sizedOr, decimalAs, warn } from '../. const types = makeDialectTypeFns({ label: 'Oracle', parseMap: { - // NUMBER(p,0) is an integer; NUMBER(p,s>0) or bare NUMBER is decimal - number: (tok) => (tok.scale && tok.scale > 0 ? 'decimal' : tok.precision !== undefined ? 'integer' : 'decimal'), + // NUMBER(p,s>0) / bare NUMBER / NUMBER(p) → decimal. NUMBER(p,0) is an + // integer-scaled value, but precision decides the family: p≤9 fits int32, + // p≤18 fits int64, anything wider must stay decimal. Mapping every + // NUMBER(p,0) to `integer` used to emit Postgres/MySQL `integer`/`int` for + // NUMBER(19,0) and NUMBER(38,0) — silent narrowing on cross-dialect migrate. + number: (tok) => { + if ((tok.scale ?? 0) > 0) return 'decimal'; + if (tok.precision === undefined) return 'decimal'; + if (tok.precision <= 9) return 'integer'; + if (tok.precision <= 18) return 'bigint'; + return 'decimal'; + }, integer: 'integer', int: 'integer', smallint: 'integer',