Skip to content

Commit 5b442bc

Browse files
avoiding using prefix for check condition (#171)
* avoiding using prefix for check condition * adding test
1 parent 7a031c6 commit 5b442bc

File tree

5 files changed

+134
-14
lines changed

5 files changed

+134
-14
lines changed

meerkat-browser/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/meerkat-browser",
3-
"version": "0.0.108",
3+
"version": "0.0.109",
44
"dependencies": {
55
"tslib": "^2.3.0",
66
"@devrev/meerkat-core": "*",

meerkat-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/meerkat-core",
3-
"version": "0.0.108",
3+
"version": "0.0.109",
44
"dependencies": {
55
"tslib": "^2.3.0"
66
},

meerkat-core/src/resolution/steps/resolution-step.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,9 @@ export const getResolvedTableSchema = async ({
9292
const resolutionDimensionsByColumnName = new Map<string, any[]>();
9393

9494
// Create a map of resolution schemas by config name for efficient lookup
95-
const resolutionSchemaByConfigName = new Map<
96-
string,
97-
(typeof resolutionSchemas)[0]
98-
>();
95+
const resolutionSchemaByConfigName = new Map<string, TableSchema>();
9996
resolutionSchemas.forEach((resSchema) => {
100-
resolutionConfig.columnConfigs.forEach((config) => {
101-
if (
102-
resSchema.dimensions.some((dim) => dim.name.startsWith(config.name))
103-
) {
104-
resolutionSchemaByConfigName.set(config.name, resSchema);
105-
}
106-
});
97+
resolutionSchemaByConfigName.set(resSchema.name, resSchema);
10798
});
10899

109100
// Build the dimension map using the pre-indexed schemas

meerkat-node/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@devrev/meerkat-node",
3-
"version": "0.0.108",
3+
"version": "0.0.109",
44
"dependencies": {
55
"@swc/helpers": "~0.5.0",
66
"@devrev/meerkat-core": "*",

meerkat-node/src/__tests__/cube-to-sql-with-resolution.spec.ts

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,4 +609,133 @@ describe('cubeQueryToSQLWithResolution - Array field resolution', () => {
609609
expect(ticket3!['Created By - Name']).toBe('User 3');
610610
expect(ticket3!['Owners']).toContain('owner4');
611611
});
612+
613+
it('Should handle fields with prefix names correctly (owners vs owners_field1)', async () => {
614+
// Add a new column to the existing tickets table for testing prefix collision
615+
await duckdbExec(`
616+
ALTER TABLE tickets ADD COLUMN owners_field1 VARCHAR[]
617+
`);
618+
619+
await duckdbExec(`
620+
UPDATE tickets SET owners_field1 = CASE
621+
WHEN id = 1 THEN ['owner1', 'owner3']
622+
WHEN id = 2 THEN ['owner2', 'owner4']
623+
WHEN id = 3 THEN ['owner1', 'owner4']
624+
END
625+
`);
626+
627+
// Create a table schema that includes both owners and owners_field1
628+
const ticketsWithPrefixSchema: TableSchema = {
629+
name: 'tickets',
630+
sql: 'select * from tickets',
631+
measures: [
632+
{
633+
name: 'count',
634+
sql: 'COUNT(*)',
635+
type: 'number',
636+
},
637+
],
638+
dimensions: [
639+
{
640+
alias: 'ID',
641+
name: 'id',
642+
sql: 'id',
643+
type: 'number',
644+
},
645+
{
646+
alias: 'Owners',
647+
name: 'owners',
648+
sql: 'owners',
649+
type: 'string_array',
650+
},
651+
{
652+
alias: 'Owners Field 1',
653+
name: 'owners_field1',
654+
sql: 'owners_field1',
655+
type: 'string_array',
656+
},
657+
],
658+
};
659+
660+
const query: Query = {
661+
measures: ['tickets.count'],
662+
dimensions: ['tickets.id', 'tickets.owners', 'tickets.owners_field1'],
663+
order: { 'tickets.id': 'asc' },
664+
};
665+
666+
const resolutionConfig: ResolutionConfig = {
667+
tableSchemas: [OWNERS_LOOKUP_SCHEMA],
668+
columnConfigs: [
669+
{
670+
name: 'tickets.owners',
671+
type: 'string_array' as const,
672+
source: 'owners_lookup',
673+
joinColumn: 'id',
674+
resolutionColumns: ['display_name', 'email'],
675+
},
676+
{
677+
name: 'tickets.owners_field1',
678+
type: 'string_array' as const,
679+
source: 'owners_lookup',
680+
joinColumn: 'id',
681+
resolutionColumns: ['display_name', 'email'],
682+
},
683+
],
684+
};
685+
686+
const sql = await cubeQueryToSQLWithResolution({
687+
query,
688+
tableSchemas: [ticketsWithPrefixSchema],
689+
resolutionConfig,
690+
columnProjections: [
691+
'tickets.owners',
692+
'tickets.owners_field1',
693+
'tickets.count',
694+
'tickets.id',
695+
],
696+
});
697+
698+
console.log('SQL (prefix test):', sql);
699+
700+
// Export to CSV using COPY command
701+
const csvPath = '/tmp/test_prefix_fields.csv';
702+
await duckdbExec(`COPY (${sql}) TO '${csvPath}' (HEADER, DELIMITER ',')`);
703+
704+
// Read the CSV back
705+
const result = (await duckdbExec(
706+
`SELECT * FROM read_csv_auto('${csvPath}')`
707+
)) as any[];
708+
console.log('Result from CSV (prefix test):', result);
709+
710+
// Check that both columns are present and resolved independently
711+
expect(result[0]).toHaveProperty('Owners - Display Name');
712+
expect(result[0]).toHaveProperty('Owners - Email');
713+
expect(result[0]).toHaveProperty('Owners Field 1 - Display Name');
714+
expect(result[0]).toHaveProperty('Owners Field 1 - Email');
715+
716+
// Verify the first ticket's data
717+
const ticket1Rows = result.filter((r: any) => Number(r.ID) === 1);
718+
719+
// Check owners field
720+
const ownersDisplayNames = parseJsonArray(
721+
ticket1Rows[0]['Owners - Display Name']
722+
);
723+
expect(Array.isArray(ownersDisplayNames)).toBe(true);
724+
expect(ownersDisplayNames).toContain('Alice Smith');
725+
expect(ownersDisplayNames).toContain('Bob Jones');
726+
727+
// Check owners_field1 field (should have different values)
728+
const ownersField1DisplayNames = parseJsonArray(
729+
ticket1Rows[0]['Owners Field 1 - Display Name']
730+
);
731+
expect(Array.isArray(ownersField1DisplayNames)).toBe(true);
732+
expect(ownersField1DisplayNames).toContain('Alice Smith');
733+
expect(ownersField1DisplayNames).toContain('Charlie Brown');
734+
735+
// Verify they are different arrays
736+
expect(ownersDisplayNames).not.toEqual(ownersField1DisplayNames);
737+
738+
// Clean up
739+
await duckdbExec('ALTER TABLE tickets DROP COLUMN owners_field1');
740+
});
612741
});

0 commit comments

Comments
 (0)