0) { return isset($row[$indexColumns]) ? $row[$indexColumns] : 0; } else { return $lastOffset + 1; } } /** * This function performs a select by structuring the primary key as offset if the table has a primary key. * For optimization issues, no checks are performed on the input query and it is assumed that the select has at least a where value. * If there are no conditions, you still have to perform an always true condition, for example * SELECT * FROM `copy1_postmeta` WHERE 1 * * @param \mysqli|resource $dbh * @param string $query * @param string $table * @param int $offset * @param int $limit // 0 no limit * @param mixed $lastRowOffset // last offset to use on next function call * @return mysqli_result * @throws Exception // exception on query fail */ public static function selectUsingPrimaryKeyAsOffset($dbh, $query, $table, $offset, $limit, &$lastRowOffset = null, $logCallback = null) { $where = ''; $orderby = ''; $offsetStr = ''; $limitStr = $limit > 0 ? ' LIMIT '.$limit : ''; if (($primaryColumn = self::getUniqueIndexColumn($dbh, $table, $logCallback)) == false) { $offsetStr = ' OFFSET '.(is_scalar($offset) ? $offset : 0); } else { if (is_array($primaryColumn)) { // COMPOSITE KEY $orderByCols = array(); foreach ($primaryColumn as $colIndex => $col) { $orderByCols[] = '`'.$col.'` ASC'; } $orderby = ' ORDER BY '.implode(',', $orderByCols); } else { $orderby = ' ORDER BY `'.$primaryColumn.'` ASC'; } $where = self::getOffsetKeyCondition($dbh, $primaryColumn, $offset); } $query .= $where.$orderby.$limitStr.$offsetStr; if (($result = self::query($dbh, $query)) === false) { if (is_callable($logCallback)) { call_user_func($logCallback, $dbh, $result, $query); } throw new Exception('SELECT ERROR: '.self::error($dbh).' QUERY: '.$query); } if (is_callable($logCallback)) { call_user_func($logCallback, $dbh, $result, $query); } if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { if ($primaryColumn == false) { $lastRowOffset = $offset + $result->num_rows; } else { if ($result->num_rows == 0) { $lastRowOffset = $offset; } else { $result->data_seek(($result->num_rows - 1)); $row = $result->fetch_assoc(); if (is_array($primaryColumn)) { $lastRowOffset = array(); foreach ($primaryColumn as $col) { $lastRowOffset[$col] = $row[$col]; } } else { $lastRowOffset = $row[$primaryColumn]; } $result->data_seek(0); } } } else { if ($primaryColumn == false) { $lastRowOffset = $offset + mysql_num_rows($result); } else { if (mysql_num_rows($result) == 0) { $lastRowOffset = $offset; } else { mysql_data_seek($result, (mysql_num_rows($result) - 1)); $row = mysql_fetch_assoc($result); if (is_array($primaryColumn)) { $lastRowOffset = array(); foreach ($primaryColumn as $col) { $lastRowOffset[$col] = $row[$col]; } } else { $lastRowOffset = $row[$primaryColumn]; } mysql_data_seek($result, 0); } } } return $result; } /** * Depending on the structure type of the primary key returns the condition to position at the right offset * * @param \mysqli|resource $dbh * @param string|string[] $primaryColumn * @param mixed $offset * @return string */ protected static function getOffsetKeyCondition($dbh, $primaryColumn, $offset) { $condition = ''; if ($offset === 0) { return ''; } // COUPOUND KEY if (is_array($primaryColumn)) { $isFirstCond = true; foreach ($primaryColumn as $colIndex => $col) { if (is_array($offset) && isset($offset[$col])) { if ($isFirstCond) { $isFirstCond = false; } else { $condition .= ' OR '; } $condition .= ' ('; for ($prevColIndex = 0; $prevColIndex < $colIndex; $prevColIndex++) { $condition .= ' `'.$primaryColumn[$prevColIndex].'` = "'.self::realEscapeString($dbh, $offset[$primaryColumn[$prevColIndex]]).'" AND '; } $condition .= ' `'.$col.'` > "'.self::realEscapeString($dbh, $offset[$col]).'")'; } } } else { $condition = '`'.$primaryColumn.'` > "'.self::realEscapeString($dbh, (is_scalar($offset) ? $offset : 0)).'"'; } return (strlen($condition) ? ' AND ('.$condition.')' : ''); } /** * get current database engine (mysql, maria, percona) * @param \mysqli|resource $dbh * * @return string */ public static function getDBEngine($dbh) { if (($result = self::query($dbh, "SHOW VARIABLES LIKE 'version%'")) === false) { // on query error assume is mysql. return self::DB_ENGINE_MYSQL; } $rows = array(); while ($row = self::fetchRow($result)) { $rows[] = $row; } self::freeResult($result); $version = isset($rows[0][1]) ? $rows[0][1] : false; $versionComment = isset($rows[1][1]) ? $rows[1][1] : false; //Default is mysql if ($version === false && $versionComment === false) { return self::DB_ENGINE_MYSQL; } if (stripos($version, 'maria') !== false || stripos($versionComment, 'maria') !== false) { return self::DB_ENGINE_MARIA; } if (stripos($version, 'percona') !== false || stripos($versionComment, 'percona') !== false) { return self::DB_ENGINE_PERCONA; } return self::DB_ENGINE_MYSQL; } /** * * @param resoruce|mysqli $dbh * @param string $string * @return string
Returns an escaped string.
*/ public static function realEscapeString($dbh, $string) { if (self::dbConnType($dbh) === self::CONN_MYSQLI) { return mysqli_real_escape_string($dbh, $string); } else { return mysql_real_escape_string($string, $dbh); } } /** * * @param resoruce|mysqli $dbh * @param string $query * @return mixedReturns FALSE on failure. For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a mysqli_result object. For other successful queries mysqli_query() will return TRUE.
An integer representing the number of fields in a result set.
* @link http://php.net/manual/en/mysqli.field-count.php */ public static function fetchRow($result) { if (self::dbConnTypeByResult($result) === self::CONN_MYSQLI) { return mysqli_fetch_row($result); } elseif (is_resource($result)) { return mysql_fetch_row($result); } } /** * * @param resoruce|mysqli_result $result * @return objectReturns an object which contains field definition information or FALSE if no field information for specified fieldnr is available.