summaryrefslogtreecommitdiff
path: root/it_dbi.class
diff options
context:
space:
mode:
Diffstat (limited to 'it_dbi.class')
-rw-r--r--it_dbi.class184
1 files changed, 119 insertions, 65 deletions
diff --git a/it_dbi.class b/it_dbi.class
index a00d236..eb5b10e 100644
--- a/it_dbi.class
+++ b/it_dbi.class
@@ -212,28 +212,20 @@ function _connect($p = array())
{
# Force new link if same server/user was seen before (mysql ignores selected db)
if ($GLOBALS['it_dbi']->_connected["{$p['server']}/{$p['user']}"]++)
- $this->_link = @mysqli_connect($p['server'], $p['user'], $p['pw']);
+ list($this->_link, $error) = $this->_connect_db($p);
else
- $this->_link = @mysqli_connect($p['server'], $p['user'], $p['pw']);
+ list($this->_link, $error) = $this->_connect_db($p);
if (!$this->_link)
{
# One retry after a short delay
- it::log('sqllog', "it_dbi(): retrying DB link (mysqli_connect {$p['server']}, {$p['db']}): " . mysqli_connect_error());
+ it::log('sqllog', "it_dbi(): retrying DB link (_connect_db {$p['server']}, {$p['db']}): $error");
sleep(1);
- $this->_link = @mysqli_connect($p['server'], $p['user'], $p['pw']);
+ list($this->_link, $error) = $this->_connect_db($p);
}
if (!$this->_link)
- $this->_fatal("_connect(): can't create DB link (mysqli_connect {$p['user']}@{$p['server']}, {$p['db']}): " . mysqli_connect_error());
-
- if (!(@mysqli_select_db($this->_link, $p['db'])))
- $this->_fatal("_connect(): can't select database \"{$p['db']}\"");
-
- # set charset used for this connection
- if ($p['charset'])
- if (!mysqli_set_charset($this->_link, $p['charset']))
- $this->_fatal("_connect(): can't set charset \"{$p['charset']}\"");
+ $this->_fatal("_connect(): can't create DB link (_connect_db {$p['user']}@{$p['server']}, {$p['db']}): $error");
# NOTE: This overwrites old state but that is on purpose. New link means we should refetch all info about connection
$state['link'] = $this->_link;
@@ -453,25 +445,15 @@ function _where($params)
return $query;
}
-
/**
* Internal: Output class name::error message and terminate execution.
*/
function _fatal($text, $body = null)
{
- $text = get_class($this).'::'.$text;
-
- if ($this->_link && ($errstr = mysqli_error($this->_link)))
- $text = "\"$errstr\" in $text [errno " . mysqli_errno($this->_link) . "]";
-
- if ($this->_link && ($res = @mysqli_fetch_row(mysqli_query($this->_link, 'select database()')))) # dont create extra errs
- $text .= ", DB: " . $res[0];
-
- it::fatal(['title' => $text . ", Server: " . $this->_p['server'], 'body' => $body]);
+ it::fatal(['title' => $this->_error($text) . ", DB: " . $this->_p['db'] . ", Server: " . $this->_p['server'], 'body' => $body]);
/* NOT REACHED */
}
-
/**
* Post-process data after reading a record.
* This is a stub-function that can be overloaded.
@@ -521,10 +503,7 @@ static function _write_preprocess($data)
*/
function tables($p = array())
{
- for ($qr = $this->query('SHOW TABLES', $p); $row = mysqli_fetch_row($qr);)
- $result[] = $row[0];
-
- return (array)$result;
+ return $this->_tables($p);
}
@@ -566,21 +545,11 @@ function query($query, $p = array())
debug("{$p['user']}@{$p['server']}:{$p['db']}" . '.' . get_class($this) . "::query(\"$query\")", 4);
- if (!($result = mysqli_query($this->_link, $query, $p['unbuffered'] ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT)) && $p['safety'])
+ if (!($result = $this->_query($query, $p)))
{
- $errno = mysqli_errno($this->_link);
- if (($p['safety'] < 2) && ($errno == 1062)) # Duplicate entry
- return false;
-
- if ($errno == 2006) # mysql server has gone away: retry
- {
- it::log('sqllog', "it_dbi(): reconnecting mysqli_connect {$p['server']}, {$p['db']}");
- $this->_connect(array('reconnect' => true));
- $result = mysqli_query($this->_link, $query, $p['unbuffered'] ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT);
- }
-
- if (!$result)
- $this->_fatal("query(\"$query\") failed");
+ if ($result === false)
+ return $result;
+ $this->_fatal("query(\"$query\") failed");
}
else if (it::match('^(CREATE|ALTER|DROP) ', $query, array('utf8' => false)))
{
@@ -589,19 +558,6 @@ function query($query, $p = array())
it_dbi::_state_purgeshared($dbid);
}
- $this->_affectedrows = $this->_link->affected_rows; # get_warnings() clobbers this
- $this->_insertid = mysqli_insert_id($this->_link); # get_warnings() clobbers this
- if (($warning = $this->_link->get_warnings()))
- {
- do {
- if (!it::match(trim($this->_p['ignored_warnings'] . "|1364|1261|1051|1062", "|"), $warning->errno))
- $messages[] = $warning->message . " [error $warning->errno]";
- } while ($warning->next() && ++$checked < 20);
-
- if ($messages)
- it::error(['title' => "Mysql warning: " . $messages[0], 'body' => "$query\n\n" . join("\n", $messages) . "\n"]);
- }
-
if ($writing && $this->_p['throttle_writes'])
usleep(1000000 * (gettimeofday(true) - $start) * $this->_p['throttle_writes']);
@@ -690,11 +646,11 @@ function select(/* $query = array|string, ... */)
$this->clear();
if ($this->_result = $this->query($sql = "SELECT $what " . $this->_from($query) . " " . $this->_where($query)))
{
- $result = $this->_p['unbuffered'] ? true : mysqli_num_rows($this->_result);
+ $result = $this->_p['unbuffered'] ? true : $this->_num_rows($this->_result);
if ($calc_found_rows)
{
- list($count) = mysqli_fetch_row($this->query('SELECT FOUND_ROWS()'));
+ $count = $this->_fetch_assoc($this->query('SELECT FOUND_ROWS() AS count'))['count'];
$this->_found_rows = intval($count);
}
@@ -717,7 +673,7 @@ function iterate()
{
if (!$this->_nofetch)
{
- if ($this->_data = mysqli_fetch_assoc($this->_result))
+ if ($this->_data = $this->_fetch_assoc($this->_result))
{
if ($localizedfields = $this->_localizedfields)
foreach ($localizedfields as $field => $dummy)
@@ -922,7 +878,7 @@ function delete_untouched($query = null)
function escape_string($str)
{
$this->_connect();
- return "'" . mysqli_real_escape_string($this->_link, $str) . "'";
+ return $this->_escape_string($str);
}
@@ -939,11 +895,10 @@ function _get_field_info()
if (!($this->_fields = $state['fields'][$this->_p['table']]))
{
debug("it_dbi(): no fields for {$dbid}.{$this->_p['table']}, calculating.", 5);
- for ($res = $this->query('SHOW COLUMNS FROM ' . $this->_p['table']); $res && ($field = mysqli_fetch_assoc($res)); )
- {
- $this->_fields[$field['Field']] = $field + array('Length' => preg_match('/date|time/', $field['Type']) ? 20 : intval(it::match('\d+', $field['Type'])));
+ foreach ($this->_get_field_defs() as $name => $field) {
+ $this->_fields[$name] = $field + array('Length' => preg_match('/date|time/', $field['Type']) ? 20 : intval(it::match('\d+', $field['Type'])));
if (preg_match('/^(tiny|small|medium|)int|^float|^double/', $field['Type']))
- $this->_convertfunc[$field['Field']] = it::match('int', $field['Type']) ? "intval" : "floatval";
+ $this->_convertfunc[$name] = it::match('int', $field['Type']) ? "intval" : "floatval";
}
$this->_fieldnames = "," . join(",", array_keys((array)$this->_fields)) . ",";
@@ -1025,8 +980,8 @@ function rewind()
$this->select();
# Only rewind if not already at start and results present
- if (!$this->_nofetch && mysqli_num_rows($this->_result))
- mysqli_data_seek($this->_result, 0);
+ if (!$this->_nofetch && $this->_num_rows($this->_result))
+ $this->_seek($this->_result, 0);
$this->_iteratorkey = 0;
$this->iterate();
@@ -1057,4 +1012,103 @@ static function get($id)
return isset($id) && ($rec = new static) && $rec->read($id) ? $rec : null;
}
+
+/**
+ * Start of mysqli specific default implmementation
+ */
+
+function _escape_string($str)
+{
+ return "'" . mysqli_real_escape_string($this->_link, $str) . "'";
+}
+
+function _connect_db($p) {
+ $result = @mysqli_connect($p['server'], $p['user'], $p['pw']);
+
+ if ($result)
+ {
+ if (!(@mysqli_select_db($result, $p['db'])))
+ $this->_fatal("_connect(): can't select database \"{$p['db']}\"");
+
+ # set charset used for this connection
+ if ($p['charset'])
+ if (!mysqli_set_charset($result, $p['charset']))
+ $this->_fatal("_connect(): can't set charset \"{$p['charset']}\"");
+ }
+
+ return [$result, mysqli_connect_error()];
+}
+
+function _get_field_defs()
+{
+ for ($res = $this->query('SHOW COLUMNS FROM ' . $this->_p['table']); $res && ($field = $this->_fetch_assoc($res)); )
+ $result[$field['Field']] = it::filter_keys($field, ['Field', 'Type', 'Key', 'Extra']);
+ return $result;
+}
+
+function _tables($p) {
+ for ($qr = $this->query('SHOW TABLES', $p); $row = mysqli_fetch_row($qr);)
+ $result[] = $row[0];
+
+ return (array)$result;
+}
+
+function _query($query, $p)
+{
+ if (!($result = mysqli_query($this->_link, $query, $p['unbuffered'] ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT)) && $p['safety'])
+ {
+ $errno = mysqli_errno($this->_link);
+ if (($p['safety'] < 2) && ($errno == 1062)) # Duplicate entry
+ return false;
+
+ if ($errno == 2006) # mysql server has gone away: retry
+ {
+ it::log('sqllog', "it_dbi(): reconnecting mysqli_connect {$p['server']}, {$p['db']}");
+ $this->_connect(array('reconnect' => true));
+ $result = mysqli_query($this->_link, $query, $p['unbuffered'] ? MYSQLI_USE_RESULT : MYSQLI_STORE_RESULT);
+ }
+ }
+
+ $this->_affectedrows = $this->_link->affected_rows; # get_warnings() clobbers this
+ $this->_insertid = mysqli_insert_id($this->_link); # get_warnings() clobbers this
+ if (($warning = $this->_link->get_warnings()))
+ {
+ do {
+ if (!it::match(trim($this->_p['ignored_warnings'] . "|1364|1261|1051|1062", "|"), $warning->errno))
+ $messages[] = $warning->message . " [error $warning->errno]";
+ } while ($warning->next() && ++$checked < 20);
+
+ if ($messages)
+ it::error(['title' => "Mysql warning: " . $messages[0], 'body' => "$query\n\n" . join("\n", $messages) . "\n"]);
+ }
+
+ return $result;
+}
+
+function _fetch_assoc($res)
+{
+ return mysqli_fetch_assoc($res);
+}
+
+function _num_rows($res)
+{
+ return mysqli_num_rows($res);
+}
+
+
+function _seek($res, $offset)
+{
+ return mysqli_data_seek($res, $offset);
+}
+
+function _error($text)
+{
+ $text = get_class($this).'::'.$text;
+
+ if ($this->_link && ($errstr = mysqli_error($this->_link)))
+ $text = "\"$errstr\" in $text [errno " . mysqli_errno($this->_link) . "]";
+
+ return $text;
+}
+
} /* End class it_dbi */