Skip to content

Commit 6e87ea9

Browse files
authored
Merge pull request #3238 from Seb33300/fix-prefix
fix: improve prefix detection
2 parents 95a81bf + 8dc6a0f commit 6e87ea9

File tree

1 file changed

+59
-10
lines changed

1 file changed

+59
-10
lines changed

src/QueryDataTable.php

+59-10
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)