diff options
Diffstat (limited to 'dbi.class')
-rw-r--r-- | dbi.class | 226 |
1 files changed, 173 insertions, 53 deletions
@@ -65,9 +65,39 @@ function it_dbi($config, $query = null) else $this->_db = $GLOBALS['ULTRADB']; - $dbid = "$this->_db/$this->_server/$this->_user"; + $this->_dbid = "$this->_db/$this->_server/$this->_user"; - if (!($this->_link = $GLOBALS['it_dbi_link'][$dbid])) + if ($this->_createclasses) + { + $this->_connect(); + + if (!($tables = mysql_list_tables($this->_db, $this->_link))) + $this->_fatal("it_dbi(): can't list on tables \"$this->_db\": " . mysql_error($this->_link)); + + $this->_defaults = ""; + foreach($config as $key => $value) + if ($key != 'createclasses') + $this->_defaults .= "'$key' => '".strtr($value, array('\'' => '\\\'', '$' => '\\$'))."', "; + + for ($i = 0; $i < mysql_num_rows($tables); $i++) + $this->createclass(mysql_tablename($tables, $i)); + } + + if (!$GLOBALS['it_dbi']) + $GLOBALS['it_dbi'] =& $this; + + if (isset($query)) + { + if (is_array($query)) + $this->select($query); + else + $this->read($query); + } +} + +function _connect() +{ + if (!($this->_link = $GLOBALS['it_dbi_link'][$this->_dbid])) { # Use persistent connections but prevent reuse if only DB differs if (!$this->_persistent || $GLOBALS['it_dbi_connected']["$this->_server/$this->_user"]++) @@ -89,74 +119,64 @@ function it_dbi($config, $query = null) if (!(@mysql_select_db($this->_db, $this->_link))) $this->_fatal("it_dbi(): can't select database \"$this->_db\": " . mysql_error($this->_link)); - $GLOBALS['it_dbi_link'][$dbid] = $this->_link; + $GLOBALS['it_dbi_link'][$this->_dbid] = $this->_link; } +} - if ($this->_createclasses) - { - if (!($tables = mysql_list_tables($this->_db, $this->_link))) - $this->_fatal("it_dbi(): can't list on tables \"$this->_db\": " . mysql_error($this->_link)); - $defaults = ''; - foreach($config as $key => $value) - if ($key != 'createclasses') - $defaults .= "'$key' => '".strtr($value, array('\'' => '\\\'', '$' => '\\$'))."', "; +/** + * Convert table given by name into a class + */ +function createclass($table) +{ + $this->_connect(); + $classname = "$this->_classprefix$table"; - for ($i = 0; $i < mysql_num_rows($tables); $i++) - { - $table = mysql_tablename($tables, $i); - $classname = "$this->_classprefix$table"; + if (!($result = @mysql_list_fields($this->_db, $table, $this->_link))) + $this->_fatal("it_dbi(): can't list fields \"$this->_db\": " . mysql_error($this->_link)); - if ($result = @mysql_list_fields($this->_db, $table, $this->_link)) - { - for ($fields=array(), $j=0; $j < mysql_num_fields($result); $j++) - { - $fields[mysql_field_name($result, $j)] = mysql_field_len($result, $j); - $flags = mysql_field_flags($result, $j); + for ($fields=array(), $j=0; $j < mysql_num_fields($result); $j++) + { + $fields[mysql_field_name($result, $j)] = mysql_field_len($result, $j); + $flags = mysql_field_flags($result, $j); - if (strstr($flags, "primary_key")) - { - $keyfield = mysql_field_name($result, $j); - $autoincrement = (bool)strstr($flags, "auto_increment"); - $randomid = (mysql_field_type($result, $j) == "string"); - } - } + if (strstr($flags, "primary_key")) + { + $keyfield = mysql_field_name($result, $j); + $autoincrement = (bool)strstr($flags, "auto_increment"); + $randomid = (mysql_field_type($result, $j) == "string"); + } + } - $fields = var_export($fields, true); + $fields = var_export($fields, true); - if ($this->_createclasses && (substr($classname, 0, 4) != 'PMA_') && !class_exists($classname)) + if ((substr($classname, 0, 4) != 'PMA_') && !class_exists($classname)) + { + debug("it_dbi: creating class $classname", 5); + eval(" + class $classname extends it_dbi + { + function $classname(\$query = null, \$config = array()) { - debug("it_dbi: creating class $classname", 5); - eval(" - class $classname extends it_dbi - { - function $classname(\$query = null, \$config = array()) - { - \$config += array($defaults'table' => '$table', 'keyfield' => '$keyfield', 'autoincrement' => '$autoincrement', 'randomid' => '$randomid'); - \$this->_fields = $fields; - \$this->it_dbi(\$config, \$query); - } - } - "); + \$config += array({$this->_defaults}'table' => '$table', 'keyfield' => '$keyfield', 'autoincrement' => '$autoincrement', 'randomid' => '$randomid'); + \$this->_fields = $fields; + \$this->it_dbi(\$config, \$query); } } - } + "); } - - if (isset($query)) - if (is_array($query)) - $this->select($query); - else - $this->read($query); } + /** * Internal: construct SQL SET clause of changed values from member vars and tags array. * Merge current values into $tags. Modifies caller's array (callers rely on it)! */ function _set(&$tags) { + $this->_connect(); + # Add member vars to tags, considering unquoted fields foreach (get_object_vars($this) as $field => $value) # Don't use isset($tags[$field]) (would not handle null values correctly) @@ -177,10 +197,109 @@ function _set(&$tags) } -/* Intermal: construct SQL WHERE clause */ -function _where($where) +/** + * Create an SQL query (the stuff after 'WHERE') according to + * an array of selection criteria.<br> + * Example:<br> + * $sql = $table->construct_sql_clause(array('Type' => 'bar', + * 'Date >=' => '1999-01-01', '-Date <' => 'NOW()', + * 'User NI' => 'chris'), 'ORDER BY Date'); + * + * @param $params optional array of fieldname => value tupels. + * These are ANDed to form a WHERE clause. + * fieldname can contain an operator (separated by space), the + * default operator is '='. The special operator 'NI' specifies + * that the argument must be contained in a comma-separated list. + * @param $sql Optional SQL addendum (added after $params), for ORDER BY etc. + * @param $omit_where (optional) Do not add 'WHERE ' at beginning of result (default: false) + * @return The generated SQL clause + * @see it_db_record::select, it_db_record::fetch_next + */ +function _where($params='', $sql='', $omit_where=false) { - return isset($where) ? ' ' . it_db_table::construct_sql_clause($where) : ''; + if (is_array($params) && (count($params) > 0)) + { + $query = ''; + $sep = ''; + + foreach($params as $field => $value) + { + if (is_int($field)) /* no key specified; just append */ + { + if ($field === $value) /* ignore array(1 => 1) et al */ + continue; + + $query .= " $value"; + } + else + { + $needs_where = true; + + if (!isset($value)) + { + $op = 'IS'; + $qval = 'NULL'; + } + else + { + if (preg_match('/^(\S+)\s+(\S.*)$/', $field, $regs)) + { + $field = $regs[1]; + $op = strtoupper($regs[2]); + } + else + $op = '='; + + /* If the field name starts with '-', the value is taken as raw, + no escaping is done and no quotes are put around it. */ + if (substr($field, 0, 1) == '-') + { + $field = substr($field, 1); /* Strip that '-' sign */ + $qval = $value; + } + else if (!is_array($value)) + $qval = "'".mysql_real_escape_string((string)$value)."'"; + } + + switch ($op) + { + case 'NI': + $query .= $sep."CONCAT(',',$field,',') LIKE '%,$value,%'"; + break; + + case 'IN': + case 'NOT IN': + if (is_array($value)) + { + if ($value) + $query .= "$sep$field $op ('" . join("','", array_map('mysql_real_escape_string', $value)) . "')"; # null is mapped to '' + else + $query .= $sep . "0"; + + break; + } + /* FALLTHROUGH */ + + default: + if (isset($qval)) + $query .= "$sep$field $op $qval"; + else + it::fatal('Undefined $qval when constructing query due to invalid $value (array)'); + break; + } + $sep = ' AND '; + } + } + + if ($needs_where && !$omit_where) + $query = 'WHERE '.$query; + + if ($sql) + $query .= ' '; + } + $query .= $sql; + + return $query; } @@ -233,6 +352,7 @@ function clear($pp = true) */ function query($query) { + $this->_connect(); debug(get_class($this)."::query(\"$query\")", 4); $start = gettimeofday(); @@ -458,7 +578,7 @@ function delete($query = null) if ($query) { - if ($sres = $this->query(($sql = "DELETE FROM $this->_table " . $this->_where($query)))) + if ($this->query(($sql = "DELETE FROM $this->_table " . $this->_where($query)))) $result = mysql_affected_rows($this->_link); } |