function browseQuery($type, $table, $query, $sortkey, $sortdir, $page, $page_size, &$max_pages)
{
// Check that we're not going to divide by zero
if (!is_numeric($page_size) || $page_size != (int) $page_size || $page_size <= 0) {
return -3;
}
// If $type is TABLE, then generate the query
switch ($type) {
case 'TABLE':
if (preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
$orderby = array($sortkey => $sortdir);
} else {
$orderby = array();
}
$query = $this->getSelectSQL($table, array(), array(), array(), $orderby);
break;
case 'QUERY':
case 'SELECT':
// Trim query
$query = trim($query);
// Trim off trailing semi-colon if there is one
if (substr($query, strlen($query) - 1, 1) == ';') {
$query = substr($query, 0, strlen($query) - 1);
}
break;
default:
return -4;
}
// Generate count query
$count = "SELECT COUNT(*) AS total FROM ({$query}) AS sub";
// Open a transaction
$status = $this->beginTransaction();
if ($status != 0) {
return -1;
}
// If backend supports read only queries, then specify read only mode
// to avoid side effects from repeating queries that do writes.
if ($this->hasReadOnlyQueries()) {
$status = $this->execute("SET TRANSACTION READ ONLY");
if ($status != 0) {
$this->rollbackTransaction();
return -5;
}
}
// Count the number of rows
$total = $this->browseQueryCount($query, $count);
if ($total < 0) {
$this->rollbackTransaction();
return -2;
}
// Calculate max pages
$max_pages = ceil($total / $page_size);
// Check that page is less than or equal to max pages
if (!is_numeric($page) || $page != (int) $page || $page > $max_pages || $page < 1) {
$this->rollbackTransaction();
return -3;
}
// Set fetch mode to NUM so that duplicate field names are properly returned
// for non-table queries. Since the SELECT feature only allows selecting one
// table, duplicate fields shouldn't appear.
if ($type == 'QUERY') {
$this->conn->setFetchMode(ADODB_FETCH_NUM);
}
// Figure out ORDER BY. Sort key is always the column number (based from one)
// of the column to order by. Only need to do this for non-TABLE queries
if ($type != 'TABLE' && preg_match('/^[0-9]+$/', $sortkey) && $sortkey > 0) {
$orderby = " ORDER BY {$sortkey}";
// Add sort order
if ($sortdir == 'desc') {
$orderby .= ' DESC';
} else {
$orderby .= ' ASC';
}
} else {
$orderby = '';
}
// Actually retrieve the rows, with offset and limit
$rs = $this->selectSet("SELECT * FROM ({$query}) AS sub {$orderby} LIMIT {$page_size} OFFSET " . ($page - 1) * $page_size);
$status = $this->endTransaction();
if ($status != 0) {
$this->rollbackTransaction();
return -1;
}
return $rs;
}