public function query($sql, $params = null, $flags = 0, $wantFields = null, $offset = 0, $limit = 0) { $link = $this->link; $handler = $this->dataHandler; $wantFields = array_flip($wantFields); if ($params) { $offs = 0; foreach ($params as $p) { $i = strpos($sql, '?', $offs); if ($i === FALSE) { return 'Too many parameters supplied for the query'; } $d =& $p['data']; if (isset($p['file'])) { $fn = $p['file']; if (!preg_match('/^[0-9a-z\\.\\-]+$/i', $fn)) { return 'Illegal file name'; } $d = file_get_contents($this->path . '/' . $p['file']); } if ($p['type'] == 'b') { $d = 'X\'' . bin2hex($d) . '\''; } else { if ($p['type'] == 's') { $d = '\'' . mysqli_real_escape_string($link, $p['data']) . '\''; } else { $d = $d . ''; } } $sql = substr_replace($sql, $d, $i, 1); $offs = $i + strlen($d); } } $sqlLen = strlen($sql); if ($sqlLen > 0x80000) { $t = MySQLQuery::SimpleQuery($link, 'SHOW VARIABLES LIKE "max_allowed_packet"', TRUE); if (!$t) { throw new Exception("Query is very large ({$sqlLen} bytes). Failed to read the value of 'max_allowed_packed' MySQL variable"); } if ($sqlLen >= $t[0][1]) { throw new Exception("Length of the query ({$sqlLen} bytes) is larger than 'max_allowed_packet' variable ({$t[0][1]} bytes) in MySQL configuration file."); } } $t = microtime(TRUE); if (!$link->multi_query($sql)) { throw new Exception($link->error); } $extime = microtime(TRUE) - $t; $affRows = $link->affected_rows; $results = array(); $noData = $flags & QUERY_ONLY_FIELDS ? TRUE : FALSE; $hashing = $flags & QUERY_WITH_HASHING ? TRUE : FALSE; $totalRows = $totalSize = 0; $warning = ''; do { if (!($result = $link->use_result())) { continue; } $res = array(); $flds = array(); $resRowCnt = 0; foreach ($result->fetch_fields() as $f) { $flds[] = MySQLQuery::GetFieldParams($f); } if ($wantFields) { $flds = array_intersect_key($flds, $wantFields); } if ($handler && ($q = call_user_func_array(array($handler, 'handleResultStarted'), array(&$flds)))) { $warning = $q; } while (!$warning && !$noData) { while ($row = $result->fetch_row()) { if ($offset > 0) { $offset--; continue; } if ($this->maxRows > 0 && ++$totalRows > $this->maxRows) { $warning = "Query aborted: {$this->maxRows} record limit has been reached."; break; } else { if ($wantFields) { $row = array_intersect_key($row, $wantFields); } foreach ($row as $i => &$c) { if ($c === NULL || $c === '') { continue; } $totalSize += strlen($c); if ($hashing) { if ($flds[$i]['binary']) { $c = array('label' => 'Binary', 'hash' => md5($c)); } else { if ($this->maxCellSize > 0 && strlen($c) > $this->maxCellSize) { $c = array('label' => 'Large', 'hash' => md5($c)); } } } } if ($this->maxDataSize > 0 && $totalSize > $this->maxDataSize) { $warning = "Query aborted: {$this->maxDataSize} megabyte limit has been reached."; break; } else { if ($handler) { if ($q = call_user_func_array(array($handler, 'handleRecord'), array(&$row))) { $warning = $q; break; } } else { $res[] = $row; } } if (++$resRowCnt == $limit) { break; } } } break; } $result->free(); $a = array('data' => $handler ? NULL : $res, 'fields' => $flds, 'rowCount' => $resRowCnt); if ($flags & QUERY_CALC_FOUND_ROWS) { $t = MySQLQuery::SimpleQuery($link, 'SELECT FOUND_ROWS()', TRUE); $a['calcFoundRows'] = (int) $t[0][0]; } if ($handler) { call_user_func_array(array($handler, 'handleResultEnded'), array(&$a)); } $results[] = $a; } while ($link->more_results() && $link->next_result()); if ($flags & QUERY_WITH_FIELD_DETAILS) { $cols = array(); foreach ($results as &$r) { foreach ($r['fields'] as &$f) { if (!($t = $f['table'])) { continue; } $c =& $cols[$t]; if (!isset($c)) { $c = MySQLQuery::SimpleQuery($link, 'SHOW COLUMNS FROM ' . ($f['db'] ? '`' . $f['db'] . '`.' : '') . "`{$t}`"); if (!$c) { $f['table'] = ''; continue; } } foreach ($c as &$q) { if ($q['Field'] != $f['field']) { continue; } if ($f['type'] == 'set' || $f['type'] == 'enum') { $f['values'] = str_replace("','", ",", preg_replace("/(enum|set)\\('(.+?)'\\)/", "\\2", $q['Type'])); } else { $f['values'] = ''; } $f['default'] = $q['Default']; break; } } } } $a = array('results' => $results, 'affectedRows' => $affRows < 0 ? 0 : $affRows, 'execTime' => sprintf("%.3f", $extime)); if ($handler) { call_user_func_array(array($handler, 'handleQueryEnded'), array(&$a)); } if (is_string($warning)) { $a['warning'] = $warning; } if ($flags & QUERY_WITH_INSERT_ID) { $t = MySQLQuery::SimpleQuery($link, 'SELECT LAST_INSERT_ID()', TRUE); $a['lastInsertId'] = $t[0][0]; } return $a; }