/** * Process an aggregate-type bucket. This is MySQL specific. * * @param Plugins_DeliveryLog $oBucket a reference to the using (context) object. * @param Date $oEnd A PEAR_Date instance, interval_start to process up to (inclusive). */ public function processBucket($oBucket, $oEnd) { $sTableName = $oBucket->getBucketTableName(); $oMainDbh =& OA_DB_Distributed::singleton(); if (PEAR::isError($oMainDbh)) { MAX::raiseError($oMainDbh, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug(' - Processing the ' . $sTableName . ' table for data with operation interval start equal to or before ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(), PEAR_LOG_INFO); // Select all rows with interval_start <= previous OI start. $rsData =& $this->getBucketTableContent($sTableName, $oEnd); $rowCount = $rsData->getRowCount(); OA::debug(' - ' . $rsData->getRowCount() . ' records found', PEAR_LOG_DEBUG); if ($rowCount) { // We can't do bulk inserts with ON DUPLICATE. $aExecQueries = array(); while ($rsData->fetch()) { // Get first row $aRow = $rsData->toArray(); // Insert or update $aExecQueries[] = "SELECT bucket_update_{$sTableName}(" . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ")"; } if (count($aExecQueries)) { foreach ($aExecQueries as $execQuery) { $result = $oMainDbh->exec($execQuery); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } } } } }
/** * Process an aggregate-type bucket. This is MySQL specific. * * @param Plugins_DeliveryLog $oBucket a reference to the using (context) object. * @param Date $oEnd A PEAR_Date instance, interval_start to process up to (inclusive). */ public function processBucket($oBucket, $oEnd) { $sTableName = $oBucket->getBucketTableName(); $oMainDbh =& OA_DB_Distributed::singleton(); if (PEAR::isError($oMainDbh)) { MAX::raiseError($oMainDbh, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } OA::debug(' - Processing the ' . $sTableName . ' table for data with operation interval start equal to or before ' . $oEnd->format('%Y-%m-%d %H:%M:%S') . ' ' . $oEnd->tz->getShortName(), PEAR_LOG_INFO); // Select all rows with interval_start <= previous OI start. $rsData =& $this->getBucketTableContent($sTableName, $oEnd); $rowCount = $rsData->getRowCount(); OA::debug(' - ' . $rsData->getRowCount() . ' records found', PEAR_LOG_DEBUG); if ($rowCount) { // We can't do bulk inserts with ON DUPLICATE. $aExecQueries = array(); if ($rsData->fetch()) { // Get first row $aRow = $rsData->toArray(); // Prepare INSERT $sInsert = "INSERT INTO {$sTableName} (" . join(',', array_keys($aRow)) . ") VALUES "; // Add first row data $sRow = '(' . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ')'; $sOnDuplicate = ' ON DUPLICATE KEY UPDATE count = count + ' . $aRow['count']; // Add first insert $aExecQueries[] = $sInsert . $sRow . $sOnDuplicate; // Deal with the other rows while ($rsData->fetch()) { $aRow = $rsData->toArray(); $sRow = '(' . join(',', array_map(array(&$oMainDbh, 'quote'), $aRow)) . ')'; $sOnDuplicate = ' ON DUPLICATE KEY UPDATE count = count + ' . $aRow['count']; $aExecQueries[] = $sInsert . $sRow . $sOnDuplicate; } } if (count($aExecQueries)) { // Try to disable the binlog for the inserts so we don't // replicate back out over our logged data. PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN); $result = $oMainDbh->exec('SET SQL_LOG_BIN = 0'); if (PEAR::isError($result)) { OA::debug('Unable to disable the bin log, proceeding anyway.', PEAR_LOG_WARNING); } PEAR::staticPopErrorHandling(); foreach ($aExecQueries as $execQuery) { $result = $oMainDbh->exec($execQuery); if (PEAR::isError($result)) { MAX::raiseError($result, MAX_ERROR_DBFAILURE, PEAR_ERROR_DIE); } } } } }
/** * Returns the stored procedure query body. Used on install * to create required procedures inside postgres database * * @return string */ function getCreateStoredProcedureQuery(Plugins_DeliveryLog $component) { $tableName = $component->getBucketTableName(); $query = 'CREATE OR REPLACE FUNCTION ' . $this->getStoredProcedureName($component) . ' (' . $this->_getColumnTypesList($component) . ', cnt integer) RETURNS void AS $BODY$DECLARE x int; BEGIN LOOP -- first try to update UPDATE ' . $tableName . ' SET count = count + cnt WHERE ' . $this->_getSPWhere($component) . '; GET DIAGNOSTICS x = ROW_COUNT; IF x > 0 THEN RETURN; END IF; -- not there, so try to insert the key -- if someone else inserts the same key concurrently, -- we could get a unique-key failure BEGIN INSERT INTO ' . $tableName . ' VALUES (' . $this->_getSPValuesList($component) . ', cnt); RETURN; EXCEPTION WHEN unique_violation THEN -- do nothing, and loop to try the UPDATE again END; END LOOP; END$BODY$ LANGUAGE \'plpgsql\''; return $query; }