Commit 80a7c793c49d55cd2cf8f62ea2d5b749d17126d3

Authored by Megan Watson
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";
... ...