Commit 80a7c793c49d55cd2cf8f62ea2d5b749d17126d3
1 parent
ac7fc794
Pivotal Tracker: 676448 Refactored getList() to use loadFromArray() instead of r…
…epeatedly hitting the database using get(). Committed by: Megan Watson
Showing
1 changed file
with
120 additions
and
173 deletions
lib/ktentity.inc
| ... | ... | @@ -333,6 +333,7 @@ class KTEntity { |
| 333 | 333 | } |
| 334 | 334 | |
| 335 | 335 | $array = array_keys($this->_aFieldToSelect); |
| 336 | + $array2 = array_flip($this->_aFieldToSelect); | |
| 336 | 337 | |
| 337 | 338 | if (!$aCache) { |
| 338 | 339 | $case = array(); |
| ... | ... | @@ -342,6 +343,9 @@ class KTEntity { |
| 342 | 343 | foreach($case as $k => $v) { |
| 343 | 344 | $case[substr($k, 1)] = $v; |
| 344 | 345 | } |
| 346 | + foreach($array2 as $k => $v) { | |
| 347 | + $case[strtolower($k)] = $v; | |
| 348 | + } | |
| 345 | 349 | } else { |
| 346 | 350 | $case = $aCache['fieldnames']; |
| 347 | 351 | } |
| ... | ... | @@ -406,200 +410,117 @@ class KTEntityUtil { |
| 406 | 410 | return KTEntityUtil::getList($sTable, $sClassName, $aWhereClause, $aOptions); |
| 407 | 411 | } |
| 408 | 412 | |
| 413 | + /** | |
| 414 | + * Core function for KTEntityUtil, gets a list of all the objects according to the given where clause | |
| 415 | + * | |
| 416 | + * @param string $sTable | |
| 417 | + * @param string $sClassName | |
| 418 | + * @param array|string $aWhereClause | |
| 419 | + * @param array $aOptions | |
| 420 | + * @return array | |
| 421 | + */ | |
| 409 | 422 | function &getList($sTable, $sClassName, $aWhereClause = null, $aOptions = null) { |
| 410 | 423 | global $default; |
| 424 | + | |
| 425 | + // Force the where clause to be an array | |
| 426 | + if (!is_array($aWhereClause)) { | |
| 427 | + $aWhereClause = array($aWhereClause, array()); | |
| 428 | + } | |
| 429 | + | |
| 430 | + // Force the options to be an array | |
| 411 | 431 | if (is_null($aOptions)) { |
| 412 | 432 | $aOptions = array(); |
| 413 | 433 | } |
| 414 | 434 | |
| 435 | + // Merge in the standard options for the class | |
| 415 | 436 | $aBaseOpts = call_user_func(array($sClassName, "_ktentityOptions")); |
| 416 | - $aOptions = KTUtil::meldOptions($aBaseOpts, $aOptions); | |
| 417 | - | |
| 418 | - $bIDs = false; | |
| 419 | - $bIDs = KTUtil::arrayGet($aOptions, "ids", false); | |
| 420 | - $sIDField = 'id'; | |
| 421 | - $cache = KTUtil::arrayGet($aOptions, 'cache', false); | |
| 422 | - | |
| 423 | - if (!is_array($aWhereClause)) { | |
| 424 | - $aWhereClause = array($aWhereClause, array()); | |
| 437 | + if(!is_array($aBaseOpts)){ | |
| 438 | + $aBaseOpts = array(); | |
| 425 | 439 | } |
| 440 | + $aOptions = array_merge($aBaseOpts, $aOptions); | |
| 426 | 441 | |
| 442 | + /* *** Check for all option values *** */ | |
| 427 | 443 | |
| 428 | - if (!$cache) { // && EVIL_CACHE_GRIND) { | |
| 429 | - $cache = 'auto'; | |
| 430 | - } | |
| 444 | + // Check if only the id's have been requested | |
| 445 | + $bIDs = isset($aOptions['ids']) ? $aOptions['ids'] : false; | |
| 431 | 446 | |
| 432 | - if (isset($GLOBALS['_STOPCACHING'][$sClassName])) { | |
| 433 | - if ($GLOBALS['_STOPCACHING'][$sClassName] > 5) { | |
| 434 | - $cache = false; | |
| 435 | - } | |
| 436 | - } | |
| 447 | + // Check if the id field differs from the standard | |
| 448 | + $sIDField = isset($aOptions['idfield']) ? $aOptions['idfield'] : 'id'; | |
| 437 | 449 | |
| 438 | - if (isset($aOptions['orderby'])) { | |
| 439 | - $sOrderBy = $aOptions['orderby']; | |
| 440 | - if (!empty($aWhereClause[0])) { | |
| 441 | - $aWhereClause[0] .= " ORDER BY " . $sOrderBy; | |
| 442 | - } else { | |
| 443 | - $aWhereClause[0] = "ORDER BY " . $sOrderBy; | |
| 444 | - } | |
| 445 | - } | |
| 450 | + // Check for an order by clause | |
| 451 | + $sOrderBy = isset($aOptions['orderby']) ? $aOptions['orderby'] : false; | |
| 446 | 452 | |
| 447 | - $sIDField = KTUtil::arrayGet($aOptions, "idfield", 'id'); | |
| 448 | - $aWhereClause[2] = $sIDField; | |
| 453 | + // Check for a limit and offset | |
| 454 | + $iLimit = isset($aOptions['limit']) ? $aOptions['limit'] : false; | |
| 455 | + $iOffset = isset($aOptions['offset']) ? $aOptions['offset'] : false; | |
| 449 | 456 | |
| 450 | - if (isset($aOptions['limit'])) { | |
| 451 | - if (isset($aOptions['offset'])) { | |
| 452 | - $iOffset = $aOptions['offset']; | |
| 453 | - } else { | |
| 454 | - $iOffset = 0; | |
| 455 | - } | |
| 456 | - $iLimit = $aOptions['limit']; | |
| 457 | + // Check for the cache value | |
| 458 | + $cache = isset($aOptions['cache']) ? $aOptions['cache'] : 'getlist'; | |
| 457 | 459 | |
| 458 | - if ($iOffset) { | |
| 459 | - $aWhereClause[0] .= " LIMIT $iOffset, $iLimit"; | |
| 460 | - } else { | |
| 461 | - $aWhereClause[0] .= " LIMIT $iLimit"; | |
| 462 | - } | |
| 460 | + /* *** Construct the query *** */ | |
| 461 | + | |
| 462 | + $sQuery = ''; | |
| 463 | + if($bIDs !== false){ | |
| 464 | + $sQuery = "SELECT $sIDField FROM $sTable"; | |
| 465 | + }else{ | |
| 466 | + $oObject = new $sClassName; | |
| 467 | + $select = $oObject->_getSqlSelection(); | |
| 468 | + $sQuery = "SELECT {$select} FROM $sTable"; | |
| 463 | 469 | } |
| 464 | 470 | |
| 465 | - $fullselect = KTUtil::arrayGet($aOptions, 'fullselect', false); | |
| 471 | + // Append the where clause | |
| 472 | + $sWhere = ''; | |
| 473 | + $aParams = array(); | |
| 474 | + if(isset($aWhereClause[0]) && !empty($aWhereClause[0])){ | |
| 475 | + // check whether the WHERE or ORDER has already been included in the query string | |
| 476 | + $check = substr($aWhereClause[0], 0, 5); | |
| 466 | 477 | |
| 467 | - if ($cache) { | |
| 468 | - if ($cache === 'auto') { | |
| 469 | - $vals = serialize($aWhereClause); | |
| 470 | - } else if (is_array($aWhereClause)) { | |
| 471 | - $vals = serialize($aWhereClause[1]); | |
| 472 | - } else { | |
| 473 | - $vals = serialize($aWhereClause); | |
| 478 | + if($check != 'WHERE' && $check != 'ORDER'){ | |
| 479 | + $sWhere = 'WHERE '; | |
| 474 | 480 | } |
| 475 | - if (KTLOG_CACHE) $default->log->debug(sprintf("Trying list cache for class %s, %s: %s", $sClassName, $cache, $vals)); | |
| 481 | + $sWhere .= $aWhereClause[0]; | |
| 482 | + $aParams = isset($aWhereClause[1]) && !empty($aWhereClause[1]) ? $aWhereClause[1] : array(); | |
| 476 | 483 | |
| 477 | - $oCache =& KTCache::getSingleton(); | |
| 478 | - $suffix = ''; | |
| 479 | - if ($fullselect) { | |
| 480 | - $suffix = '_fullselect'; | |
| 481 | - } | |
| 482 | - $group = sprintf("%s/%s%s", $sClassName, $cache, $suffix); | |
| 483 | - list($bCached, $mCached) = $oCache->get($group, $vals); | |
| 484 | - } else { | |
| 485 | - $bCached = false; | |
| 484 | + $sQuery .= " $sWhere"; | |
| 486 | 485 | } |
| 487 | 486 | |
| 488 | - if ($cache && !$bCached) { | |
| 489 | - global $default; | |
| 490 | - if (KTLOG_CACHE) $default->log->debug(sprintf("No list cache for class %s, %s: %s", $sClassName, $cache, $vals)); | |
| 487 | + // Append the order by | |
| 488 | + if($sOrderBy != false){ | |
| 489 | + $sQuery .= " ORDER BY $sOrderBy"; | |
| 491 | 490 | } |
| 492 | - if ($bCached && EVIL_CACHE_GRIND) { | |
| 493 | - if (!empty($fullselect)) { | |
| 494 | - $oObject = new $sClassName; | |
| 495 | - $select = $oObject->_getSqlSelection(); | |
| 496 | - $sQuery = "SELECT $select FROM " . $sTable;/*ok*/ | |
| 497 | - } else { | |
| 498 | - $sIDField = KTUtil::arrayGet($aOptions, "idfield", 'id'); | |
| 499 | - $sQuery = "SELECT $sIDField FROM " . $sTable;/*ok*/ | |
| 500 | - } | |
| 501 | - $aParams = array(); | |
| 502 | - if (!empty($aWhereClause[0])) { | |
| 503 | - if (is_string($aWhereClause)) { | |
| 504 | - if (substr($aWhereClause, 0, 5) != 'WHERE') { | |
| 505 | - if (substr($aWhereClause, 0, 5) != 'ORDER') { | |
| 506 | - $sQuery .= ' WHERE'; | |
| 507 | - } | |
| 508 | - } | |
| 509 | - $sQuery .= ' ' . $aWhereClause; | |
| 510 | - } else if (is_array($aWhereClause)) { | |
| 511 | - if (substr($aWhereClause[0], 0, 5) != 'WHERE') { | |
| 512 | - if (substr($aWhereClause[0], 0, 5) != 'ORDER') { | |
| 513 | - $sQuery .= ' WHERE'; | |
| 514 | - } | |
| 515 | - } | |
| 516 | - $sQuery .= ' ' . $aWhereClause[0]; | |
| 517 | - $aParams = $aWhereClause[1]; | |
| 518 | - } else { | |
| 519 | - return new PEAR_Error('Weird WhereClause passed'); | |
| 520 | - } | |
| 521 | - } | |
| 522 | 491 | |
| 523 | - if (!empty($fullselect)) { | |
| 524 | - $aIDs = DBUtil::getResultArray(array($sQuery, $aParams)); | |
| 525 | - } else { | |
| 526 | - $aIDs = DBUtil::getResultArrayKey(array($sQuery, $aParams), $sIDField); | |
| 492 | + // Append a limit and offset | |
| 493 | + if($iLimit != false){ | |
| 494 | + $sLimit = ''; | |
| 495 | + if($iOffset != false){ | |
| 496 | + $sLimit .= "$iOffset, "; | |
| 527 | 497 | } |
| 528 | - // compare mcached == $aIds | |
| 498 | + $sLimit .= $iLimit; | |
| 529 | 499 | |
| 530 | - if ($aIDs != $mCached) { | |
| 531 | - /* | |
| 532 | - print "==================\n\n\n\n\n"; | |
| 533 | - var_dump($aIDs); | |
| 534 | - print "------\n"; | |
| 535 | - var_dump($mCached); | |
| 536 | - */ | |
| 537 | - $oCache->alertFailure($group, array('Stored IDS != Cache IDS')); | |
| 538 | - } | |
| 539 | - } else if ($bCached) { | |
| 540 | - if (KTLOG_CACHE) $default->log->debug(sprintf("Using object cache for class %s, %s: %s", $sClassName, $cache, $vals)); | |
| 541 | - $aIDs = $mCached; | |
| 542 | - /* */ | |
| 543 | - } else { | |
| 544 | - if (!empty($fullselect)) { | |
| 545 | - $oObject = new $sClassName; | |
| 546 | - $select = $oObject->_getSqlSelection(); | |
| 547 | - $sQuery = "SELECT $select FROM " . $sTable;/*ok*/ | |
| 548 | - } else { | |
| 549 | - $sIDField = KTUtil::arrayGet($aOptions, "idfield", 'id'); | |
| 550 | - $sQuery = "SELECT $sIDField FROM " . $sTable;/*ok*/ | |
| 551 | - } | |
| 552 | - $aParams = array(); | |
| 553 | - if (!is_null($aWhereClause[0])) { | |
| 554 | - if (is_string($aWhereClause)) { | |
| 555 | - if (substr($aWhereClause, 0, 5) != 'WHERE') { | |
| 556 | - if (substr($aWhereClause, 0, 5) != 'ORDER') { | |
| 557 | - $sQuery .= ' WHERE'; | |
| 558 | - } | |
| 559 | - } | |
| 560 | - $sQuery .= ' ' . $aWhereClause; | |
| 561 | - } else if (is_array($aWhereClause)) { | |
| 562 | - if (substr($aWhereClause[0], 0, 5) != 'WHERE') { | |
| 563 | - if (substr($aWhereClause[0], 0, 5) != 'ORDER') { | |
| 564 | - $sQuery .= ' WHERE'; | |
| 565 | - } | |
| 566 | - } | |
| 567 | - $sQuery .= ' ' . $aWhereClause[0]; | |
| 568 | - $aParams = $aWhereClause[1]; | |
| 569 | - } else { | |
| 570 | - return new PEAR_Error('Weird WhereClause passed'); | |
| 571 | - } | |
| 572 | - } | |
| 573 | - | |
| 574 | - if (!empty($fullselect)) { | |
| 575 | - $aIDs = DBUtil::getResultArray(array($sQuery, $aParams)); | |
| 576 | - } else { | |
| 577 | - $aIDs = DBUtil::getResultArrayKey(array($sQuery, $aParams), $sIDField); | |
| 578 | - } | |
| 500 | + $sQuery .= " LIMIT $sLimit"; | |
| 579 | 501 | } |
| 580 | 502 | |
| 581 | - if (PEAR::isError($aIDs)) { | |
| 582 | - return $aIDs; | |
| 583 | - } | |
| 503 | + /* *** Check the cache *** */ | |
| 504 | + | |
| 505 | + $oCache = KTCache::getSingleton(); | |
| 506 | + $vals = serialize(array($sQuery, $aParams)); | |
| 507 | + $group = $sClassName.'/'.$cache; | |
| 508 | + | |
| 509 | + list($bCached, $mCached) = $oCache->get($group, $vals); | |
| 584 | 510 | |
| 585 | - if ($cache && !$bCached) { | |
| 586 | - if (KTLOG_CACHE) $default->log->debug(sprintf("Setting object cache for class %s, %s, %s", $sClassName, $cache, $vals)); | |
| 587 | - $oCache->set($group, $vals, $aIDs); | |
| 588 | - } | |
| 589 | 511 | |
| 590 | - if ($bIDs === true) { | |
| 512 | + /* *** Execute the query *** */ | |
| 513 | + | |
| 514 | + // If only id's are requested, return them | |
| 515 | + if($bIDs){ | |
| 516 | + $aIDs = DBUtil::getResultArrayKey(array($sQuery, $aParams), $sIDField); | |
| 591 | 517 | return $aIDs; |
| 592 | 518 | } |
| 593 | 519 | |
| 594 | - if (!empty($fullselect)) { | |
| 595 | - $aRet =& KTEntityUtil::loadFromArrayMulti($sClassName, $aIDs); | |
| 596 | - return $aRet; | |
| 597 | - } | |
| 598 | - $aRet = array(); | |
| 599 | - foreach ($aIDs as $iId) { | |
| 600 | - $aRet[] = call_user_func(array($sClassName, 'get'), $iId); | |
| 601 | - } | |
| 602 | - return $aRet; | |
| 520 | + // Get the object data and load into objects | |
| 521 | + $results = DBUtil::getResultArray(array($sQuery, $aParams)); | |
| 522 | + $aObjects = KTEntityUtil::loadFromArrayMulti($sClassName, $results); | |
| 523 | + return $aObjects; | |
| 603 | 524 | } |
| 604 | 525 | |
| 605 | 526 | function &createFromArray ($sClassName, $aOptions) { |
| ... | ... | @@ -650,7 +571,25 @@ class KTEntityUtil { |
| 650 | 571 | |
| 651 | 572 | function &loadFromArrayMulti($sClassName, $aMultiArray, $aOptions = null) { |
| 652 | 573 | $aRet = array(); |
| 574 | + $config =& KTConfig::getSingleton(); | |
| 575 | + //$useProxy = $config->get('cache/proxyCacheEnabled'); | |
| 653 | 576 | foreach ($aMultiArray as $aArray) { |
| 577 | + | |
| 578 | + //if($useProxy){ | |
| 579 | + $iId = (int)$aArray['id']; | |
| 580 | + if(empty($iId)){ | |
| 581 | + $iId = null; | |
| 582 | + } | |
| 583 | + $sProxyClass = KTEntityUtil::_getProxyClass($sClassName); | |
| 584 | + $oObject =new $sProxyClass($iId, $aArray); | |
| 585 | + $res = $oObject->getId(); | |
| 586 | + if (PEAR::isError($res)) { | |
| 587 | + return $res; | |
| 588 | + } | |
| 589 | + $aRet[] = $oObject; | |
| 590 | + continue; | |
| 591 | + //} | |
| 592 | + | |
| 654 | 593 | $oObject =new $sClassName; |
| 655 | 594 | $ret = $oObject->loadFromArray($aArray); |
| 656 | 595 | if (PEAR::isError($ret)) { |
| ... | ... | @@ -666,15 +605,17 @@ class KTEntityUtil { |
| 666 | 605 | return PEAR::raiseError(_kt('Non-numeric identifier')); |
| 667 | 606 | } |
| 668 | 607 | $iId = (int)$iId; |
| 669 | - /* */ | |
| 670 | - $sProxyClass = KTEntityUtil::_getProxyClass($sClassName); | |
| 671 | - $oObject =new $sProxyClass($iId); | |
| 672 | - $res = $oObject->getId(); | |
| 673 | - if (PEAR::isError($res)) { | |
| 674 | - return $res; | |
| 675 | - } | |
| 676 | - return $oObject; | |
| 677 | - /* */ | |
| 608 | + // Use a proxy class if enabled | |
| 609 | + $config =& KTConfig::getSingleton(); | |
| 610 | + //if($config->get('cache/proxyCacheEnabled')){ | |
| 611 | + $sProxyClass = KTEntityUtil::_getProxyClass($sClassName); | |
| 612 | + $oObject =new $sProxyClass($iId); | |
| 613 | + $res = $oObject->getId(); | |
| 614 | + if (PEAR::isError($res)) { | |
| 615 | + return $res; | |
| 616 | + } | |
| 617 | + return $oObject; | |
| 618 | + //} | |
| 678 | 619 | // XXX Object cache currently causes hard-to-trace inconsistencies in data. |
| 679 | 620 | // $oObject =& KTUtil::arrayGet($GLOBALS['_OBJECTCACHE'][$sClassName], $iId); |
| 680 | 621 | // if ($oObject) { return $oObject; } |
| ... | ... | @@ -736,11 +677,13 @@ class KTEntityUtil { |
| 736 | 677 | } |
| 737 | 678 | eval($code); |
| 738 | 679 | } |
| 680 | + | |
| 739 | 681 | function _proxyBuild($sClassName, $sProxyClassName) { |
| 740 | 682 | // var_dump("Building proxy for $sClassName"); |
| 741 | 683 | $methods = get_class_methods($sClassName); |
| 742 | 684 | $allcode = array(); |
| 743 | 685 | $allcode[] = sprintf('var $cacheGlobal = null;%s', "\n"); |
| 686 | + $allcode[] = sprintf('var $aFieldArr = null;%s', "\n"); | |
| 744 | 687 | |
| 745 | 688 | foreach ($methods as $sMethod) { |
| 746 | 689 | if(substr($sMethod, 0, 2) == '__') { |
| ... | ... | @@ -765,13 +708,17 @@ class KTEntityUtil { |
| 765 | 708 | return $oObject; |
| 766 | 709 | } |
| 767 | 710 | $oObject =new %s; |
| 768 | - $res = $oObject->load($this->iId); | |
| 711 | + if(!empty($this->aFieldArr)){ | |
| 712 | + $res = $oObject->loadFromArray($this->aFieldArr); | |
| 713 | + }else{ | |
| 714 | + $res = $oObject->load($this->iId); | |
| 715 | + } | |
| 769 | 716 | if (PEAR::isError($res)) { |
| 770 | 717 | return $res; |
| 771 | 718 | } |
| 772 | 719 | $this->cacheGlobal[$this->iId] =& $oObject; |
| 773 | 720 | return $oObject; |
| 774 | - }', $sClassName, $sClassName, $sClassName, $sClassName); | |
| 721 | + }', $sClassName, $sClassName, $sClassName, $sClassName, $sClassName); | |
| 775 | 722 | |
| 776 | 723 | $allcode[] = sprintf('function _save(&$oObject) { |
| 777 | 724 | $this->cacheGlobal[$this->iId] =& $oObject; |
| ... | ... | @@ -802,7 +749,7 @@ class KTEntityUtil { |
| 802 | 749 | /* */ |
| 803 | 750 | }'; |
| 804 | 751 | |
| 805 | - $allcode[] = sprintf('function %s ($iId) { $this->iId = $iId; $this->cacheGlobal =& $GLOBALS["_OBJECTCACHE"][%s]; }' . "\n", $sProxyClassName, $sClassName); | |
| 752 | + $allcode[] = sprintf('function %s ($iId, $aInfo = null) { $this->iId = $iId; $this->aFieldArr = $aInfo; $this->cacheGlobal =& $GLOBALS["_OBJECTCACHE"][%s]; }' . "\n", $sProxyClassName, $sClassName); | |
| 806 | 753 | |
| 807 | 754 | $gen = sprintf("class %s extends %s {\n", $sProxyClassName, $sClassName); |
| 808 | 755 | $gen .= " " . join("\n ", $allcode) . "\n"; | ... | ... |