clean up query parsing code -- will be necessary for transition to prepared statement approach

This commit is contained in:
Sergey Tsalkov
2013-06-02 12:49:01 -07:00
parent e94f75fe2a
commit ecd5fe190f

View File

@@ -439,14 +439,13 @@ class MeekroDB {
return $result; return $result;
} }
public function parseQueryParams() { public function preparseQueryParams() {
$args = func_get_args(); $args = func_get_args();
if (count($args) < 2) return $args[0]; $sql = trim(strval(array_shift($args)));
$sql = array_shift($args);
$args_all = $args; $args_all = $args;
$posList = array();
$pos_adj = 0; if (count($args_all) == 0) return array($sql);
$param_char_length = strlen($this->param_char); $param_char_length = strlen($this->param_char);
$named_seperator_length = strlen($this->named_param_seperator); $named_seperator_length = strlen($this->named_param_seperator);
@@ -464,6 +463,9 @@ class MeekroDB {
$this->param_char . 'ss' // search string (like string, surrounded with %'s) $this->param_char . 'ss' // search string (like string, surrounded with %'s)
); );
// generate list of all MeekroDB variables in our query, and their position
// in the form "offset => variable", sorted by offsets
$posList = array();
foreach ($types as $type) { foreach ($types as $type) {
$lastPos = 0; $lastPos = 0;
while (($pos = strpos($sql, $type, $lastPos)) !== false) { while (($pos = strpos($sql, $type, $lastPos)) !== false) {
@@ -475,19 +477,25 @@ class MeekroDB {
ksort($posList); ksort($posList);
// for each MeekroDB variable, substitute it with array(type: i, value: 53) or whatever
$chunkyQuery = array(); // preparsed query
$pos_adj = 0; // how much we've added or removed from the original sql string
foreach ($posList as $pos => $type) { foreach ($posList as $pos => $type) {
$type = substr($type, $param_char_length); $type = substr($type, $param_char_length); // variable, without % in front of it
$length_type = strlen($type) + $param_char_length; $length_type = strlen($type) + $param_char_length; // length of variable w/o %
$new_pos = $pos + $pos_adj; $new_pos = $pos + $pos_adj; // position of start of variable
$new_pos_back = $new_pos + $length_type; $new_pos_back = $new_pos + $length_type; // position of end of variable
$arg_number_length = 0; // length of any named or numbered parameter addition
// handle numbered parameters
if ($arg_number_length = strspn($sql, '0123456789', $new_pos_back)) { if ($arg_number_length = strspn($sql, '0123456789', $new_pos_back)) {
$arg_number = substr($sql, $new_pos_back, $arg_number_length); $arg_number = substr($sql, $new_pos_back, $arg_number_length);
if (! array_key_exists($arg_number, $args_all)) $this->nonSQLError("Non existent argument reference (arg $arg_number): $sql"); if (! array_key_exists($arg_number, $args_all)) $this->nonSQLError("Non existent argument reference (arg $arg_number): $sql");
$arg = $args_all[$arg_number]; $arg = $args_all[$arg_number];
// handle named parameters
} else if (substr($sql, $new_pos_back, $named_seperator_length) == $this->named_param_seperator) { } else if (substr($sql, $new_pos_back, $named_seperator_length) == $this->named_param_seperator) {
$arg_number_length = strspn($sql, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_', $arg_number_length = strspn($sql, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_',
$new_pos_back + $named_seperator_length) + $named_seperator_length; $new_pos_back + $named_seperator_length) + $named_seperator_length;
@@ -503,35 +511,59 @@ class MeekroDB {
$arg = array_shift($args); $arg = array_shift($args);
} }
if (in_array($type, array('s', 'i', 'd', 'b', 'l'))) { if ($new_pos > 0) $chunkyQuery[] = substr($sql, 0, $new_pos);
$array_type = false; $chunkyQuery[] = array('type' => $type, 'value' => $arg);
$arg = array($arg); $sql = substr($sql, $new_pos_back + $arg_number_length);
$type = 'l' . $type; $pos_adj -= $new_pos_back + $arg_number_length;
} else if ($type == 'ss') {
$result = "'%" . $this->escape(str_replace(array('%', '_'), array('\%', '\_'), $arg)) . "%'";
} else {
$array_type = true;
if (! is_array($arg)) $this->nonSQLError("Badly formatted SQL query: $sql -- expecting array, but didn't get one!");
} }
if ($type == 'ls') $result = $this->wrapStr($arg, "'", true); if (strlen($sql) > 0) $chunkyQuery[] = $sql;
return $chunkyQuery;
}
public function parseQueryParams() {
$args = func_get_args();
$chunkyQuery = call_user_func_array(array($this, 'preparseQueryParams'), $args);
$query = '';
$array_types = array('ls', 'li', 'ld', 'lb', 'll');
foreach ($chunkyQuery as $chunk) {
if (is_string($chunk)) {
$query .= $chunk;
continue;
}
$type = $chunk['type'];
$arg = $chunk['value'];
$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!");
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);
else if ($type == 'i') $result = intval($arg);
else if ($type == 'd') $result = doubleval($arg);
else if ($type == 'b') $result = $this->formatTableName($arg);
else if ($type == 'l') $result = $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 == 'li') $result = array_map('intval', $arg); else if ($type == 'li') $result = array_map('intval', $arg);
else if ($type == 'ld') $result = array_map('floatval', $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 (! $result) $this->nonSQLError("Badly formatted SQL query: $sql");
if (is_array($result)) { else $this->nonSQLError("Badly formatted SQL query: Invalid MeekroDB param $type");
if (! $array_type) $result = $result[0];
else $result = '(' . implode(',', $result) . ')';
if (is_array($result)) $this->nonSQLError("Badly formatted SQL query: $sql -- you passed an array but I didn't expect one!"); if (is_array($result)) $result = '(' . implode(',', $result) . ')';
$query .= $result;
} }
$sql = substr_replace($sql, $result, $new_pos, $length_type + $arg_number_length); return $query;
$pos_adj += strlen($result) - ($length_type + $arg_number_length);
}
return $sql;
} }