Skip to content

Commit

Permalink
feat: implement private members (dimensions, metrics)
Browse files Browse the repository at this point in the history
  • Loading branch information
retro committed Sep 3, 2024
1 parent 334613b commit 6a80dad
Show file tree
Hide file tree
Showing 18 changed files with 1,626 additions and 315 deletions.
255 changes: 102 additions & 153 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
},
"devDependencies": {
"@biomejs/biome": "^1.8.3",
"@microsoft/api-extractor": "^7.42.3",
"@microsoft/api-extractor": "^7.47.7",
"@nitrogql/esbuild-register": "^1.6.0-beta.0",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^11.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/__tests__/clone.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe("clone", () => {

assert.equal(
query.sql,
'select "q0"."customer___user_id" as "customer___user_id", "q0"."employee___user_id" as "employee___user_id", "q0"."invoice___invoice_id" as "invoice___invoice_id", "q0"."customer___count" as "customer___count", "q1"."employee___count" as "employee___count" from (select "s0"."customer___user_id" as "customer___user_id", "s0"."employee___user_id" as "employee___user_id", "s0"."invoice___invoice_id" as "invoice___invoice_id", COUNT(DISTINCT "count___metric_ref_0") as "customer___count" from (select distinct "User"."UserId" as "customer___user_id", "User"."UserId" as "employee___user_id", "Invoice"."InvoiceId" as "invoice___invoice_id", "User"."UserId" as "count___metric_ref_0" from "User" left join "Invoice" on "User"."UserId" = "Invoice"."CustomerId" right join "User" on "User"."UserId" = "Invoice"."EmployeeId") as "s0" group by "s0"."customer___user_id", "s0"."employee___user_id", "s0"."invoice___invoice_id") as "q0" inner join (select "s1"."customer___user_id" as "customer___user_id", "s1"."employee___user_id" as "employee___user_id", "s1"."invoice___invoice_id" as "invoice___invoice_id", COUNT(DISTINCT "count___metric_ref_0") as "employee___count" from (select distinct "User"."UserId" as "customer___user_id", "User"."UserId" as "employee___user_id", "Invoice"."InvoiceId" as "invoice___invoice_id", "User"."UserId" as "count___metric_ref_0" from "User" left join "Invoice" on "User"."UserId" = "Invoice"."EmployeeId" right join "User" on "User"."UserId" = "Invoice"."CustomerId") as "s1" group by "s1"."customer___user_id", "s1"."employee___user_id", "s1"."invoice___invoice_id") as "q1" on "q0"."customer___user_id" = "q1"."customer___user_id" and "q0"."employee___user_id" = "q1"."employee___user_id" and "q0"."invoice___invoice_id" = "q1"."invoice___invoice_id" order by "customer___count" desc',
'select "q0"."customer___user_id" as "customer___user_id", "q0"."employee___user_id" as "employee___user_id", "q0"."invoice___invoice_id" as "invoice___invoice_id", "q0"."customer___count" as "customer___count", "q1"."employee___count" as "employee___count" from (select "s0"."customer___user_id" as "customer___user_id", "s0"."employee___user_id" as "employee___user_id", "s0"."invoice___invoice_id" as "invoice___invoice_id", COUNT(DISTINCT "customer___count___mr_0") as "customer___count" from (select distinct "User"."UserId" as "customer___user_id", "User"."UserId" as "employee___user_id", "Invoice"."InvoiceId" as "invoice___invoice_id", "User"."UserId" as "customer___count___mr_0" from "User" left join "Invoice" on "User"."UserId" = "Invoice"."CustomerId" right join "User" on "User"."UserId" = "Invoice"."EmployeeId") as "s0" group by "s0"."customer___user_id", "s0"."employee___user_id", "s0"."invoice___invoice_id") as "q0" inner join (select "s1"."customer___user_id" as "customer___user_id", "s1"."employee___user_id" as "employee___user_id", "s1"."invoice___invoice_id" as "invoice___invoice_id", COUNT(DISTINCT "employee___count___mr_0") as "employee___count" from (select distinct "User"."UserId" as "customer___user_id", "User"."UserId" as "employee___user_id", "Invoice"."InvoiceId" as "invoice___invoice_id", "User"."UserId" as "employee___count___mr_0" from "User" left join "Invoice" on "User"."UserId" = "Invoice"."EmployeeId" right join "User" on "User"."UserId" = "Invoice"."CustomerId") as "s1" group by "s1"."customer___user_id", "s1"."employee___user_id", "s1"."invoice___invoice_id") as "q1" on "q0"."customer___user_id" = "q1"."customer___user_id" and "q0"."employee___user_id" = "q1"."employee___user_id" and "q0"."invoice___invoice_id" = "q1"."invoice___invoice_id" order by "customer___count" desc',
);
});
});
109 changes: 109 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1653,38 +1653,46 @@ describe("semantic layer", async () => {
customers___customer_id: {
memberType: "dimension",
path: "customers.customer_id",
alias: "customers___customer_id",
type: "number",
description: "The unique identifier of the customer",
format: undefined,
isPrimaryKey: true,
isGranularity: false,
isPrivate: false,
},
invoices___invoice_id: {
memberType: "dimension",
path: "invoices.invoice_id",
alias: "invoices___invoice_id",
type: "number",
description: "The unique identifier of the invoice",
format: undefined,
isPrimaryKey: true,
isGranularity: false,
isPrivate: false,
},
invoices___customer_id: {
memberType: "dimension",
path: "invoices.customer_id",
alias: "invoices___customer_id",
type: "number",
description: "The unique identifier of the invoice customer",
format: undefined,
isPrimaryKey: false,
isGranularity: false,
isPrivate: false,
},
invoices___total: {
memberType: "metric",
path: "invoices.total",
alias: "invoices___total",
format: "percentage",
type: "string",
description: undefined,
isPrimaryKey: false,
isGranularity: false,
isPrivate: false,
},
});
});
Expand Down Expand Up @@ -3099,4 +3107,105 @@ describe("semantic layer", async () => {
]);
});
});

describe("repository with private members", () => {
const customersModel = semanticLayer
.model()
.withName("customers")
.fromTable("Customer")
.withDimension("customer_id", {
type: "number",
primaryKey: true,
private: true,
sql: ({ model, sql }) => sql`${model.column("CustomerId")}`,
})
.withDimension("public_customer_id", {
type: "number",
primaryKey: true,
sql: ({ model, sql }) => sql`${model.dimension("customer_id")}`,
})
.withMetric("count", {
type: "string",
private: true,
sql: ({ model, sql }) =>
sql`COUNT(DISTINCT ${model.column("CustomerId")})`,
})
.withMetric("public_count", {
type: "string",
sql: ({ model, sql }) => sql`${model.metric("count").aggregated()}`,
});

const repository = semanticLayer
.repository()
.withModel(customersModel)
.withCalculatedDimension("public_customer_id", {
type: "string",
sql: ({ sql, models }) =>
sql`${models.customers.dimension(
"customer_id",
)} || ' - ' || ${models.customers.dimension("public_customer_id")}`,
})
.withCalculatedMetric("public_count", {
type: "string",
sql: ({ sql, models }) =>
sql`${models.customers.metric("count").aggregated()} || ' - ' || ${models.customers.metric("public_count").aggregated()}`,
});

const queryBuilder = repository.build("postgresql");

it("can have private members", async () => {
const validationResult = queryBuilder.querySchema.safeParse({
members: ["customers.customer_id", "customers.count"],
});

// @ts-expect-error - We expect the validation to fail
assert.deepEqual(validationResult.error.issues, [
{ code: "custom", message: "Member not found", path: ["members", 0] },
{ code: "custom", message: "Member not found", path: ["members", 1] },
]);

const query = queryBuilder.buildQuery({
members: [
"customers.public_customer_id",
"public_customer_id",
"customers.public_count",
"public_count",
],
limit: 1,
order: [{ member: "customers.public_customer_id", direction: "asc" }],
});

const result = await client.query<InferSqlQueryResultType<typeof query>>(
query.sql,
query.bindings,
);

assert.deepEqual(result.rows, [
{
customers___public_count: "1",
customers___public_customer_id: 1,
public_count: "1 - 1",
public_customer_id: "1 - 1",
},
]);

const introspectionResult = queryBuilder.introspect({
members: ["customers.customer_id"],
});

assert.deepEqual(introspectionResult, {
customers___customer_id: {
memberType: "dimension",
path: "customers.customer_id",
alias: "customers___customer_id",
format: undefined,
type: "number",
description: undefined,
isPrimaryKey: true,
isGranularity: false,
isPrivate: true,
},
});
});
});
});
Loading

0 comments on commit 6a80dad

Please sign in to comment.