array(), 'info' => array()); foreach(self::Get('SHOW FULL COLUMNS FROM #'.$table) as $fld) { $ds = array(); foreach($fld as $k => $v) { $k = strtolower($k); if($k == 'comment') { $p = explode(',', $v); $v = false; if(sizeof($p) > 0) foreach($p as $pi) { $pk = trim(nibble('=', $pi)); $ds['_'.$pk] = trim($pi); } } if($v) $ds[$k] = $v; } $ds['caption'] = first($ds['_title'], $ds['field']); $result['fields'][$ds['field']] = $ds; } return($result); } # updates/creates the $dataset in the $tablename static function Insert($tablename, $dataset) { self::$writeOps++; $query='INSERT INTO '.$tablename.' ('.DB::MakeNamesList($dataset). ') VALUES('.DB::MakeValuesList($dataset).')'; mysqli_query(self::$link, $query) or critical(mysqli_error(self::$link).'{ '.$query.' }'); self::$affectedRows += mysqli_affected_rows(self::$link); return(mysqli_insert_id(self::$link)); } # updates/creates the $dataset in the $tablename static function Commit($tablename, &$dataset) { self::$writeOps++; $keynames = self::Keys($tablename); $keyname = $keynames[0]; $keyvalue = $dataset[$keyname]; Profiler::Log('DB::Commit('.$tablename.', '.$dataset[$keyname].') start'); $cache_entry = $tablename.':'.$keyname.':'.$keyvalue; unset(self::$dataCache[$cache_entry]); $query='REPLACE INTO '.$tablename.' ('.DB::MakeNamesList($dataset). ') VALUES('.DB::MakeValuesList($dataset).');'; # keeping this around just in case, but performance seems the same: # $query='INSERT INTO '.$tablename.' ('.DB::MakeNamesList($dataset). # ') VALUES('.DB::MakeValuesList($dataset).') # ON DUPLICATE KEY UPDATE '.DB::MakeSetList($dataset).';'; mysqli_query(self::$link, $query) or critical(mysqli_error(self::$link).' { '.$query.' }'); $dataset[$keyname] = first($dataset[$keyname], mysqli_insert_id(self::$link)); self::$dataCache[$cache_entry] = $dataset; Profiler::Log('DB::Commit('.$tablename.', '.$dataset[$keyname].') done'); return($dataset[$keyname]); } static function GetRowsMatch($table, $matchOptions, $fillIfEmpty = true) { self::$readOps++; $where = array('1'); foreach($matchOptions as $k => $v) $where[] = '('.$k.'="'.DB::Safe($v).'")'; $iwhere = implode(' AND ', $where); $query = 'SELECT * FROM '.($table). ' WHERE '.$iwhere; $resultDS = self::GetRowWithQuery($query); if ($fillIfEmpty && sizeof($resultDS) == 0) foreach($matchOptions as $k => $v) $resultDS[$k] = $v; Profiler::Log('DB::GetRowsMatch('.$table.') done'); return($resultDS); } # from table $tablename, get dataset with key $keyvalue static function GetRow($tablename, $keyvalue, $keyname = '', $options = array()) { if($keyvalue == '0') return(array()); $fields = @$options['fields']; $fields = first($fields, '*'); if (!self::$link) return(array()); if ($keyname == '') { $keynames = self::Keys($tablename); $keyname = $keynames[0]; } $cache_entry = $tablename.':'.$keyname.':'.$keyvalue; if(isset(self::$dataCache[$cache_entry])) return(self::$dataCache[$cache_entry]); $join = isset($options['join']) ? ' '.$options['join'] : ''; $query = 'SELECT '.$fields.' FROM '.$tablename.$join.' WHERE '.$keyname.'="'.DB::Safe($keyvalue).'";'; $queryResult = mysqli_query(self::$link, $query) or critical(mysqli_error(self::$link).' { Query: "'.$query.'" }'); self::$readOps++; if ($line = @mysqli_fetch_array($queryResult, MYSQLI_ASSOC)) { mysqli_free_result($queryResult); self::$dataCache[$cache_entry] = $line; Profiler::Log('DB::GetRow('.$tablename.', '.$keyvalue.')'); return($line); } else $result = array(); Profiler::Log('DB::GetRow('.$tablename.', '.$keyvalue.') #fail'); return($result); } static function RemoveRow($tablename, $keyvalue, $keyname = null) { if ($keyname == null) { $keynames = self::Keys($tablename); $keyname = $keynames[0]; } $res = (mysqli_query(self::$link, 'DELETE FROM '.$tablename.' WHERE '.$keyname.'="'. DB::Safe($keyvalue).'";') or critical(' Cannot remove dataset // '.mysqli_error(self::$link))); Profiler::Log('DB::RemoveRow('.$tablename.', '.$keyvalue.') done'); self::$affectedRows += mysqli_affected_rows(self::$link); self::$writeOps++; return($res); } // retrieve dataset identified by SQL $query static function GetRowWithQuery($query, $parameters = null) { $query = self::ParseQueryParams($query, $parameters); $queryResult = mysqli_query(self::$link, $query); if(!$queryResult) return(critical('Error getting data // '.mysqli_error(self::$link).'{ '.$query.' }')); if ($line = mysqli_fetch_array($queryResult, MYSQLI_ASSOC)) { $result = $line; mysqli_free_result($queryResult); } else $result = array(); Profiler::Log('DB::GetRowWithQuery('.$query.')'); self::$readOps++; return($result); } # execute a simple update $query static function Query($query, $parameters = null) { $query = self::parseQueryParams($query, $parameters); if (substr($query, -1, 1) == ';') $query = substr($query, 0, -1); $result = (mysqli_query(self::$link, $query) or critical(' Query error // '.mysqli_error(self::$link))); Profiler::Log('DB::Query('.$query.') done'); self::$affectedRows += mysqli_affected_rows(self::$link); self::$writeOps++; return($result); } # create a comma-separated list of keys in $dataset static function MakeNamesList(&$dataset) { $result = ''; if (sizeof($dataset) > 0) foreach (array_keys($dataset) as $k) { if ($k!='') $result = $result.','.$k; } return(substr($result, 1)); } # make a name-value list for UPDATE-queries static function MakeValuesList(&$dataset) { $result = ''; if (sizeof($dataset) > 0) foreach ($dataset as $k => $v) { if ($k!='') $result = $result.',"'.DB::safe($v).'"'; } return(substr($result, 1)); } static function MakeSetList(&$dataset, $concat = ', ') { $result = array(); if (sizeof($dataset) > 0) foreach ($dataset as $k => $v) { if(substr($k, -1) == '+' || substr($k, -1) == '-') { $op = substr($k, -1); $k = substr($k, 0, -1); $result[] = $k.' = '.$k.' '.$op.' "'.DB::safe($v).'"'; } else { $result[] = $k.' = "'.DB::safe($v).'"'; } } return(implode($concat, $result)); } static function ParseQueryParams($query, $parameters = null) { if ($parameters != null) { $pctr = 0; $result = ''; for($a = 0; $a < strlen($query); $a++) { $chr = substr($query, $a, 1); if ($chr == '?') { $result .= '"'.DB::Safe($parameters[$pctr]).'"'; $pctr++; } else if ($chr == '&') { $result .= ''.intval($parameters[$pctr]).''; $pctr++; } else if ($chr == ':') { $paramName = ''; $a += 1; $pFormat = 'string'; if($query[$a] == ':') { $pFormat = 'number'; $a += 1; } while(!ctype_space($chr = substr($query, $a, 1)) && $a < strlen($query)) { $paramName .= $chr; $a += 1; } if($pFormat == 'number') $result .= ' '.($parameters[$paramName]+0).' '; else $result .= ' "'.DB::Safe($parameters[$paramName]).'" '; } else $result .= $chr; } } else $result = $query; $q = str_replace('#', cfg('db/prefix'), $result); self::$lastQuery = $q; return($q); } static function Safe($raw) { if(!self::$link) return(addslashes($raw)); else return(mysqli_real_escape_string(self::$link, $raw)); } } DB::connect();