@@ -475,20 +475,26 @@ protected function addTablePrefix($query, string $column): string
475475 return $ column ;
476476 }
477477
478- $ q = $ this ->getBaseQueryBuilder ($ query );
478+ // Extract selected columns from the query
479+ $ selects = $ this ->getSelectedColumns ($ query );
479480
480- // Column is an alias, no prefix required
481- foreach ($ q ->columns ?? [] as $ select ) {
482- $ sql = trim ($ select instanceof Expression ? $ select ->getValue ($ this ->getConnection ()->getQueryGrammar ()) : $ select );
483- $ match = preg_quote ($ column ).'\b| ' .preg_quote ($ this ->wrap ($ column ));
484- if (preg_match ("/(\s)as(\s+)( $ match)/i " , $ sql )) {
485- return $ column ;
486- }
481+ // We have a match
482+ if (isset ($ selects ['columns ' ][$ column ])) {
483+ return $ selects ['columns ' ][$ column ];
487484 }
488485
489- $ prefix = $ this ->getTablePrefix ($ query );
486+ // Multiple wildcards => Unable to determine prefix
487+ if (in_array ('* ' , $ selects ['wildcards ' ]) || count (array_unique ($ selects ['wildcards ' ])) > 1 ) {
488+ return $ column ;
489+ }
490490
491- return $ prefix ? $ prefix .'. ' .$ column : $ column ;
491+ // Use the only wildcard available
492+ if (! empty ($ selects ['wildcards ' ])) {
493+ return $ selects ['wildcards ' ][0 ].'. ' .$ column ;
494+ }
495+
496+ // Fallback on table prefix
497+ return ltrim ($ this ->getTablePrefix ($ query ).'. ' .$ column , '. ' );
492498 }
493499
494500 /**
@@ -513,6 +519,49 @@ protected function getTablePrefix($query): ?string
513519 return null ;
514520 }
515521
522+ /**
523+ * Get declared column names from the query.
524+ *
525+ * @param QueryBuilder|EloquentBuilder $query
526+ */
527+ protected function getSelectedColumns ($ query ): array
528+ {
529+ $ q = $ this ->getBaseQueryBuilder ($ query );
530+
531+ $ selects = [
532+ 'wildcards ' => [],
533+ 'columns ' => [],
534+ ];
535+
536+ foreach ($ q ->columns ?? [] as $ select ) {
537+ $ sql = trim ($ select instanceof Expression ? $ select ->getValue ($ this ->getConnection ()->getQueryGrammar ()) : $ select );
538+ // Remove expressions
539+ $ sql = preg_replace ('/\s*\w*\((?:[^()]*|(?R))*\)/ ' , '_ ' , $ sql );
540+ // Remove multiple spaces
541+ $ sql = preg_replace ('/\s+/ ' , ' ' , $ sql );
542+ // Remove wrappers
543+ $ sql = str_replace (['` ' , '" ' , '[ ' , '] ' ], '' , $ sql );
544+ // Loop on select columns
545+ foreach (explode (', ' , $ sql ) as $ column ) {
546+ $ column = trim ($ column );
547+ if (preg_match ('/[\w.]+\s+(?:as\s+)?([a-zA-Z0-9_]+)$/i ' , $ column , $ matches )) {
548+ // Column with alias
549+ $ selects ['columns ' ][$ matches [1 ]] = $ matches [1 ];
550+ } elseif (preg_match ('/^([\w.]+)$/i ' , $ column )) {
551+ // Column without alias
552+ [$ table , $ name ] = str_contains ($ column , '. ' ) ? explode ('. ' , $ column ) : [null , $ column ];
553+ if ($ name === '* ' ) {
554+ $ selects ['wildcards ' ][] = $ table ?? '* ' ;
555+ } else {
556+ $ selects ['columns ' ][$ name ] = $ column ;
557+ }
558+ }
559+ }
560+ }
561+
562+ return $ selects ;
563+ }
564+
516565 /**
517566 * Prepare search keyword based on configurations.
518567 */
0 commit comments