Skip to content

Commit

Permalink
Merge pull request coral-erm#9 from queryluke/improved-selective-join…
Browse files Browse the repository at this point in the history
…s-3.0.1-compat

ERM-56: Long load times in the Resources module
  • Loading branch information
brthompsonSirsi authored Dec 3, 2019
2 parents 4cc29d2 + c31aedd commit 6dd76ee
Showing 1 changed file with 121 additions and 52 deletions.
173 changes: 121 additions & 52 deletions resources/admin/classes/domain/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -529,22 +529,20 @@ public static function getSearchDetails() {

if ($config->settings->organizationsModule == 'Y') {
$dbName = $config->settings->organizationsDatabaseName;

$whereAdd[] = "((UPPER(R.titleText) LIKE " . $nameQueryString . ") OR (UPPER(A.shortName) LIKE " . $nameQueryString . ") OR (UPPER(O.name) LIKE " . $nameQueryString . ") OR (UPPER(OA.name) LIKE " . $nameQueryString . ") OR (UPPER(RP.titleText) LIKE " . $nameQueryString . ") OR (UPPER(RC.titleText) LIKE " . $nameQueryString . ") OR (UPPER(RA.recordSetIdentifier) LIKE " . $nameQueryString . "))";

}else{

$whereAdd[] = "((UPPER(R.titleText) LIKE " . $nameQueryString . ") OR (UPPER(A.shortName) LIKE " . $nameQueryString . ") OR (UPPER(O.shortName) LIKE " . $nameQueryString . ") OR (UPPER(RP.titleText) LIKE " . $nameQueryString . ") OR (UPPER(RC.titleText) LIKE " . $nameQueryString . ") OR (UPPER(RA.recordSetIdentifier) LIKE " . $nameQueryString . "))";

}

$searchDisplay[] = _("Name contains: ") . $search['name'];

}

//get where statements together (and escape single quotes)
if ($search['resourceISBNOrISSN']) {
$resourceISBNOrISSN = $resource->db->escapeString(str_replace("-","",$search['resourceISBNOrISSN']));
$whereAdd[] = "REPLACE(I.isbnOrIssn,'-','') = '" . $resourceISBNOrISSN . "'";
$whereAdd[] = "REPLACE(I.isbnOrIssn,'-','') = '" . $resourceISBNOrISSN . "'";
$searchDisplay[] = _("ISSN/ISBN: ") . $search['resourceISBNOrISSN'];
}

Expand Down Expand Up @@ -630,6 +628,7 @@ public static function getSearchDetails() {
$whereAdd[] = "RPAY.fundID = '" . $resource->db->escapeString($fund) . "'";
$searchDisplay[] = _("Fund: ") . $search['fund'];
}

if ($search['resourceTypeID'] == 'none') {
$whereAdd[] = "((R.resourceTypeID IS NULL) OR (R.resourceTypeID = '0'))";
$searchDisplay[] = _("Resource Type: none");
Expand Down Expand Up @@ -769,14 +768,97 @@ public function searchQuery($whereAdd, $orderBy = '', $limit = '', $count = fals
$config = new Configuration();
$status = new Status();

$joinTree = array(
"A" => array(
"stmt" => "LEFT JOIN Alias A ON R.resourceID = A.resourceID",
),
"AT" => array(
"stmt" => "LEFT JOIN AcquisitionType AT ON RA.acquisitionTypeID = AT.acquisitionTypeID",
"requires" => "RA"
),
"CU" => array(
"stmt" => "LEFT JOIN User CU ON R.createLoginID = CU.loginID",
),
"GDLINK" => array(
"stmt" => "LEFT JOIN GeneralDetailSubjectLink GDLINK ON RSUB.generalDetailSubjectLinkID = GDLINK.generalDetailSubjectLinkID",
"requires" => "RSUB"
),
"I" => array(
"stmt" => "LEFT JOIN IsbnOrIssn I ON R.resourceID = I.resourceID"
),
"RA" => array(
"stmt" => "LEFT JOIN ResourceAcquisition RA ON R.resourceID = RA.resourceID",
),
"RADSL" => array(
"stmt" => "LEFT JOIN ResourceAdministeringSiteLink RADSL ON RA.resourceAcquisitionID = RADSL.resourceAcquisitionID",
"requires" => "RA"
),
"RAUSL" => array(
"stmt" => "LEFT JOIN ResourceAuthorizedSiteLink RAUSL ON RA.resourceAcquisitionID = RAUSL.resourceAcquisitionID",
"requires" => "RA"
),
"RF" => array(
"stmt" => "LEFT JOIN ResourceFormat RF ON R.resourceFormatID = RF.resourceFormatID",
),
"RC" => array(
"stmt" => "LEFT JOIN Resource RC ON RC.resourceID = RRC.resourceID",
"requires" => "RRC"
),
"RNA" => array(
"stmt" => "LEFT JOIN ResourceNote RNA ON RA.resourceAcquisitionID = RNA.entityID",
"requires" => "RA"
),
"RNR" => array(
"stmt" => "LEFT JOIN ResourceNote RNR ON R.resourceID = RNR.entityID",
),
"RP" => array(
"stmt" => "LEFT JOIN Resource RP ON RP.resourceID = RRP.relatedResourceID",
"requires" => "RRP"
),
"RPAY" => array(
"stmt" => "LEFT JOIN ResourcePayment RPAY ON RA.resourceAcquisitionID = RPAY.resourceAcquisitionID",
"requires" => "RA"
),
"RPSL" => array(
"stmt" => "LEFT JOIN ResourcePurchaseSiteLink RPSL ON RA.resourceAcquisitionID = RPSL.resourceAcquisitionID",
"requires" => "RA"
),
"ROL" => array(
"stmt" => "LEFT JOIN ResourceOrganizationLink ROL ON R.resourceID = ROL.resourceID",
),
"RRC" => array(
"stmt" => "LEFT JOIN ResourceRelationship RRC ON RRC.relatedResourceID = R.resourceID",
),
"RRP" => array(
"stmt" => "LEFT JOIN ResourceRelationship RRP ON RRP.resourceID = R.resourceID",
),
"RS" => array(
"stmt" => "LEFT JOIN ResourceStep RS ON RA.resourceAcquisitionID = RS.resourceAcquisitionID",
"requires" => "RA"
),
"RSUB" => array(
"stmt" => "LEFT JOIN ResourceSubject RSUB ON R.resourceID = RSUB.resourceID",
),
"RT" => array(
"stmt" => "LEFT JOIN ResourceType RT ON R.resourceTypeID = RT.resourceTypeID",
),
"S" => array(
"stmt" => "LEFT JOIN Status S ON R.statusID = S.statusID",
),
);

if ($config->settings->organizationsModule == 'Y') {
$dbName = $config->settings->organizationsDatabaseName;

$orgJoinAdd = "LEFT JOIN " . $dbName . ".Organization O ON O.organizationID = ROL.organizationID
LEFT JOIN " . $dbName . ".Alias OA ON OA.organizationID = ROL.organizationID";

$joinTree["O"] = array(
"stmt" => "LEFT JOIN " . $dbName . ".Organization O ON O.organizationID = ROL.organizationID
LEFT JOIN " . $dbName . ".Alias OA ON OA.organizationID = ROL.organizationID",
"requires" => "ROL"
);
}else{
$orgJoinAdd = "LEFT JOIN Organization O ON O.organizationID = ROL.organizationID";
$joinTree["O"] = array(
"stmt" => "LEFT JOIN Organization O ON O.organizationID = ROL.organizationID",
"requires" => "ROL"
);
}

$savedStatusID = intval($status->getIDFromName('saved'));
Expand All @@ -798,59 +880,46 @@ public function searchQuery($whereAdd, $orderBy = '', $limit = '', $count = fals
$groupBy = "GROUP BY R.resourceID";
}

$referenced_tables = array();
// Build a list of tables that are referenced by the select and where statements in order to limit the number of joins performed in the search.
preg_match_all("/[A-Z]+(?=[.][A-Z]+)/iu", $select, $table_matches);
$referenced_tables = array_unique($table_matches[0]);

$table_matches = array();
preg_match_all("/[A-Z]+(?=[.][A-Z]+)/iu", $whereStatement, $table_matches);
$referenced_tables = array_unique(array_merge($referenced_tables, $table_matches[0]));
// Remove the R table
if (($key = array_search('R', $referenced_tables)) !== false) {
unset($referenced_tables[$key]);
}

// Build a list of tables that are referenced by the select and where statements in order to limit the number of joins performed in the search.
preg_match_all("/[A-Z]+(?=[.][A-Z]+)/iu", $select, $table_matches);
$referenced_tables = array_unique($table_matches[0]);
$joinStmts = array();

preg_match_all("/[A-Z]+(?=[.][A-Z]+)/iu", $whereStatement, $table_matches);
$referenced_tables = array_unique(array_merge($referenced_tables, $table_matches[0]));
if (!empty($referenced_tables)) {
$alreadyJoined = array();

// These join statements will only be included in the query if the alias is referenced by the select and/or where.
$conditional_joins = explode("\n", "LEFT JOIN ResourceFormat RF ON R.resourceFormatID = RF.resourceFormatID
LEFT JOIN ResourceType RT ON R.resourceTypeID = RT.resourceTypeID
LEFT JOIN AcquisitionType AT ON RA.acquisitionTypeID = AT.acquisitionTypeID
LEFT JOIN Status S ON R.statusID = S.statusID
LEFT JOIN User CU ON R.createLoginID = CU.loginID
LEFT JOIN ResourcePurchaseSiteLink RPSL ON RA.resourceAcquisitionID = RPSL.resourceAcquisitionID
LEFT JOIN ResourceAuthorizedSiteLink RAUSL ON RA.resourceAcquisitionID = RAUSL.resourceAcquisitionID
LEFT JOIN ResourceAdministeringSiteLink RADSL ON RA.resourceAcquisitionID = RADSL.resourceAcquisitionID
LEFT JOIN ResourceNote RNA ON RA.resourceAcquisitionID = RNA.entityID
LEFT JOIN ResourceNote RNR ON R.resourceID = RNR.entityID
LEFT JOIN ResourcePayment RPAY ON RA.resourceAcquisitionID = RPAY.resourceAcquisitionID
LEFT JOIN ResourceStep RS ON RA.resourceAcquisitionID = RS.resourceAcquisitionID
LEFT JOIN IsbnOrIssn I ON R.resourceID = I.resourceID
");

$additional_joins = array();
foreach($referenced_tables as $join) {
// Prevent joining more than once
if (in_array($join, $alreadyJoined)) {
continue;
}

foreach($conditional_joins as $join) {
// drop the last line of $conditional_joins which is empty
if (trim($join) == "") { break; }
// If the table requires another linking table, join that first
if(!empty($joinTree[$join]['requires'])) {
// Prevent joining parents more than once
$parent = $joinTree[$join]['requires'];
if (!in_array($parent, $alreadyJoined)) {
$joinStmts[] = $joinTree[$parent]['stmt'];
$alreadyJoined[] = $parent;
}
}

$match = array();
preg_match("/[A-Z]+(?= ON )/i", $join, $match);
$table_name = $match[0];
if (in_array($table_name, $referenced_tables)) {
$additional_joins[] = $join;
$joinStmts[] = $joinTree[$join]['stmt'];
$alreadyJoined[] = $join;
}
}

$query = $select . "
FROM Resource R
LEFT JOIN ResourceAcquisition RA ON R.resourceID = RA.resourceID
LEFT JOIN Alias A ON R.resourceID = A.resourceID
LEFT JOIN ResourceOrganizationLink ROL ON R.resourceID = ROL.resourceID
" . $orgJoinAdd . "
LEFT JOIN ResourceRelationship RRC ON RRC.relatedResourceID = R.resourceID
LEFT JOIN ResourceRelationship RRP ON RRP.resourceID = R.resourceID
LEFT JOIN ResourceSubject RSUB ON R.resourceID = RSUB.resourceID
LEFT JOIN Resource RC ON RC.resourceID = RRC.resourceID
LEFT JOIN Resource RP ON RP.resourceID = RRP.relatedResourceID
LEFT JOIN GeneralDetailSubjectLink GDLINK ON RSUB.generalDetailSubjectLinkID = GDLINK.generalDetailSubjectLinkID
" . implode("\n", $additional_joins) . "
" . implode("\n", $joinStmts) . "
" . $whereStatement . "
" . $groupBy;

Expand Down

0 comments on commit 6dd76ee

Please sign in to comment.