add %? autodetection parameter, simplify functions such as insert() and update() to rely on it
This commit is contained in:
178
db.class.php
178
db.class.php
@@ -265,54 +265,11 @@ class MeekroDB {
|
|||||||
return $this->nested_transactions_count;
|
return $this->nested_transactions_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function escape($str) {
|
|
||||||
$db = $this->get();
|
|
||||||
return $db->real_escape_string($str);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sanitize($value) {
|
|
||||||
if (is_object($value) && ($value instanceof MeekroDBEval)) {
|
|
||||||
$value = $value->text;
|
|
||||||
} else {
|
|
||||||
if (is_array($value) || is_object($value)) $value = serialize($value);
|
|
||||||
|
|
||||||
if (is_string($value)) $value = "'" . $this->escape($value) . "'";
|
|
||||||
else if (is_null($value)) $value = 'NULL';
|
|
||||||
else if (is_bool($value)) $value = ($value ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function formatTableName($table) {
|
protected function formatTableName($table) {
|
||||||
$table = str_replace('`', '', $table);
|
$table = trim($table, '`');
|
||||||
if (strpos($table, '.')) {
|
|
||||||
list($table_db, $table_table) = explode('.', $table, 2);
|
|
||||||
$table = "`$table_db`.`$table_table`";
|
|
||||||
} else {
|
|
||||||
$table = "`$table`";
|
|
||||||
}
|
|
||||||
|
|
||||||
return $table;
|
if (strpos($table, '.')) return implode('.', array_map(array($this, 'formatTableName'), explode('.', $table)));
|
||||||
}
|
else return '`' . str_replace('`', '``', $table) . '`';
|
||||||
|
|
||||||
protected function prependCall($function, $args, $prepend) {
|
|
||||||
array_unshift($args, $prepend);
|
|
||||||
return call_user_func_array($function, $args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function wrapStr($strOrArray, $wrapChar, $escape = false) {
|
|
||||||
if (! is_array($strOrArray)) {
|
|
||||||
if ($escape) return $wrapChar . $this->escape($strOrArray) . $wrapChar;
|
|
||||||
else return $wrapChar . $strOrArray . $wrapChar;
|
|
||||||
} else {
|
|
||||||
$R = array();
|
|
||||||
foreach ($strOrArray as $element) {
|
|
||||||
$R[] = $this->wrapStr($element, $wrapChar, $escape);
|
|
||||||
}
|
|
||||||
return $R;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update() {
|
public function update() {
|
||||||
@@ -320,61 +277,46 @@ class MeekroDB {
|
|||||||
$table = array_shift($args);
|
$table = array_shift($args);
|
||||||
$params = array_shift($args);
|
$params = array_shift($args);
|
||||||
$where = array_shift($args);
|
$where = array_shift($args);
|
||||||
$buildquery = "UPDATE " . $this->formatTableName($table) . " SET ";
|
|
||||||
$keyval = array();
|
|
||||||
foreach ($params as $key => $value) {
|
|
||||||
$value = $this->sanitize($value);
|
|
||||||
$keyval[] = "`" . $key . "`=" . $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
$buildquery = "UPDATE " . $this->formatTableName($table) . " SET " . implode(', ', $keyval) . " WHERE " . $where;
|
$query = "UPDATE %b SET %? WHERE " . $where;
|
||||||
array_unshift($args, $buildquery);
|
|
||||||
|
array_unshift($args, $params);
|
||||||
|
array_unshift($args, $table);
|
||||||
|
array_unshift($args, $query);
|
||||||
return call_user_func_array(array($this, 'query'), $args);
|
return call_user_func_array(array($this, 'query'), $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function insertOrReplace($which, $table, $datas, $options=array()) {
|
public function insertOrReplace($which, $table, $datas, $options=array()) {
|
||||||
$datas = unserialize(serialize($datas)); // break references within array
|
$datas = unserialize(serialize($datas)); // break references within array
|
||||||
$keys = null;
|
$keys = $values = array();
|
||||||
|
|
||||||
if (isset($datas[0]) && is_array($datas[0])) {
|
if (isset($datas[0]) && is_array($datas[0])) {
|
||||||
$many = true;
|
foreach ($datas as $datum) {
|
||||||
|
ksort($datum);
|
||||||
|
if (! $keys) $keys = array_keys($datum);
|
||||||
|
$values[] = array_values($datum);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$datas = array($datas);
|
$keys = array_keys($datas);
|
||||||
$many = false;
|
$values = array_values($datas);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($datas as $data) {
|
if (isset($options['ignore']) && $options['ignore']) $which = 'INSERT IGNORE';
|
||||||
if (! $keys) {
|
|
||||||
$keys = array_keys($data);
|
if (isset($options['update']) && is_array($options['update']) && $options['update'] && strtolower($which) == 'insert') {
|
||||||
if ($many) sort($keys);
|
if (array_values($options['update']) !== $options['update']) {
|
||||||
|
return $this->query("INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE %?", $table, $keys, $values, $options['update']);
|
||||||
|
} else {
|
||||||
|
$update_str = array_shift($options['update']);
|
||||||
|
$query_param = array("INSERT INTO %b %lb VALUES %? ON DUPLICATE KEY UPDATE $update_str", $table, $keys, $values);
|
||||||
|
$query_param = array_merge($query_param, $options['update']);
|
||||||
|
return call_user_func_array(array($this, 'query'), $query_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
$insert_values = array();
|
}
|
||||||
|
|
||||||
foreach ($keys as $key) {
|
|
||||||
if ($many && !array_key_exists($key, $data)) $this->nonSQLError('insert/replace many: each assoc array must have the same keys!');
|
|
||||||
$datum = $data[$key];
|
|
||||||
$datum = $this->sanitize($datum);
|
|
||||||
$insert_values[] = $datum;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$values[] = '(' . implode(', ', $insert_values) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
$table = $this->formatTableName($table);
|
return $this->query("%l INTO %b %lb VALUES %?", $which, $table, $keys, $values);
|
||||||
$keys_str = implode(', ', $this->wrapStr($keys, '`'));
|
|
||||||
$values_str = implode(',', $values);
|
|
||||||
|
|
||||||
if (isset($options['ignore']) && $options['ignore'] && strtolower($which) == 'insert') {
|
|
||||||
return $this->query("INSERT IGNORE INTO $table ($keys_str) VALUES $values_str");
|
|
||||||
|
|
||||||
} else if (isset($options['update']) && $options['update'] && strtolower($which) == 'insert') {
|
|
||||||
return $this->query("INSERT INTO $table ($keys_str) VALUES $values_str ON DUPLICATE KEY UPDATE {$options['update']}");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return $this->query("$which INTO $table ($keys_str) VALUES $values_str");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function insert($table, $data) { return $this->insertOrReplace('INSERT', $table, $data); }
|
public function insert($table, $data) { return $this->insertOrReplace('INSERT', $table, $data); }
|
||||||
@@ -394,19 +336,10 @@ class MeekroDB {
|
|||||||
$args[0] = $data;
|
$args[0] = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($args[0])) {
|
if (is_array($args[0])) $update = $args[0];
|
||||||
$keyval = array();
|
else $update = $args;
|
||||||
foreach ($args[0] as $key => $value) {
|
|
||||||
$value = $this->sanitize($value);
|
|
||||||
$keyval[] = "`" . $key . "`=" . $value;
|
|
||||||
}
|
|
||||||
$updatestr = implode(', ', $keyval);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$updatestr = call_user_func_array(array($this, 'parseQueryParams'), $args);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->insertOrReplace('INSERT', $table, $data, array('update' => $updatestr));
|
return $this->insertOrReplace('INSERT', $table, $data, array('update' => $update));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete() {
|
public function delete() {
|
||||||
@@ -460,6 +393,7 @@ class MeekroDB {
|
|||||||
$this->param_char . 'i', // integer
|
$this->param_char . 'i', // integer
|
||||||
$this->param_char . 'd', // double / decimal
|
$this->param_char . 'd', // double / decimal
|
||||||
$this->param_char . 'b', // backtick
|
$this->param_char . 'b', // backtick
|
||||||
|
$this->param_char . '?', // infer type
|
||||||
$this->param_char . 'ss' // search string (like string, surrounded with %'s)
|
$this->param_char . 'ss' // search string (like string, surrounded with %'s)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -522,6 +456,32 @@ class MeekroDB {
|
|||||||
return $chunkyQuery;
|
return $chunkyQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function escape($str) { return "'" . $this->get()->real_escape_string(strval($str)) . "'"; }
|
||||||
|
|
||||||
|
public function sanitize($value) {
|
||||||
|
if (is_object($value) && ($value instanceof MeekroDBEval)) return $value->text;
|
||||||
|
else if (is_null($value)) return 'NULL';
|
||||||
|
else if (is_bool($value)) return ($value ? 1 : 0);
|
||||||
|
else if (is_int($value)) return $value;
|
||||||
|
else if (is_float($value)) return $value;
|
||||||
|
|
||||||
|
else if (is_array($value)) {
|
||||||
|
// non-assoc array?
|
||||||
|
if (array_values($value) === $value) {
|
||||||
|
if (is_array($value[0])) return implode(', ', array_map(array($this, 'sanitize'), $value));
|
||||||
|
else return '(' . implode(', ', array_map(array($this, 'sanitize'), $value)) . ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
$pairs = array();
|
||||||
|
foreach ($value as $k => $v) {
|
||||||
|
$pairs[] = $this->formatTableName($k) . '=' . $this->sanitize($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(', ', $pairs);
|
||||||
|
}
|
||||||
|
else return $this->escape($value);
|
||||||
|
}
|
||||||
|
|
||||||
public function parseQueryParams() {
|
public function parseQueryParams() {
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
$chunkyQuery = call_user_func_array(array($this, 'preparseQueryParams'), $args);
|
$chunkyQuery = call_user_func_array(array($this, 'preparseQueryParams'), $args);
|
||||||
@@ -538,24 +498,28 @@ class MeekroDB {
|
|||||||
$type = $chunk['type'];
|
$type = $chunk['type'];
|
||||||
$arg = $chunk['value'];
|
$arg = $chunk['value'];
|
||||||
$result = '';
|
$result = '';
|
||||||
$is_array_type = in_array($type, $array_types, true);
|
|
||||||
|
|
||||||
if ($is_array_type && !is_array($arg)) $this->nonSQLError("Badly formatted SQL query: Expected array, got scalar instead!");
|
if ($type != '?') {
|
||||||
else if (!$is_array_type && is_array($arg)) $this->nonSQLError("Badly formatted SQL query: Expected scalar, got array instead!");
|
$is_array_type = in_array($type, $array_types, true);
|
||||||
|
if ($is_array_type && !is_array($arg)) $this->nonSQLError("Badly formatted SQL query: Expected array, got scalar instead!");
|
||||||
|
else if (!$is_array_type && is_array($arg)) $this->nonSQLError("Badly formatted SQL query: Expected scalar, got array instead!");
|
||||||
|
}
|
||||||
|
|
||||||
if ($type == 's') $result = $this->wrapStr($arg, "'", true);
|
if ($type == 's') $result = $this->escape($arg);
|
||||||
else if ($type == 'i') $result = intval($arg);
|
else if ($type == 'i') $result = intval($arg);
|
||||||
else if ($type == 'd') $result = doubleval($arg);
|
else if ($type == 'd') $result = doubleval($arg);
|
||||||
else if ($type == 'b') $result = $this->formatTableName($arg);
|
else if ($type == 'b') $result = $this->formatTableName($arg);
|
||||||
else if ($type == 'l') $result = $arg;
|
else if ($type == 'l') $result = $arg;
|
||||||
else if ($type == 'ss') $result = "'%" . $this->escape(str_replace(array('%', '_'), array('\%', '\_'), $arg)) . "%'";
|
else if ($type == 'ss') $result = "%" . $this->escape(str_replace(array('%', '_'), array('\%', '\_'), $arg)) . "%";
|
||||||
|
|
||||||
else if ($type == 'ls') $result = $this->wrapStr($arg, "'", true);
|
else if ($type == 'ls') $result = array_map(array($this, 'escape'), $arg);
|
||||||
else if ($type == 'li') $result = array_map('intval', $arg);
|
else if ($type == 'li') $result = array_map('intval', $arg);
|
||||||
else if ($type == 'ld') $result = array_map('doubleval', $arg);
|
else if ($type == 'ld') $result = array_map('doubleval', $arg);
|
||||||
else if ($type == 'lb') $result = array_map(array($this, 'formatTableName'), $arg);
|
else if ($type == 'lb') $result = array_map(array($this, 'formatTableName'), $arg);
|
||||||
else if ($type == 'll') $result = $arg;
|
else if ($type == 'll') $result = $arg;
|
||||||
|
|
||||||
|
else if ($type == '?') $result = $this->sanitize($arg);
|
||||||
|
|
||||||
else $this->nonSQLError("Badly formatted SQL query: Invalid MeekroDB param $type");
|
else $this->nonSQLError("Badly formatted SQL query: Invalid MeekroDB param $type");
|
||||||
|
|
||||||
if (is_array($result)) $result = '(' . implode(',', $result) . ')';
|
if (is_array($result)) $result = '(' . implode(',', $result) . ')';
|
||||||
@@ -565,8 +529,8 @@ class MeekroDB {
|
|||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function prependCall($function, $args, $prepend) { array_unshift($args, $prepend); return call_user_func_array($function, $args); }
|
||||||
public function query() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'assoc'); }
|
public function query() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'assoc'); }
|
||||||
public function queryAllLists() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'list'); }
|
public function queryAllLists() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'list'); }
|
||||||
public function queryFullColumns() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'full'); }
|
public function queryFullColumns() { $args = func_get_args(); return $this->prependCall(array($this, 'queryHelper'), $args, 'full'); }
|
||||||
|
|||||||
Reference in New Issue
Block a user