Skip to content

Commit 2c010f5

Browse files
authored
Use raw column name if we cannot resolve it when building a query (#52)
* If we can't resolve a name when building a query, use the raw name * Properly handle unknown column names where there is no ambiguity
1 parent 4790b29 commit 2c010f5

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

src/QueryBuilder.ts

+20-6
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,31 @@ import { Query, QueryAnd, QueryOr, Order, Predicate, Operator, IsNull } from "./
22

33
function predicateToSQL<TRow>(
44
predicate: Predicate<TRow>,
5-
resolveName: (key: keyof TRow) => string
5+
resolveName: (key: keyof TRow) => string | undefined
66
): string {
77
const { column, compare } = predicate;
8+
// If we cannot find the column name, we just use the column name as is.
9+
// It's possible that the column exists but we just don't know it on the client.
10+
const columnName = resolveName(column) ?? String(column);
811

912
if ("other" in predicate) {
1013
const { other } = predicate;
14+
1115
// TODO this is a bit too tricky. If the RHS matches a column name, we treat it as such. Otherwise we use it bare.
1216
const otherColumn = resolveName(other as keyof TRow);
1317
if (otherColumn !== undefined) {
14-
return `"${resolveName(column)}" ${compare} "${otherColumn}"`;
18+
return `"${columnName}" ${compare} "${otherColumn}"`;
1519
} else {
20+
// We did not resolve the RHS to a column name, so we treat it as a value.
21+
// It's possible that this is actually a column that exists in the table,
22+
// but the client does not know about it.
23+
24+
// This quoting is bad – we should require client users to do this.
1625
const bareValue = typeof other === "string" ? `'${other}'` : other;
17-
return `"${resolveName(column)}" ${compare} ${String(bareValue)}`;
26+
return `"${columnName}" ${compare} ${String(bareValue)}`;
1827
}
1928
}
20-
return `"${resolveName(column)}" ${compare}`;
29+
return `"${columnName}" ${compare}`;
2130
}
2231

2332
export class QueryBuilder<TRow, TOmit extends string>
@@ -30,7 +39,9 @@ export class QueryBuilder<TRow, TOmit extends string>
3039
private _and: Predicate<TRow>[] = [];
3140
private _or: Predicate<TRow>[] = [];
3241

33-
constructor(private props: { table: string; displayNameToName(name: keyof TRow): string }) {}
42+
constructor(
43+
private props: { table: string; displayNameToName(name: keyof TRow): string | undefined }
44+
) {}
3445

3546
public toSQL(): string {
3647
const { table, displayNameToName } = this.props;
@@ -46,7 +57,10 @@ export class QueryBuilder<TRow, TOmit extends string>
4657

4758
if (this._orderBy !== undefined) {
4859
const { column, order = "ASC" } = this._orderBy;
49-
sql += ` ORDER BY "${displayNameToName(column)}" ${order}`;
60+
// If we cannot find the column name, we just use the column name as is.
61+
// It's possible that the column exists but we just don't know it on the client.
62+
const columnName = displayNameToName(column) ?? String(column);
63+
sql += ` ORDER BY "${columnName}" ${order}`;
5064
}
5165

5266
if (this._limit !== undefined) {

0 commit comments

Comments
 (0)