Skip to content

Commit cdad0c4

Browse files
authored
Merge pull request #1168 from cardstack/cs-6468-implement-postgres-db-adapter-for-indexer
Added postgres implementation for indexer
2 parents c220289 + b6d0840 commit cdad0c4

File tree

14 files changed

+1158
-880
lines changed

14 files changed

+1158
-880
lines changed

packages/host/app/lib/sqlite-adapter.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
export default class SQLiteAdapter implements DBAdapter {
1414
private _sqlite: typeof SQLiteWorker | undefined;
1515
private _dbId: string | undefined;
16+
private primaryKeys = new Map<string, string>();
1617

1718
// TODO: one difference that I'm seeing is that it looks like "json_each" is
1819
// actually similar to "json_each_text" in postgres. i think we might need to
@@ -56,11 +57,25 @@ export default class SQLiteAdapter implements DBAdapter {
5657
);
5758
throw e;
5859
}
60+
61+
let pks = (await this.execute(
62+
`
63+
SELECT m.name AS table_name,
64+
GROUP_CONCAT(p.name, ', ') AS primary_keys
65+
FROM sqlite_master AS m
66+
JOIN pragma_table_info(m.name) AS p ON m.type = 'table'
67+
WHERE p.pk > 0
68+
GROUP BY m.name;
69+
`,
70+
)) as { table_name: string; primary_keys: string }[];
71+
for (let { table_name, primary_keys } of pks) {
72+
this.primaryKeys.set(table_name, primary_keys);
73+
}
5974
}
6075
}
6176

6277
async execute(sql: string, opts?: ExecuteOptions) {
63-
return await this.query(sql, opts);
78+
return await this.query(this.adjustSQL(sql), opts);
6479
}
6580

6681
async close() {
@@ -137,6 +152,24 @@ export default class SQLiteAdapter implements DBAdapter {
137152

138153
return results;
139154
}
155+
156+
private adjustSQL(sql: string): string {
157+
return sql
158+
.replace(/ON CONFLICT ON CONSTRAINT (\w*)\b/, (_, constraint) => {
159+
let tableName = constraint.replace(/_pkey$/, '');
160+
let pkColumns = this.primaryKeys.get(tableName);
161+
if (!pkColumns) {
162+
throw new Error(
163+
`could not determine primary key columns for constraint '${constraint}'`,
164+
);
165+
}
166+
return `ON CONFLICT (${pkColumns})`;
167+
})
168+
.replace(/CROSS JOIN LATERAL/g, 'CROSS JOIN')
169+
.replace(/jsonb_array_each\(/g, 'json_each(')
170+
.replace(/\.text_value/g, '.value')
171+
.replace(/COLLATE "POSIX"/g, '');
172+
}
140173
}
141174

142175
function assertNever(value: never) {

packages/host/tests/helpers/index.gts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ import {
2121
type TokenClaims,
2222
} from '@cardstack/runtime-common';
2323

24+
import {
25+
testRealmInfo,
26+
testRealmURL,
27+
} from '@cardstack/runtime-common/helpers/const';
2428
import { Loader } from '@cardstack/runtime-common/loader';
2529
import { LocalPath, RealmPaths } from '@cardstack/runtime-common/paths';
2630
import { Realm } from '@cardstack/runtime-common/realm';
@@ -47,15 +51,14 @@ import {
4751
type FieldDef,
4852
} from 'https://cardstack.com/base/card-api';
4953

50-
import { testRealmInfo, testRealmURL } from './const';
5154
import percySnapshot from './percy-snapshot';
5255

5356
import { renderComponent } from './render-component';
5457
import { WebMessageStream, messageCloseHandler } from './stream';
5558
import visitOperatorMode from './visit-operator-mode';
5659

5760
export { visitOperatorMode, testRealmURL, testRealmInfo, percySnapshot };
58-
export * from './indexer';
61+
export * from '@cardstack/runtime-common/helpers/indexer';
5962

6063
const waiter = buildWaiter('@cardstack/host/test/helpers/index:onFetch-waiter');
6164

0 commit comments

Comments
 (0)