@malloy-publisher/server 0.0.212 → 0.0.213
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.mjs +4 -1
- package/package.json +1 -1
- package/src/service/db_utils.spec.ts +53 -1
- package/src/service/db_utils.ts +14 -1
package/dist/server.mjs
CHANGED
|
@@ -230137,7 +230137,10 @@ async function listTablesForSchema(connection, schemaName, malloyConnection, tab
|
|
|
230137
230137
|
async function listTablesForBigQuery(connection, schemaName, malloyConnection, tableNames) {
|
|
230138
230138
|
try {
|
|
230139
230139
|
const bigquery = createBigQueryClient(connection);
|
|
230140
|
-
const
|
|
230140
|
+
const lastDot = schemaName.lastIndexOf(".");
|
|
230141
|
+
const dataset = lastDot === -1 ? bigquery.dataset(schemaName) : bigquery.dataset(schemaName.slice(lastDot + 1), {
|
|
230142
|
+
projectId: schemaName.slice(0, lastDot)
|
|
230143
|
+
});
|
|
230141
230144
|
const [tables] = await dataset.getTables();
|
|
230142
230145
|
let names = tables.map((table) => table.id).filter((id) => id !== undefined);
|
|
230143
230146
|
if (tableNames) {
|
package/package.json
CHANGED
|
@@ -7,8 +7,16 @@ mock.module("@azure/identity", () => ({
|
|
|
7
7
|
mock.module("@azure/storage-blob", () => ({
|
|
8
8
|
ContainerClient: class {},
|
|
9
9
|
}));
|
|
10
|
+
// Records bigquery.dataset() calls so tests can assert how a (possibly
|
|
11
|
+
// project-qualified) schema name is split into datasetId + projectId.
|
|
12
|
+
const bqDatasetCalls: Array<{ id: string; options?: unknown }> = [];
|
|
10
13
|
mock.module("@google-cloud/bigquery", () => ({
|
|
11
|
-
BigQuery: class {
|
|
14
|
+
BigQuery: class {
|
|
15
|
+
dataset(id: string, options?: unknown) {
|
|
16
|
+
bqDatasetCalls.push({ id, options });
|
|
17
|
+
return { getTables: async () => [[]] };
|
|
18
|
+
}
|
|
19
|
+
},
|
|
12
20
|
}));
|
|
13
21
|
|
|
14
22
|
import { Connection } from "@malloydata/malloy";
|
|
@@ -1031,3 +1039,47 @@ describe("publisher proxy introspection", () => {
|
|
|
1031
1039
|
);
|
|
1032
1040
|
});
|
|
1033
1041
|
});
|
|
1042
|
+
|
|
1043
|
+
// ---------------------------------------------------------------------------
|
|
1044
|
+
// listTablesForSchema — bigquery (project-qualified dataset)
|
|
1045
|
+
// ---------------------------------------------------------------------------
|
|
1046
|
+
describe("listTablesForSchema bigquery", () => {
|
|
1047
|
+
const bqConnection = {
|
|
1048
|
+
name: "bq",
|
|
1049
|
+
type: "bigquery",
|
|
1050
|
+
bigqueryConnection: {
|
|
1051
|
+
defaultProjectId: "default-proj",
|
|
1052
|
+
serviceAccountKeyJson: JSON.stringify({ project_id: "default-proj" }),
|
|
1053
|
+
},
|
|
1054
|
+
} as unknown as ApiConnection;
|
|
1055
|
+
const malloyConn = {} as unknown as Connection;
|
|
1056
|
+
|
|
1057
|
+
it("splits a project-qualified schema into a bare dataset id + projectId", async () => {
|
|
1058
|
+
bqDatasetCalls.length = 0;
|
|
1059
|
+
await listTablesForSchema(bqConnection, "myproj.myds", malloyConn);
|
|
1060
|
+
expect(bqDatasetCalls).toHaveLength(1);
|
|
1061
|
+
expect(bqDatasetCalls[0]?.id).toBe("myds");
|
|
1062
|
+
expect(bqDatasetCalls[0]?.options).toEqual({ projectId: "myproj" });
|
|
1063
|
+
});
|
|
1064
|
+
|
|
1065
|
+
it("splits on the last dot so domain-scoped project ids survive", async () => {
|
|
1066
|
+
bqDatasetCalls.length = 0;
|
|
1067
|
+
await listTablesForSchema(
|
|
1068
|
+
bqConnection,
|
|
1069
|
+
"domain.com:proj.myds",
|
|
1070
|
+
malloyConn,
|
|
1071
|
+
);
|
|
1072
|
+
expect(bqDatasetCalls[0]?.id).toBe("myds");
|
|
1073
|
+
expect(bqDatasetCalls[0]?.options).toEqual({
|
|
1074
|
+
projectId: "domain.com:proj",
|
|
1075
|
+
});
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
it("passes a bare dataset name through unqualified", async () => {
|
|
1079
|
+
bqDatasetCalls.length = 0;
|
|
1080
|
+
await listTablesForSchema(bqConnection, "myds", malloyConn);
|
|
1081
|
+
expect(bqDatasetCalls).toHaveLength(1);
|
|
1082
|
+
expect(bqDatasetCalls[0]?.id).toBe("myds");
|
|
1083
|
+
expect(bqDatasetCalls[0]?.options).toBeUndefined();
|
|
1084
|
+
});
|
|
1085
|
+
});
|
package/src/service/db_utils.ts
CHANGED
|
@@ -1077,7 +1077,20 @@ async function listTablesForBigQuery(
|
|
|
1077
1077
|
): Promise<ApiTable[]> {
|
|
1078
1078
|
try {
|
|
1079
1079
|
const bigquery = createBigQueryClient(connection);
|
|
1080
|
-
|
|
1080
|
+
// A 3-segment table reference ("project.dataset.table") reaches here with a
|
|
1081
|
+
// project-qualified schema ("project.dataset"). bigquery.dataset() takes a
|
|
1082
|
+
// BARE dataset id plus an optional projectId, so passing "project.dataset" as
|
|
1083
|
+
// the id resolves to a non-existent dataset in the client's default project —
|
|
1084
|
+
// the dataset's tables never list, so the orphan sweep can't see (and reclaim)
|
|
1085
|
+
// those tables. Split the project off the last dot. (Domain-scoped project ids
|
|
1086
|
+
// like "domain.com:project" keep their dots/colon since we split on the last.)
|
|
1087
|
+
const lastDot = schemaName.lastIndexOf(".");
|
|
1088
|
+
const dataset =
|
|
1089
|
+
lastDot === -1
|
|
1090
|
+
? bigquery.dataset(schemaName)
|
|
1091
|
+
: bigquery.dataset(schemaName.slice(lastDot + 1), {
|
|
1092
|
+
projectId: schemaName.slice(0, lastDot),
|
|
1093
|
+
});
|
|
1081
1094
|
const [tables] = await dataset.getTables();
|
|
1082
1095
|
|
|
1083
1096
|
let names = tables
|