Skip to content

Commit 5a4d786

Browse files
committed
Generated query mapper
1 parent 24659c1 commit 5a4d786

File tree

1 file changed

+104
-0
lines changed

1 file changed

+104
-0
lines changed

drizzle-orm/src/utils.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,110 @@ export function mapResultRow<TResult>(
7676
return result as TResult;
7777
}
7878

79+
/** @internal */
80+
function makeJitQueryMapperInner(
81+
columns: SelectedFieldsOrdered<AnyColumn>,
82+
joinsNotNullableMap: Record<string, boolean> | undefined,
83+
): string {
84+
let fn = [];
85+
if (joinsNotNullableMap) fn.push(`const nullifyMap = {};`);
86+
87+
const initializedPaths = new Set<string>();
88+
89+
for (const [idx, { path: pathArr, field, codec }] of columns.entries()) {
90+
const pathPrefix = pathArr.slice(0, -1);
91+
const path = pathArr.map((e) => `[${JSON.stringify(e)}]`).join('');
92+
93+
let processedPath;
94+
for (const p of pathPrefix) {
95+
processedPath = processedPath ? `${p}[${JSON.stringify(p)}]` : JSON.stringify(p);
96+
if (initializedPaths.has(processedPath)) continue;
97+
fn.push(`res[${processedPath}] = {};`);
98+
initializedPaths.add(processedPath);
99+
}
100+
101+
let decoder: DriverValueDecoder<unknown, unknown>;
102+
let decoderStr: string;
103+
if (is(field, Column)) {
104+
decoder = field;
105+
decoderStr = `columns[${idx}].field.mapFromDriverValue`;
106+
} else if (is(field, SQL)) {
107+
decoder = field.decoder;
108+
decoderStr = `columns[${idx}].field.decoder.mapFromDriverValue`;
109+
} else if (is(field, Subquery)) {
110+
decoder = field._.sql.decoder;
111+
decoderStr = `columns[${idx}].field._.sql.decoder.mapFromDriverValue`;
112+
} else {
113+
decoder = field.sql.decoder;
114+
decoderStr = `columns[${idx}].field.sql.decoder.mapFromDriverValue`;
115+
}
116+
if (decoder.mapFromDriverValue.isNoop) decoderStr = '';
117+
const rowStr = `rows[i][${idx}]`;
118+
119+
fn.push(
120+
` res${path} = ${rowStr} === null ? ${rowStr} : ${
121+
decoderStr
122+
? `${decoderStr}(${codec ? `columns[${idx}].codec(${rowStr}, columns[${idx}].arrayDimensions)` : rowStr})`
123+
: codec
124+
? `columns[${idx}].codec(${rowStr}, columns[${idx}].arrayDimensions)`
125+
: rowStr
126+
};`,
127+
);
128+
129+
if (joinsNotNullableMap && is(field, Column) && pathArr.length === 2) {
130+
const objectName = JSON.stringify(pathArr[0]!);
131+
fn.push(
132+
`if (!(${objectName} in nullifyMap)) {`,
133+
` nullifyMap[${objectName}] = res${path} === null ? this.getTableName(columns[${idx}].field.table) : false;`,
134+
`} else if (typeof nullifyMap[${objectName}] === 'string' && nullifyMap[${objectName}] !== this.getTableName(columns[${idx}].field.table)) {`,
135+
` nullifyMap[${objectName}] = false;`,
136+
`}`,
137+
);
138+
}
139+
}
140+
141+
if (joinsNotNullableMap) {
142+
fn.push(
143+
`if(Object.keys(nullifyMap).length) {`,
144+
` for (const [objectName, tableName] of Object.entries(nullifyMap)) {`,
145+
` if (typeof tableName === 'string' && !joinsNotNullableMap[tableName]) {`,
146+
` res[objectName] = null;`,
147+
` }`,
148+
` }`,
149+
`}`,
150+
);
151+
}
152+
153+
return fn.join('\n');
154+
}
155+
156+
export type JitMapper<TResult = Record<string, unknown>[]> = (
157+
rows: unknown[][],
158+
columns: SelectedFieldsOrdered<AnyColumn>,
159+
joinsNotNullableMap: Record<string, boolean> | undefined,
160+
) => TResult;
161+
162+
/** @internal */
163+
export function makeJitQueryMapper<TResult>(
164+
columns: SelectedFieldsOrdered<AnyColumn>,
165+
joinsNotNullableMap: Record<string, boolean> | undefined,
166+
): JitMapper<TResult> {
167+
return new Function(
168+
'rows',
169+
'columns',
170+
'joinsNotNullableMap',
171+
`const mapped = [];
172+
for (let i = 0; i < rows.length; ++i) {
173+
const res = {};
174+
${makeJitQueryMapperInner(columns, joinsNotNullableMap)}
175+
mapped[i] = res;
176+
}
177+
return mapped;`,
178+
).bind({
179+
getTableName,
180+
}) as any;
181+
}
182+
79183
/** @internal */
80184
export function orderSelectedFields<TColumn extends AnyColumn>(
81185
fields: Record<string, unknown>,

0 commit comments

Comments
 (0)