MCPcopy Create free account
hub / github.com/Openpanel-dev/openpanel / getSelectPropertyKey

Function getSelectPropertyKey

packages/db/src/services/chart.service.ts:317–381  ·  view source on GitHub ↗
(
  rawProperty: string,
  projectId?: string,
  cohortId?: string,
  cohortName?: string,
  /**
   * When set, the events table's `properties` map is qualified with this
   * alias (e.g. `e.properties[...]`). Required in any query where another
   * joined table also exposes a `properties` column (such as the groups
   * `_g` join), otherwise ClickHouse rejects with "ambiguous identifier".
   */
  eventsAlias?: string,
)

Source from the content-addressed store, hash-verified

315}
316
317export function getSelectPropertyKey(
318 rawProperty: string,
319 projectId?: string,
320 cohortId?: string,
321 cohortName?: string,
322 /**
323 * When set, the events table's `properties` map is qualified with this
324 * alias (e.g. `e.properties[...]`). Required in any query where another
325 * joined table also exposes a `properties` column (such as the groups
326 * `_g` join), otherwise ClickHouse rejects with "ambiguous identifier".
327 */
328 eventsAlias?: string,
329) {
330 // Map camelCase aliases (`referrerName` → `referrer_name`) and bare UTM
331 // names (`utm_source` → `properties.__query.utm_source`) into their
332 // canonical form before doing any pattern matching. The fallback at the
333 // bottom of this function returns `property` verbatim, so without this
334 // normalization an alias would leak into the generated SQL and fail with
335 // UNKNOWN_IDENTIFIER.
336 const property = normalizeEventField(rawProperty);
337 const extractedCohortId = cohortId || extractCohortId(property);
338
339 if (extractedCohortId && projectId) {
340 const cohortAlias = getCohortAlias(extractedCohortId);
341 const inLabel = cohortName
342 ? sqlstring.escape(cohortName)
343 : "'In Cohort'";
344 const notInLabel = cohortName
345 ? sqlstring.escape(`Not ${cohortName}`)
346 : "'Not In Cohort'";
347 return `if(notEmpty(${cohortAlias}.profile_id), ${inLabel}, ${notInLabel})`;
348 }
349
350 if (property === 'has_profile') {
351 return `if(profile_id != device_id, 'true', 'false')`;
352 }
353
354 // Handle group properties — requires ARRAY JOIN + _g JOIN to be present in query
355 if (property.startsWith('group.') && projectId) {
356 return getGroupPropertySql(property);
357 }
358
359 const propertyPatterns = ['properties', 'profile.properties'];
360
361 const match = propertyPatterns.find((pattern) =>
362 property.startsWith(`${pattern}.`)
363 );
364 if (!match) {
365 return property;
366 }
367
368 // Only the events table's bare `properties` map needs aliasing —
369 // `profile.properties` already routes through the profile join alias.
370 const aliasPrefix = match === 'properties' && eventsAlias
371 ? `${eventsAlias}.`
372 : '';
373
374 if (property.includes('*')) {

Callers 7

getFunnelMethod · 0.90
getTopLinkOutMethod · 0.90
getConversionMethod · 0.90
chart.tsFile · 0.90
getChartSqlFunction · 0.85
getAggregateChartSqlFunction · 0.85

Calls 6

normalizeEventFieldFunction · 0.85
extractCohortIdFunction · 0.85
getCohortAliasFunction · 0.85
getGroupPropertySqlFunction · 0.85
transformPropertyKeyFunction · 0.85
replaceMethod · 0.80

Tested by

no test coverage detected