@@ -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