@duckcodeailabs/dql-cli 0.3.0 → 0.5.0

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.
Files changed (60) hide show
  1. package/dist/assets/dql-notebook/assets/index-C7bfa1Fe.js +477 -0
  2. package/dist/assets/dql-notebook/index.html +1 -1
  3. package/dist/assets/templates/dql.config.reference.json +154 -0
  4. package/dist/assets/templates/ecommerce/dql.config.json +5 -0
  5. package/dist/assets/templates/ecommerce/semantic-layer/cubes/customers_cube.yaml +49 -0
  6. package/dist/assets/templates/ecommerce/semantic-layer/cubes/orders_cube.yaml +70 -0
  7. package/dist/assets/templates/ecommerce/semantic-layer/dimensions/channel.yaml +5 -1
  8. package/dist/assets/templates/ecommerce/semantic-layer/dimensions/order_date.yaml +9 -0
  9. package/dist/assets/templates/ecommerce/semantic-layer/dimensions/region.yaml +9 -0
  10. package/dist/assets/templates/ecommerce/semantic-layer/dimensions/segment.yaml +8 -0
  11. package/dist/assets/templates/ecommerce/semantic-layer/hierarchies/customer_geo.yaml +18 -0
  12. package/dist/assets/templates/ecommerce/semantic-layer/metrics/avg_order_value.yaml +10 -0
  13. package/dist/assets/templates/ecommerce/semantic-layer/metrics/gmv.yaml +7 -1
  14. package/dist/assets/templates/ecommerce/semantic-layer/metrics/gross_margin.yaml +10 -0
  15. package/dist/assets/templates/ecommerce/semantic-layer/metrics/order_count.yaml +10 -0
  16. package/dist/assets/templates/saas/dql.config.json +5 -0
  17. package/dist/assets/templates/saas/semantic-layer/dimensions/owner_segment.yaml +8 -0
  18. package/dist/assets/templates/saas/semantic-layer/dimensions/plan_tier.yaml +8 -0
  19. package/dist/assets/templates/saas/semantic-layer/dimensions/risk_bucket.yaml +9 -0
  20. package/dist/assets/templates/saas/semantic-layer/dimensions/status.yaml +8 -0
  21. package/dist/assets/templates/saas/semantic-layer/hierarchies/account_segments.yaml +18 -0
  22. package/dist/assets/templates/saas/semantic-layer/metrics/account_count.yaml +10 -0
  23. package/dist/assets/templates/saas/semantic-layer/metrics/expansion_mrr.yaml +11 -0
  24. package/dist/assets/templates/saas/semantic-layer/metrics/mrr.yaml +7 -1
  25. package/dist/assets/templates/starter/dql.config.json +5 -0
  26. package/dist/assets/templates/starter/notebooks/semantic_layer_tutorial.dqlnb +60 -0
  27. package/dist/assets/templates/starter/semantic-layer/cubes/revenue_cube.yaml +77 -0
  28. package/dist/assets/templates/starter/semantic-layer/dimensions/segment_tier.yaml +1 -1
  29. package/dist/assets/templates/starter/semantic-layer/metrics/revenue.yaml +1 -1
  30. package/dist/assets/templates/taxi/dql.config.json +5 -0
  31. package/dist/assets/templates/taxi/semantic-layer/dimensions/airport_flag.yaml +8 -0
  32. package/dist/assets/templates/taxi/semantic-layer/dimensions/dropoff_borough.yaml +9 -0
  33. package/dist/assets/templates/taxi/semantic-layer/dimensions/payment_type.yaml +8 -0
  34. package/dist/assets/templates/taxi/semantic-layer/dimensions/pickup_borough.yaml +9 -0
  35. package/dist/assets/templates/taxi/semantic-layer/dimensions/pickup_date.yaml +9 -0
  36. package/dist/assets/templates/taxi/semantic-layer/hierarchies/trip_route.yaml +14 -0
  37. package/dist/assets/templates/taxi/semantic-layer/metrics/avg_trip_miles.yaml +10 -0
  38. package/dist/assets/templates/taxi/semantic-layer/metrics/total_fare.yaml +10 -0
  39. package/dist/assets/templates/taxi/semantic-layer/metrics/total_tips.yaml +10 -0
  40. package/dist/assets/templates/taxi/semantic-layer/metrics/trip_count.yaml +10 -0
  41. package/dist/commands/doctor.d.ts.map +1 -1
  42. package/dist/commands/doctor.js +36 -0
  43. package/dist/commands/doctor.js.map +1 -1
  44. package/dist/commands/init.d.ts.map +1 -1
  45. package/dist/commands/init.js +8 -2
  46. package/dist/commands/init.js.map +1 -1
  47. package/dist/commands/semantic.d.ts +10 -0
  48. package/dist/commands/semantic.d.ts.map +1 -0
  49. package/dist/commands/semantic.js +242 -0
  50. package/dist/commands/semantic.js.map +1 -0
  51. package/dist/index.js +6 -1
  52. package/dist/index.js.map +1 -1
  53. package/dist/local-runtime.d.ts +2 -0
  54. package/dist/local-runtime.d.ts.map +1 -1
  55. package/dist/local-runtime.js +106 -18
  56. package/dist/local-runtime.js.map +1 -1
  57. package/dist/package.json +44 -0
  58. package/package.json +15 -14
  59. package/LICENSE +0 -123
  60. package/dist/assets/dql-notebook/assets/index-_N_gerXe.js +0 -353
@@ -7,7 +7,7 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com" />
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
9
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10
- <script type="module" crossorigin src="/assets/index-_N_gerXe.js"></script>
10
+ <script type="module" crossorigin src="/assets/index-C7bfa1Fe.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="/assets/react-CRB3T2We.js">
12
12
  <link rel="modulepreload" crossorigin href="/assets/codemirror-CCrEt63p.js">
13
13
  </head>
@@ -0,0 +1,154 @@
1
+ {
2
+ "_comment": "DQL Config Reference — copy sections you need into your dql.config.json",
3
+
4
+ "project": "my-project-name",
5
+
6
+ "_comment_connections": "=== CONNECTION OPTIONS ===",
7
+
8
+ "_option_1_duckdb_memory": {
9
+ "defaultConnection": {
10
+ "driver": "file",
11
+ "filepath": ":memory:"
12
+ }
13
+ },
14
+
15
+ "_option_2_duckdb_file": {
16
+ "defaultConnection": {
17
+ "driver": "duckdb",
18
+ "filepath": "./data/warehouse.duckdb"
19
+ }
20
+ },
21
+
22
+ "_option_3_snowflake": {
23
+ "defaultConnection": {
24
+ "driver": "snowflake",
25
+ "account": "your-account.snowflakecomputing.com",
26
+ "username": "your_user",
27
+ "password": "${SNOWFLAKE_PASSWORD}",
28
+ "database": "ANALYTICS",
29
+ "schema": "PUBLIC",
30
+ "warehouse": "COMPUTE_WH",
31
+ "role": "ANALYST"
32
+ }
33
+ },
34
+
35
+ "_option_4_bigquery": {
36
+ "defaultConnection": {
37
+ "driver": "bigquery",
38
+ "project": "your-gcp-project-id",
39
+ "dataset": "analytics",
40
+ "keyFilename": "./service-account.json"
41
+ }
42
+ },
43
+
44
+ "_option_5_postgres": {
45
+ "defaultConnection": {
46
+ "driver": "postgres",
47
+ "host": "localhost",
48
+ "port": 5432,
49
+ "database": "analytics",
50
+ "username": "your_user",
51
+ "password": "${POSTGRES_PASSWORD}"
52
+ }
53
+ },
54
+
55
+ "_option_6_sqlite": {
56
+ "defaultConnection": {
57
+ "driver": "sqlite",
58
+ "database": "./data/analytics.sqlite"
59
+ }
60
+ },
61
+
62
+ "_comment_semantic": "=== SEMANTIC LAYER OPTIONS ===",
63
+
64
+ "_semantic_option_1_dql_native": {
65
+ "semanticLayer": {
66
+ "provider": "dql"
67
+ },
68
+ "_directory_structure": {
69
+ "semantic-layer/metrics/": "one YAML file per metric",
70
+ "semantic-layer/dimensions/": "one YAML file per dimension",
71
+ "semantic-layer/hierarchies/":"one YAML file per hierarchy",
72
+ "semantic-layer/cubes/": "one YAML file per cube (groups measures + dimensions + joins)"
73
+ }
74
+ },
75
+
76
+ "_semantic_option_2_dql_custom_path": {
77
+ "semanticLayer": {
78
+ "provider": "dql",
79
+ "path": "./my-definitions"
80
+ }
81
+ },
82
+
83
+ "_semantic_option_3_dbt": {
84
+ "semanticLayer": {
85
+ "provider": "dbt",
86
+ "projectPath": "/absolute/path/to/your/dbt-project"
87
+ },
88
+ "_notes": {
89
+ "how_it_works": "Reads semantic_models and metrics from your dbt models/**/*.yml files",
90
+ "requires": "dbt 1.6+ with semantic_models defined in YAML",
91
+ "relative_path": "You can also use a relative path: ../my-dbt-repo"
92
+ }
93
+ },
94
+
95
+ "_semantic_option_4_cubejs": {
96
+ "semanticLayer": {
97
+ "provider": "cubejs",
98
+ "projectPath": "/absolute/path/to/your/cube-project"
99
+ },
100
+ "_notes": {
101
+ "how_it_works": "Reads cube definitions from model/ or schema/ directory",
102
+ "relative_path": "You can also use a relative path: ../my-cube-project"
103
+ }
104
+ },
105
+
106
+ "_semantic_option_5_dbt_remote_github": {
107
+ "semanticLayer": {
108
+ "provider": "dbt",
109
+ "source": "github",
110
+ "repoUrl": "https://github.com/your-org/dbt-metrics.git",
111
+ "branch": "main",
112
+ "subPath": "models"
113
+ },
114
+ "_notes": {
115
+ "how_it_works": "Clones the remote repo into ~/.dql/cache/repos/ and reads dbt semantic models from it",
116
+ "auth": "For private repos, set GITHUB_TOKEN environment variable",
117
+ "cache": "Cached for 10 minutes; use 'dql semantic pull' to force refresh"
118
+ }
119
+ },
120
+
121
+ "_semantic_option_6_cubejs_remote_gitlab": {
122
+ "semanticLayer": {
123
+ "provider": "cubejs",
124
+ "source": "gitlab",
125
+ "repoUrl": "https://gitlab.com/your-org/cube-schema.git",
126
+ "branch": "main",
127
+ "subPath": ""
128
+ },
129
+ "_notes": {
130
+ "auth": "For private repos, set GITLAB_TOKEN environment variable"
131
+ }
132
+ },
133
+
134
+ "_semantic_option_7_snowflake": {
135
+ "semanticLayer": {
136
+ "provider": "snowflake",
137
+ "projectPath": "MY_DATABASE"
138
+ },
139
+ "_notes": {
140
+ "how_it_works": "Introspects Snowflake semantic views (SHOW SEMANTIC VIEWS) via the active connection",
141
+ "requires": "Snowflake account with semantic views (CREATE SEMANTIC VIEW) and a configured Snowflake connection",
142
+ "projectPath_usage": "Optional: filters semantic views to a specific database"
143
+ }
144
+ },
145
+
146
+ "_comment_preview": "=== PREVIEW / NOTEBOOK OPTIONS ===",
147
+
148
+ "dataDir": "./data",
149
+ "preview": {
150
+ "port": 3474,
151
+ "open": true,
152
+ "theme": "dark"
153
+ }
154
+ }
@@ -5,6 +5,11 @@
5
5
  "filepath": ":memory:"
6
6
  },
7
7
  "dataDir": "./data",
8
+
9
+ "semanticLayer": {
10
+ "provider": "dql"
11
+ },
12
+
8
13
  "preview": {
9
14
  "port": 3474,
10
15
  "open": true,
@@ -0,0 +1,49 @@
1
+ # Customers cube — joinable from the orders cube.
2
+
3
+ name: customers
4
+ label: Customers Cube
5
+ description: Customer master data.
6
+ table: customers
7
+ domain: commerce
8
+
9
+ measures:
10
+ - name: customer_count
11
+ label: Customer Count
12
+ sql: COUNT(DISTINCT customer_id)
13
+ type: count_distinct
14
+ - name: avg_health_score
15
+ label: Average Health Score
16
+ sql: AVG(health_score)
17
+ type: avg
18
+
19
+ dimensions:
20
+ - name: customer_name
21
+ label: Customer Name
22
+ sql: customer_name
23
+ type: string
24
+ - name: segment
25
+ label: Segment
26
+ sql: segment
27
+ type: string
28
+ - name: region
29
+ label: Region
30
+ sql: region
31
+ type: string
32
+ - name: acquisition_channel
33
+ label: Acquisition Channel
34
+ sql: acquisition_channel
35
+ type: string
36
+
37
+ time_dimensions:
38
+ - name: first_order_date
39
+ label: First Order Date
40
+ sql: first_order_date
41
+ primary_time: true
42
+ granularities:
43
+ - month
44
+ - quarter
45
+ - year
46
+
47
+ tags:
48
+ - commerce
49
+ - customers
@@ -0,0 +1,70 @@
1
+ # Multi-table cube with joins — demonstrates cross-table semantic queries.
2
+ # This cube joins orders with customers to enable queries like:
3
+ # "total GMV by customer health_score and region"
4
+
5
+ name: orders
6
+ label: Orders Cube
7
+ description: E-commerce orders cube with customer join.
8
+ table: orders
9
+ domain: commerce
10
+
11
+ measures:
12
+ - name: gmv
13
+ label: Gross Merchandise Value
14
+ sql: SUM(order_total)
15
+ type: sum
16
+ - name: order_count
17
+ label: Order Count
18
+ sql: COUNT(order_id)
19
+ type: count
20
+ - name: avg_order_value
21
+ label: Average Order Value
22
+ sql: AVG(order_total)
23
+ type: avg
24
+ - name: avg_margin
25
+ label: Average Margin
26
+ sql: AVG(gross_margin)
27
+ type: avg
28
+
29
+ dimensions:
30
+ - name: segment
31
+ label: Segment
32
+ sql: segment
33
+ type: string
34
+ - name: channel
35
+ label: Channel
36
+ sql: channel
37
+ type: string
38
+ - name: region
39
+ label: Region
40
+ sql: region
41
+ type: string
42
+ - name: payment_method
43
+ label: Payment Method
44
+ sql: payment_method
45
+ type: string
46
+ - name: is_repeat
47
+ label: Repeat Customer
48
+ sql: is_repeat
49
+ type: boolean
50
+
51
+ time_dimensions:
52
+ - name: order_date
53
+ label: Order Date
54
+ sql: order_date
55
+ primary_time: true
56
+ granularities:
57
+ - day
58
+ - week
59
+ - month
60
+ - quarter
61
+ - year
62
+
63
+ joins:
64
+ - name: customers
65
+ type: left
66
+ sql: "${left}.customer_id = ${right}.customer_id"
67
+
68
+ tags:
69
+ - commerce
70
+ - ecommerce
@@ -1,4 +1,8 @@
1
1
  name: channel
2
2
  label: Channel
3
- domain: commerce
4
3
  description: Order acquisition channel.
4
+ sql: channel
5
+ type: string
6
+ table: orders
7
+ tags:
8
+ - commerce
@@ -0,0 +1,9 @@
1
+ name: order_date
2
+ label: Order Date
3
+ description: Date the order was placed.
4
+ sql: order_date
5
+ type: date
6
+ table: orders
7
+ tags:
8
+ - commerce
9
+ - time
@@ -0,0 +1,9 @@
1
+ name: region
2
+ label: Region
3
+ description: Geographic region of the order.
4
+ sql: region
5
+ type: string
6
+ table: orders
7
+ tags:
8
+ - commerce
9
+ - geo
@@ -0,0 +1,8 @@
1
+ name: segment
2
+ label: Customer Segment
3
+ description: Customer segment (Enterprise, Mid-Market, SMB).
4
+ sql: segment
5
+ type: string
6
+ table: orders
7
+ tags:
8
+ - commerce
@@ -0,0 +1,18 @@
1
+ name: customer_geo
2
+ label: Customer Geography
3
+ description: Drill from region down to customer segment.
4
+ domain: commerce
5
+ levels:
6
+ - name: region
7
+ label: Region
8
+ dimension: region
9
+ order: 1
10
+ - name: segment
11
+ label: Segment
12
+ dimension: segment
13
+ order: 2
14
+ - name: channel
15
+ label: Channel
16
+ dimension: channel
17
+ order: 3
18
+ defaultRollup: sum
@@ -0,0 +1,10 @@
1
+ name: avg_order_value
2
+ label: Average Order Value
3
+ description: Average revenue per order.
4
+ domain: commerce
5
+ sql: AVG(order_total)
6
+ type: avg
7
+ table: orders
8
+ tags:
9
+ - revenue
10
+ - commerce
@@ -1,4 +1,10 @@
1
1
  name: gmv
2
2
  label: Gross Merchandise Value
3
- domain: commerce
4
3
  description: Total order value across the commerce sample dataset.
4
+ domain: commerce
5
+ sql: SUM(order_total)
6
+ type: sum
7
+ table: orders
8
+ tags:
9
+ - revenue
10
+ - commerce
@@ -0,0 +1,10 @@
1
+ name: gross_margin
2
+ label: Gross Margin
3
+ description: Average gross margin percentage across orders.
4
+ domain: commerce
5
+ sql: AVG(gross_margin)
6
+ type: avg
7
+ table: orders
8
+ tags:
9
+ - profitability
10
+ - commerce
@@ -0,0 +1,10 @@
1
+ name: order_count
2
+ label: Order Count
3
+ description: Total number of orders.
4
+ domain: commerce
5
+ sql: COUNT(order_id)
6
+ type: count
7
+ table: orders
8
+ tags:
9
+ - orders
10
+ - commerce
@@ -5,6 +5,11 @@
5
5
  "filepath": ":memory:"
6
6
  },
7
7
  "dataDir": "./data",
8
+
9
+ "semanticLayer": {
10
+ "provider": "dql"
11
+ },
12
+
8
13
  "preview": {
9
14
  "port": 3474,
10
15
  "open": true,
@@ -0,0 +1,8 @@
1
+ name: owner_segment
2
+ label: Owner Segment
3
+ description: Account owner segment (Enterprise, Mid-Market, SMB).
4
+ sql: owner_segment
5
+ type: string
6
+ table: subscriptions
7
+ tags:
8
+ - saas
@@ -0,0 +1,8 @@
1
+ name: plan_tier
2
+ label: Plan Tier
3
+ description: Subscription plan tier (Starter, Growth, Enterprise).
4
+ sql: plan_tier
5
+ type: string
6
+ table: subscriptions
7
+ tags:
8
+ - saas
@@ -0,0 +1,9 @@
1
+ name: risk_bucket
2
+ label: Risk Bucket
3
+ description: Account risk level (low, medium, high).
4
+ sql: risk_bucket
5
+ type: string
6
+ table: subscriptions
7
+ tags:
8
+ - saas
9
+ - risk
@@ -0,0 +1,8 @@
1
+ name: status
2
+ label: Account Status
3
+ description: Subscription status (active, at_risk, churned).
4
+ sql: status
5
+ type: string
6
+ table: subscriptions
7
+ tags:
8
+ - saas
@@ -0,0 +1,18 @@
1
+ name: account_segments
2
+ label: Account Segments
3
+ description: Drill from owner segment to plan tier to risk bucket.
4
+ domain: saas
5
+ levels:
6
+ - name: owner_segment
7
+ label: Owner Segment
8
+ dimension: owner_segment
9
+ order: 1
10
+ - name: plan_tier
11
+ label: Plan Tier
12
+ dimension: plan_tier
13
+ order: 2
14
+ - name: risk_bucket
15
+ label: Risk Bucket
16
+ dimension: risk_bucket
17
+ order: 3
18
+ defaultRollup: sum
@@ -0,0 +1,10 @@
1
+ name: account_count
2
+ label: Account Count
3
+ description: Total number of accounts.
4
+ domain: saas
5
+ sql: COUNT(DISTINCT account_id)
6
+ type: count_distinct
7
+ table: subscriptions
8
+ tags:
9
+ - accounts
10
+ - saas
@@ -0,0 +1,11 @@
1
+ name: expansion_mrr
2
+ label: Expansion MRR
3
+ description: Additional MRR from upsells and expansions.
4
+ domain: saas
5
+ sql: SUM(expansion_mrr)
6
+ type: sum
7
+ table: subscriptions
8
+ tags:
9
+ - revenue
10
+ - saas
11
+ - growth
@@ -1,4 +1,10 @@
1
1
  name: mrr
2
2
  label: Monthly Recurring Revenue
3
- domain: saas
4
3
  description: Monthly recurring revenue across active subscriptions.
4
+ domain: saas
5
+ sql: SUM(mrr)
6
+ type: sum
7
+ table: subscriptions
8
+ tags:
9
+ - revenue
10
+ - saas
@@ -5,6 +5,11 @@
5
5
  "filepath": ":memory:"
6
6
  },
7
7
  "dataDir": "./data",
8
+
9
+ "semanticLayer": {
10
+ "provider": "dql"
11
+ },
12
+
8
13
  "preview": {
9
14
  "port": 3474,
10
15
  "open": true,
@@ -0,0 +1,60 @@
1
+ {
2
+ "version": 1,
3
+ "title": "Semantic Layer Tutorial",
4
+ "cells": [
5
+ {
6
+ "id": "intro_1",
7
+ "type": "markdown",
8
+ "content": "# Semantic Layer Tutorial\n\nThis notebook walks you through setting up and using the DQL semantic layer.\n\nThe semantic layer lets you define **reusable metrics, dimensions, and hierarchies** in YAML files. Once defined, they appear in the sidebar panel and can be queried via the API.\n\n---\n\n## Prerequisites\n\nMake sure your `dql.config.json` has:\n\n```json\n\"semanticLayer\": {\n \"provider\": \"dql\"\n}\n```\n\nAnd you have YAML files in `semantic-layer/metrics/`, `semantic-layer/dimensions/`, etc."
9
+ },
10
+ {
11
+ "id": "check_1",
12
+ "type": "markdown",
13
+ "content": "## Step 1: Verify your data\n\nFirst, let's make sure you have data to work with. The starter template includes `data/revenue.csv`."
14
+ },
15
+ {
16
+ "id": "query_1",
17
+ "type": "sql",
18
+ "name": "preview_data",
19
+ "content": "SELECT * FROM read_csv_auto('./data/revenue.csv') LIMIT 10"
20
+ },
21
+ {
22
+ "id": "step2_md",
23
+ "type": "markdown",
24
+ "content": "## Step 2: Understand the YAML definitions\n\nYour `semantic-layer/` directory should contain:\n\n```\nsemantic-layer/\n├── metrics/\n│ └── revenue.yaml # SUM(amount) as total_revenue\n├── dimensions/\n│ └── segment_tier.yaml # segment_tier column\n├── hierarchies/\n│ └── revenue_time.yaml # fiscal_year → fiscal_quarter drill path\n└── cubes/\n └── revenue_cube.yaml # groups everything into one model\n```\n\n### Metric YAML format\n```yaml\nname: total_revenue\nlabel: Total Revenue\ndescription: Sum of recognized revenue\nsql: SUM(amount) # the SQL aggregate expression\ntype: sum # sum|count|count_distinct|avg|min|max\ntable: fct_revenue # which table this metric belongs to\ntags: [revenue, kpi]\n```\n\n### Dimension YAML format\n```yaml\nname: segment_tier\nlabel: Segment Tier\nsql: segment_tier # the column expression\ntype: string # string|number|date|boolean\ntable: fct_revenue\n```"
25
+ },
26
+ {
27
+ "id": "step3_md",
28
+ "type": "markdown",
29
+ "content": "## Step 3: Query using semantic layer concepts\n\nYou can write SQL queries that use the same columns and aggregates defined in your semantic layer. The metric `total_revenue` is defined as `SUM(amount)` and the dimension `segment_tier` maps to the `segment_tier` column."
30
+ },
31
+ {
32
+ "id": "query_2",
33
+ "type": "sql",
34
+ "name": "revenue_by_segment",
35
+ "content": "-- This query mirrors the semantic layer definitions:\n-- metric: total_revenue = SUM(amount)\n-- dimension: segment_tier\nSELECT\n segment_tier,\n SUM(amount) AS total_revenue,\n COUNT(*) AS deal_count,\n AVG(amount) AS avg_deal_size\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY segment_tier\nORDER BY total_revenue DESC"
36
+ },
37
+ {
38
+ "id": "step4_md",
39
+ "type": "markdown",
40
+ "content": "## Step 4: Use hierarchies for drill-down\n\nThe `revenue_time` hierarchy defines a drill path: **fiscal_year → fiscal_quarter**.\n\nStart at the top level (year), then drill into quarters."
41
+ },
42
+ {
43
+ "id": "query_3",
44
+ "type": "sql",
45
+ "name": "revenue_by_year",
46
+ "content": "-- Hierarchy level 1: fiscal_year\nSELECT\n fiscal_year,\n SUM(amount) AS total_revenue\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY fiscal_year\nORDER BY fiscal_year"
47
+ },
48
+ {
49
+ "id": "query_4",
50
+ "type": "sql",
51
+ "name": "revenue_by_quarter",
52
+ "content": "-- Hierarchy level 2: drill into fiscal_quarter\nSELECT\n fiscal_year,\n fiscal_quarter,\n SUM(amount) AS total_revenue\nFROM read_csv_auto('./data/revenue.csv')\nGROUP BY fiscal_year, fiscal_quarter\nORDER BY fiscal_year, fiscal_quarter"
53
+ },
54
+ {
55
+ "id": "step5_md",
56
+ "type": "markdown",
57
+ "content": "## Step 5: Explore in the sidebar\n\nClick the **Semantic Layer icon** (3rd icon in the left activity bar) to see:\n\n- **Metrics** — your defined aggregations with type badges (sum, count, avg...)\n- **Dimensions** — grouping columns with type indicators\n- **Hierarchies** — expandable drill paths\n\nYou can search and click any item to see its details.\n\n---\n\n## What's next?\n\n### Connect to dbt\nIf you have a dbt project with `semantic_models`, update `dql.config.json`:\n```json\n\"semanticLayer\": {\n \"provider\": \"dbt\",\n \"projectPath\": \"/path/to/your/dbt-project\"\n}\n```\n\n### Connect to Cube.js\n```json\n\"semanticLayer\": {\n \"provider\": \"cubejs\",\n \"projectPath\": \"/path/to/your/cube-project\"\n}\n```\n\n### Use cubes for multi-table models\nCreate `semantic-layer/cubes/my_cube.yaml` to define measures, dimensions, time dimensions, and joins all in one file. See the Reference panel (Help icon) for the full YAML format.\n\n### Full reference\nClick the **Help icon** (bottom of sidebar) → **Semantic Layer** and **Semantic Layer Providers** sections for complete YAML formats and config examples."
58
+ }
59
+ ]
60
+ }
@@ -0,0 +1,77 @@
1
+ # Cube Definition — groups measures, dimensions, time dimensions, and joins
2
+ # into a single semantic model. This is the recommended way to define
3
+ # complex, multi-table semantic layers.
4
+ #
5
+ # The DQL notebook will automatically discover this cube and display
6
+ # its measures and dimensions in the Semantic Layer sidebar panel.
7
+
8
+ name: revenue
9
+ label: Revenue Cube
10
+ description: Core revenue analysis cube built on the starter revenue data.
11
+ table: read_csv_auto('./data/revenue.csv')
12
+ domain: revenue
13
+ owner: analytics-team
14
+
15
+ # Measures — aggregate calculations shown as "Metrics" in the UI
16
+ measures:
17
+ - name: total_revenue
18
+ label: Total Revenue
19
+ description: Sum of all recognized revenue.
20
+ sql: SUM(amount)
21
+ type: sum
22
+ tags:
23
+ - revenue
24
+ - kpi
25
+
26
+ - name: deal_count
27
+ label: Deal Count
28
+ description: Number of revenue deals.
29
+ sql: COUNT(*)
30
+ type: count
31
+
32
+ - name: avg_deal_size
33
+ label: Average Deal Size
34
+ description: Average revenue per deal.
35
+ sql: AVG(amount)
36
+ type: avg
37
+ tags:
38
+ - revenue
39
+
40
+ # Dimensions — grouping columns shown as "Dimensions" in the UI
41
+ dimensions:
42
+ - name: segment_tier
43
+ label: Segment Tier
44
+ description: Customer segment (Enterprise, Mid-Market, SMB).
45
+ sql: segment_tier
46
+ type: string
47
+
48
+ - name: fiscal_period
49
+ label: Fiscal Period
50
+ description: Fiscal period classification.
51
+ sql: fiscal_period
52
+ type: string
53
+
54
+ # Time Dimensions — date columns with granularity support (day/week/month/quarter/year)
55
+ time_dimensions:
56
+ - name: recognized_at
57
+ label: Recognition Date
58
+ description: Date revenue was recognized.
59
+ sql: recognized_at
60
+ primary_time: true
61
+ granularities:
62
+ - day
63
+ - week
64
+ - month
65
+ - quarter
66
+ - year
67
+
68
+ # Joins — connect this cube to other cubes for cross-table queries
69
+ # Example (uncomment if you have a customers cube):
70
+ # joins:
71
+ # - name: customers
72
+ # type: left
73
+ # sql: "${left}.customer_id = ${right}.id"
74
+
75
+ tags:
76
+ - revenue
77
+ - starter
@@ -3,4 +3,4 @@ label: Segment Tier
3
3
  description: Customer segment tier
4
4
  sql: segment_tier
5
5
  type: string
6
- table: fct_revenue
6
+ table: read_csv_auto('./data/revenue.csv')