Skip to content

Commit cd84557

Browse files
authored
Merge pull request #32474 from colemanw/databaseName
Api4 - Support entities in alternate databases
2 parents bf8e8e4 + 4793f98 commit cd84557

File tree

4 files changed

+40
-19
lines changed

4 files changed

+40
-19
lines changed

Civi/Api4/Entity.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class Entity extends Generic\AbstractEntity {
6565
'name' => 'table_name',
6666
'description' => 'Name of sql table, if applicable',
6767
],
68+
[
69+
'name' => 'database_name',
70+
'description' => 'Name of sql database, if different from CiviCRM',
71+
],
6872
[
6973
'name' => 'primary_key',
7074
'data_type' => 'Array',

Civi/Api4/Query/Api4SelectQuery.php

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ public function __construct($api) {
7777
$this->addSpecField($field['name'], $field);
7878
}
7979

80-
$tableName = CoreUtil::getTableName($this->getEntity());
81-
$this->query = \CRM_Utils_SQL_Select::from($tableName . ' ' . self::MAIN_TABLE_ALIAS);
80+
$tableExpr = CoreUtil::getTableExpr($this->getEntity());
81+
$this->query = \CRM_Utils_SQL_Select::from($tableExpr . ' ' . self::MAIN_TABLE_ALIAS);
8282

8383
$this->fillEntityValues();
8484

@@ -486,7 +486,8 @@ private function addExplicitJoins() {
486486
$this->addSpecField($alias . '.' . $field['name'], $field);
487487
}
488488
$tableName = CoreUtil::getTableName($entity);
489-
$this->startNewJoin($tableName, $alias);
489+
$tableExpr = CoreUtil::getTableExpr($entity);
490+
$this->startNewJoin($tableExpr, $alias);
490491
// Save join info to be retrieved by $this->getExplicitJoin()
491492
$joinOn = array_filter(array_filter($join, 'is_array'));
492493
$this->explicitJoins[$alias] = [
@@ -601,8 +602,9 @@ protected function addBridgeJoin($joinTree, $joinEntity, $alias) {
601602

602603
$bridgeAlias = $alias . '_via_' . strtolower($bridgeEntity);
603604

604-
$joinTable = CoreUtil::getTableName($joinEntity);
605-
[$bridgeTable, $baseRef, $joinRef] = $this->getBridgeRefs($bridgeEntity, $joinEntity);
605+
$joinTableExpr = CoreUtil::getTableExpr($joinEntity);
606+
$bridgeTableExpr = CoreUtil::getTableExpr($bridgeEntity);
607+
[$baseRef, $joinRef] = $this->getBridgeRefs($bridgeEntity, $joinEntity);
606608

607609
$this->registerBridgeJoinFields($bridgeEntity, $joinRef, $baseRef, $alias, $bridgeAlias);
608610

@@ -630,12 +632,12 @@ protected function addBridgeJoin($joinTree, $joinEntity, $alias) {
630632
// Info needed for joining custom fields extending the bridge entity
631633
$this->explicitJoins[$alias]['bridge_table_alias'] = $bridgeAlias;
632634
// Invert the join so all nested joins will link to the bridge entity
633-
$this->openJoin['table'] = $bridgeTable;
635+
$this->openJoin['table'] = $bridgeTableExpr;
634636
$this->openJoin['alias'] = $bridgeAlias;
635637

636638
// Add main table as inner join
637639
$innerConditions = array_merge($linkConditions, $acls);
638-
$this->addJoin('INNER', $joinTable, $alias, $bridgeAlias, $innerConditions);
640+
$this->addJoin('INNER', $joinTableExpr, $alias, $bridgeAlias, $innerConditions);
639641
return array_merge($outerConditions, $bridgeConditions);
640642
}
641643

@@ -652,7 +654,6 @@ private function getBridgeRefs(string $bridgeEntity, string $joinEntity): array
652654
/** @var \CRM_Core_DAO $bridgeDAO */
653655
$bridgeDAO = CoreUtil::getInfoItem($bridgeEntity, 'dao');
654656
$bridgeEntityFields = \Civi\API\Request::create($bridgeEntity, 'get', ['version' => 4, 'checkPermissions' => $this->getCheckPermissions()])->entityFields();
655-
$bridgeTable = $bridgeDAO::getTableName();
656657

657658
// Get the 2 bridge reference columns as CRM_Core_Reference_* objects
658659
$referenceColumns = $bridgeDAO::getReferenceColumns();
@@ -664,7 +665,7 @@ private function getBridgeRefs(string $bridgeEntity, string $joinEntity): array
664665
}
665666
foreach ($bridgeDAO::getReferenceColumns() as $baseRef) {
666667
if ($baseRef->getReferenceKey() === $bridges[$refKey]['to']) {
667-
return [$bridgeTable, $baseRef, $joinRef];
668+
return [$baseRef, $joinRef];
668669
}
669670
}
670671
}
@@ -887,43 +888,43 @@ protected function autoJoinFK($key) {
887888
/**
888889
* Begins a new join; as long as it's "open" then additional joins will nest inside it.
889890
*/
890-
private function startNewJoin(string $tableName, string $joinAlias): void {
891+
private function startNewJoin(string $tableExpr, string $joinAlias): void {
891892
$this->openJoin = [
892-
'table' => $tableName,
893+
'table' => $tableExpr,
893894
'alias' => $joinAlias,
894895
'subjoins' => [],
895896
];
896897
}
897898

898899
private function finishJoin(string $side, $conditions): void {
899900
$tableAlias = $this->openJoin['alias'];
900-
$tableName = $this->openJoin['table'];
901+
$tableExpr = $this->openJoin['table'];
901902
$subjoinClause = '';
902903
foreach ($this->openJoin['subjoins'] as $subjoin) {
903-
$subjoinClause .= " INNER JOIN `{$subjoin['table']}` `{$subjoin['alias']}` ON (" . implode(' AND ', $subjoin['conditions']) . ")";
904+
$subjoinClause .= " INNER JOIN {$subjoin['table']} `{$subjoin['alias']}` ON (" . implode(' AND ', $subjoin['conditions']) . ")";
904905
}
905-
$this->query->join($tableAlias, "$side JOIN (`$tableName` `$tableAlias`$subjoinClause) ON " . implode(' AND ', $conditions));
906+
$this->query->join($tableAlias, "$side JOIN ($tableExpr `$tableAlias`$subjoinClause) ON " . implode(' AND ', $conditions));
906907
$this->openJoin = NULL;
907908
}
908909

909910
/**
910911
* @param string $side
911-
* @param string $tableName
912+
* @param string $tableExpr
912913
* @param string $tableAlias
913914
* @param string $baseTableAlias
914915
* @param array $conditions
915916
*/
916-
private function addJoin(string $side, string $tableName, string $tableAlias, string $baseTableAlias, array $conditions): void {
917+
private function addJoin(string $side, string $tableExpr, string $tableAlias, string $baseTableAlias, array $conditions): void {
917918
// If this join is based off the current open join, incorporate it
918919
if ($baseTableAlias === ($this->openJoin['alias'] ?? NULL)) {
919920
$this->openJoin['subjoins'][] = [
920-
'table' => $tableName,
921+
'table' => $tableExpr,
921922
'alias' => $tableAlias,
922923
'conditions' => $conditions,
923924
];
924925
}
925926
else {
926-
$this->query->join($tableAlias, "$side JOIN `$tableName` `$tableAlias` ON " . implode(' AND ', $conditions));
927+
$this->query->join($tableAlias, "$side JOIN $tableExpr `$tableAlias` ON " . implode(' AND ', $conditions));
927928
}
928929
}
929930

Civi/Api4/Utils/CoreUtil.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,22 @@ public static function getTableName(string $entityName): ?string {
135135
return self::getInfoItem($entityName, 'table_name');
136136
}
137137

138+
/**
139+
* Get sql for table, including database prefix if needed
140+
*
141+
* @param string $entityName
142+
*
143+
* @return string|null
144+
*/
145+
public static function getTableExpr(string $entityName): ?string {
146+
$tableName = self::getInfoItem($entityName, 'table_name');
147+
$databaseName = self::getInfoItem($entityName, 'database_name');
148+
if ($databaseName) {
149+
return "`$databaseName`.`$tableName`";
150+
}
151+
return "`$tableName`";
152+
}
153+
138154
/**
139155
* Given a sql table name, return the name of the api entity.
140156
*

tests/phpunit/api/v4/Query/Api4SelectQueryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public function testAggregateNoGroupBy(): void {
6767
$query = new Api4SelectQuery($api);
6868
$this->assertEquals(
6969
'SELECT SUM(`a`.`amount`) AS `SUM_amount`
70-
FROM civicrm_pledge a',
70+
FROM `civicrm_pledge` a',
7171
trim($query->getSql())
7272
);
7373
}

0 commit comments

Comments
 (0)