public function saveItems(array $itemData, EarthIT_Schema_ResourceClass $rc, array $options = array())
 {
     if (count($itemData) == 0) {
         // Save a few processor cycles
         return $options[EarthIT_Storage_ItemSaver::RETURN_SAVED] ? array() : null;
     }
     EarthIT_Storage_Util::defaultSaveItemsOptions($options);
     $rcName = $rc->getName();
     $blankItem = EarthIT_Storage_Util::defaultItem($rc, true);
     $savedItems = array();
     foreach ($itemData as $item) {
         $id = EarthIT_Storage_Util::itemId($item, $rc);
         if ($id === null) {
             $pk = $rc->getPrimaryKey();
             if ($pk !== null) {
                 foreach ($pk->getFieldNames() as $fn) {
                     if (!isset($item[$fn])) {
                         if ($rc->getField($fn)->getType()->getName() == 'entity ID') {
                             $item[$fn] = call_user_func($this->idGenerator);
                         } else {
                             throw new Exception("Don't know how to generate ID component '{$fn}' of '" . $rc->getName() . "'");
                         }
                     }
                 }
             }
             $id = EarthIT_Storage_Util::itemId($item, $rc);
             if ($id === null) {
                 // Note: In some cases we may want to allow ID-less records,
                 // in which case remove the throw and just append the item to wherever lists.
                 throw new Exception("Failed to generate an ID for a " . $rc->getName());
             }
         }
         $item = EarthIT_Storage_Util::castItemFieldValues($item, $rc);
         if (isset($this->items[$rcName][$id])) {
             switch ($odk = $options[EarthIT_Storage_ItemSaver::ON_DUPLICATE_KEY]) {
                 case EarthIT_Storage_ItemSaver::ODK_ERROR:
                 case EarthIT_Storage_ItemSaver::ODK_UNDEFINED:
                     throw new Exception("saveItem causes collision for " . $rc->getName() . " '{$id}'");
                 case EarthIT_Storage_ItemSaver::ODK_KEEP:
                     $savedItems[$id] = $this->items[$rcName][$id];
                     break;
                 case EarthIT_Storage_ItemSaver::ODK_REPLACE:
                     $savedItems[$id] = $this->items[$rcName][$id] = $item + $blankItem;
                     break;
                 case EarthIT_Storage_ItemSaver::ODK_UPDATE:
                     $savedItems[$id] = $this->items[$rcName][$id] = $item + $this->items[$rcName][$id];
                     break;
                 default:
                     throw new Exception("Unrecognized on-duplicate-key option: '{$odk}'");
             }
         } else {
             $savedItems[$id] = $this->items[$rcName][$id] = $item + $blankItem;
         }
     }
     return $options[EarthIT_Storage_ItemSaver::RETURN_SAVED] ? $savedItems : null;
 }
 /** @override */
 public function saveItems(array $itemData, EarthIT_Schema_ResourceClass $rc, array $options = array())
 {
     EarthIT_Storage_Util::defaultSaveItemsOptions($options);
     $queries = $this->sqlGenerator->makeBulkSaveQueries($itemData, $rc, $options);
     $resultRows = array();
     foreach ($queries as $q) {
         list($sql, $params) = EarthIT_DBC_SQLExpressionUtil::templateAndParamValues($q);
         if ($q->returnsStuff()) {
             $resultRows = array_merge($resultRows, $this->sqlRunner->fetchRows($sql, $params));
         } else {
             $this->sqlRunner->doQuery($sql, $params);
         }
     }
     if ($options[EarthIT_Storage_ItemSaver::RETURN_SAVED]) {
         return $this->sqlGenerator->dbExternalToSchemaItems($resultRows, $rc);
     }
 }
 /**
  * @return array of EarthIT_DBC_SQLExpressions to be doQueried; the
  *   last will be fetchAlled if options.returnSaved is true
  */
 public function makeBulkSaveQueries(array $itemData, EarthIT_Schema_ResourceClass $rc, array $options = array())
 {
     if (count($itemData) == 0) {
         return array();
     }
     EarthIT_Storage_Util::defaultSaveItemsOptions($options);
     switch ($options[EarthIT_Storage_ItemSaver::ON_DUPLICATE_KEY]) {
         case EarthIT_Storage_ItemSaver::ODK_ERROR:
         case EarthIT_Storage_ItemSaver::ODK_UNDEFINED:
             return $this->_bulkInsertQueries($itemData, $rc, $options[EarthIT_Storage_ItemSaver::RETURN_SAVED]);
         default:
             return $this->_bulkPatchyQueries($itemData, $rc, $options);
     }
 }