@gscdump/engine-duckdb-wasm 0.25.6 → 0.25.8
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/index.mjs +45 -24
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -77,6 +77,37 @@ function rangePredicate(q) {
|
|
|
77
77
|
]
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
+
function facetPredicate(query) {
|
|
81
|
+
const facets = query.facets;
|
|
82
|
+
if (!facets?.length) return {
|
|
83
|
+
sql: "",
|
|
84
|
+
params: []
|
|
85
|
+
};
|
|
86
|
+
const parts = [];
|
|
87
|
+
const params = [];
|
|
88
|
+
for (const f of facets) {
|
|
89
|
+
const col = DIM_COLUMN[f.column] ?? f.column;
|
|
90
|
+
switch (f.op) {
|
|
91
|
+
case "eq":
|
|
92
|
+
parts.push(`${col} = ?`);
|
|
93
|
+
params.push(f.value);
|
|
94
|
+
break;
|
|
95
|
+
case "regex":
|
|
96
|
+
parts.push(`regexp_matches(LOWER(${col}), ?)`);
|
|
97
|
+
params.push(f.value);
|
|
98
|
+
break;
|
|
99
|
+
case "notRegex":
|
|
100
|
+
parts.push(`NOT regexp_matches(LOWER(${col}), ?)`);
|
|
101
|
+
params.push(f.value);
|
|
102
|
+
break;
|
|
103
|
+
default: throw new Error(`[archetype-sql] unknown facet op: ${f.op}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
sql: parts.length ? ` AND ${parts.join(" AND ")}` : "",
|
|
108
|
+
params
|
|
109
|
+
};
|
|
110
|
+
}
|
|
80
111
|
function compileArchetypeSql(query) {
|
|
81
112
|
switch (query.archetype) {
|
|
82
113
|
case "site-daily-timeseries": {
|
|
@@ -134,8 +165,13 @@ function compileArchetypeSql(query) {
|
|
|
134
165
|
};
|
|
135
166
|
}
|
|
136
167
|
const col = DIM_COLUMN[query.dimension];
|
|
137
|
-
|
|
138
|
-
|
|
168
|
+
const facet = facetPredicate(query);
|
|
169
|
+
let sql = `SELECT ${col} AS ${query.dimension}, ${metricSelectList(query.metrics)} FROM ${table} WHERE ${where.sql}${facet.sql} GROUP BY ${col} ORDER BY ${query.orderBy.metric} ${dir} LIMIT ?`;
|
|
170
|
+
const params = [
|
|
171
|
+
...where.params,
|
|
172
|
+
...facet.params,
|
|
173
|
+
query.limit
|
|
174
|
+
];
|
|
139
175
|
if (query.offset && query.offset > 0) {
|
|
140
176
|
sql += " OFFSET ?";
|
|
141
177
|
params.push(query.offset);
|
|
@@ -183,29 +219,10 @@ function compileArchetypeSql(query) {
|
|
|
183
219
|
params: where.params
|
|
184
220
|
};
|
|
185
221
|
}
|
|
186
|
-
case "preset-analyzer": {
|
|
187
|
-
const table = "queries";
|
|
188
|
-
const where = rangePredicate(query);
|
|
189
|
-
const params = query.params ?? {};
|
|
190
|
-
const minPos = Number(params.minPosition ?? 4);
|
|
191
|
-
const maxPos = Number(params.maxPosition ?? 20);
|
|
192
|
-
const minImpr = Number(params.minImpressions ?? 10);
|
|
193
|
-
const limit = Number(params.limit ?? 1e3);
|
|
194
|
-
return {
|
|
195
|
-
table,
|
|
196
|
-
sql: `SELECT query, ${metricExpr("clicks")} AS clicks, ${metricExpr("impressions")} AS impressions, ${metricExpr("position")} AS position FROM ${table} WHERE ${where.sql} GROUP BY query HAVING position BETWEEN ? AND ? AND impressions > ? ORDER BY impressions DESC LIMIT ?`,
|
|
197
|
-
params: [
|
|
198
|
-
...where.params,
|
|
199
|
-
minPos,
|
|
200
|
-
maxPos,
|
|
201
|
-
minImpr,
|
|
202
|
-
limit
|
|
203
|
-
]
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
222
|
case "two-dimension-detail": {
|
|
207
223
|
const table = "page_queries";
|
|
208
224
|
const where = rangePredicate(query);
|
|
225
|
+
const facet = facetPredicate(query);
|
|
209
226
|
const filterParts = [];
|
|
210
227
|
const filterParams = [];
|
|
211
228
|
if (query.filter?.page) {
|
|
@@ -217,8 +234,12 @@ function compileArchetypeSql(query) {
|
|
|
217
234
|
filterParams.push(query.filter.query);
|
|
218
235
|
}
|
|
219
236
|
const filterSql = filterParts.length ? ` AND ${filterParts.join(" AND ")}` : "";
|
|
220
|
-
let sql = `SELECT url AS page, query, ${metricSelectList(query.metrics)} FROM ${table} WHERE ${where.sql}${filterSql} GROUP BY url, query`;
|
|
221
|
-
const params = [
|
|
237
|
+
let sql = `SELECT url AS page, query, ${metricSelectList(query.metrics)} FROM ${table} WHERE ${where.sql}${filterSql}${facet.sql} GROUP BY url, query`;
|
|
238
|
+
const params = [
|
|
239
|
+
...where.params,
|
|
240
|
+
...filterParams,
|
|
241
|
+
...facet.params
|
|
242
|
+
];
|
|
222
243
|
if (query.orderBy) {
|
|
223
244
|
const dir = query.orderBy.dir === "asc" ? "ASC" : "DESC";
|
|
224
245
|
sql += ` ORDER BY ${query.orderBy.metric} ${dir}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gscdump/engine-duckdb-wasm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.25.
|
|
4
|
+
"version": "0.25.8",
|
|
5
5
|
"description": "DuckDB-WASM engine adapter for @gscdump/analysis — typed browser analytics against parquet via R2.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"drizzle-orm": "1.0.0-rc.3",
|
|
48
|
-
"@gscdump/engine": "0.25.
|
|
49
|
-
"
|
|
50
|
-
"gscdump": "0.25.
|
|
48
|
+
"@gscdump/engine": "0.25.8",
|
|
49
|
+
"gscdump": "0.25.8",
|
|
50
|
+
"@gscdump/sdk": "0.25.8"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@duckdb/duckdb-wasm": "^1.32.0",
|