mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
7cb9e665e9
git-svn-id: http://www.observium.org/svn/observer/trunk@3224 61d68cd4-352d-0410-923a-c4978735b2b8
422 lines
11 KiB
PHP
422 lines
11 KiB
PHP
<?php
|
|
/*
|
|
dbFacile - A Database API that should have existed from the start
|
|
Version 0.4.3
|
|
|
|
This code is covered by the MIT license http://en.wikipedia.org/wiki/MIT_License
|
|
|
|
By Alan Szlosek from http://www.greaterscope.net/projects/dbFacile
|
|
|
|
The non-OO version of dbFacile. It's a bit simplistic, but gives you the
|
|
really useful bits in non-class form.
|
|
|
|
Usage
|
|
1. Connect to MySQL as you normally would ... this code uses an existing connection
|
|
2. Use dbFacile as you normally would, without the object context
|
|
3. Oh, and dbFetchAll() is now dbFetchRows()
|
|
|
|
*/
|
|
|
|
/*
|
|
* Performs a query using the given string.
|
|
* Used by the other _query functions.
|
|
* */
|
|
function dbQuery($sql, $parameters = array()) {
|
|
global $fullSql, $debug;
|
|
$fullSql = dbMakeQuery($sql, $parameters);
|
|
if($debug) {
|
|
print Console_Color::convert("\nSQL[%y".$fullSql."%n] ");
|
|
#echo("\nSQL[".$fullSql."] ");
|
|
}
|
|
|
|
/*
|
|
if($this->logFile)
|
|
$time_start = microtime(true);
|
|
*/
|
|
|
|
$result = mysql_query($fullSql); // sets $this->result
|
|
/*
|
|
if($this->logFile) {
|
|
$time_end = microtime(true);
|
|
fwrite($this->logFile, date('Y-m-d H:i:s') . "\n" . $fullSql . "\n" . number_format($time_end - $time_start, 8) . " seconds\n\n");
|
|
}
|
|
*/
|
|
|
|
if($result === false && (error_reporting() & 1)) {
|
|
// aye. this gets triggers on duplicate Contact insert
|
|
//trigger_error('QDB - Error in query: ' . $fullSql . ' : ' . mysql_error(), E_USER_WARNING);
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/*
|
|
* Passed an array and a table name, it attempts to insert the data into the table.
|
|
* Check for boolean false to determine whether insert failed
|
|
* */
|
|
function dbInsert($data, $table) {
|
|
global $fullSql;
|
|
global $db_stats;
|
|
// the following block swaps the parameters if they were given in the wrong order.
|
|
// it allows the method to work for those that would rather it (or expect it to)
|
|
// follow closer with SQL convention:
|
|
// insert into the TABLE this DATA
|
|
if(is_string($data) && is_array($table)) {
|
|
$tmp = $data;
|
|
$data = $table;
|
|
$table = $tmp;
|
|
//trigger_error('QDB - Parameters passed to insert() were in reverse order, but it has been allowed', E_USER_NOTICE);
|
|
}
|
|
|
|
$sql = 'INSERT INTO `' . $table . '` (`' . implode('`,`', array_keys($data)) . '`) VALUES (' . implode(',', dbPlaceHolders($data)) . ')';
|
|
|
|
$time_start = microtime(true);
|
|
dbBeginTransaction();
|
|
$result = dbQuery($sql, $data);
|
|
if($result) {
|
|
$id = mysql_insert_id();
|
|
dbCommitTransaction();
|
|
#return $id;
|
|
} else {
|
|
if($table != 'Contact') {
|
|
trigger_error('QDB - Insert failed.', E_USER_WARNING);
|
|
}
|
|
dbRollbackTransaction();
|
|
#$id = false;
|
|
}
|
|
|
|
#logfile($fullSql);
|
|
|
|
$time_end = microtime(true);
|
|
$db_stats['insert_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['insert']++;
|
|
|
|
return $id;
|
|
|
|
}
|
|
|
|
/*
|
|
* Passed an array, table name, WHERE clause, and placeholder parameters, it attempts to update a record.
|
|
* Returns the number of affected rows
|
|
* */
|
|
function dbUpdate($data, $table, $where = null, $parameters = array()) {
|
|
global $fullSql;
|
|
global $db_stats;
|
|
// the following block swaps the parameters if they were given in the wrong order.
|
|
// it allows the method to work for those that would rather it (or expect it to)
|
|
// follow closer with SQL convention:
|
|
// update the TABLE with this DATA
|
|
if(is_string($data) && is_array($table)) {
|
|
$tmp = $data;
|
|
$data = $table;
|
|
$table = $tmp;
|
|
//trigger_error('QDB - The first two parameters passed to update() were in reverse order, but it has been allowed', E_USER_NOTICE);
|
|
}
|
|
|
|
// need field name and placeholder value
|
|
// but how merge these field placeholders with actual $parameters array for the WHERE clause
|
|
$sql = 'UPDATE `' . $table . '` set ';
|
|
foreach($data as $key => $value) {
|
|
$sql .= "`".$key."` ". '=:' . $key . ',';
|
|
}
|
|
$sql = substr($sql, 0, -1); // strip off last comma
|
|
|
|
if($where) {
|
|
$sql .= ' WHERE ' . $where;
|
|
$data = array_merge($data, $parameters);
|
|
}
|
|
|
|
$time_start = microtime(true);
|
|
if(dbQuery($sql, $data)) {
|
|
$return = mysql_affected_rows();
|
|
} else {
|
|
#echo("$fullSql");
|
|
trigger_error('QDB - Update failed.', E_USER_WARNING);
|
|
$return = false;
|
|
}
|
|
$time_end = microtime(true);
|
|
$db_stats['update_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['update']++;
|
|
|
|
return $return;
|
|
|
|
}
|
|
|
|
function dbDelete($table, $where = null, $parameters = array()) {
|
|
$sql = 'DELETE FROM `' . $table.'`';
|
|
if($where) {
|
|
$sql .= ' WHERE ' . $where;
|
|
}
|
|
if(dbQuery($sql, $parameters)) {
|
|
return mysql_affected_rows();
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fetches all of the rows (associatively) from the last performed query.
|
|
* Most other retrieval functions build off this
|
|
* */
|
|
function dbFetchRows($sql, $parameters = array()) {
|
|
global $db_stats;
|
|
|
|
$time_start = microtime(true);
|
|
$result = dbQuery($sql, $parameters);
|
|
|
|
if(mysql_num_rows($result) > 0) {
|
|
$rows = array();
|
|
while($row = mysql_fetch_assoc($result)) {
|
|
$rows[] = $row;
|
|
}
|
|
mysql_free_result($result);
|
|
return $rows;
|
|
}
|
|
|
|
mysql_free_result($result);
|
|
|
|
$time_end = microtime(true);
|
|
$db_stats['fetchrows_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['fetchrows']++;
|
|
|
|
// no records, thus return empty array
|
|
// which should evaluate to false, and will prevent foreach notices/warnings
|
|
return array();
|
|
}
|
|
/*
|
|
* This is intended to be the method used for large result sets.
|
|
* It is intended to return an iterator, and act upon buffered data.
|
|
* */
|
|
function dbFetch($sql, $parameters = array()) {
|
|
return dbFetchRows($sql, $parameters);
|
|
/*
|
|
// for now, don't do the iterator thing
|
|
$result = dbQuery($sql, $parameters);
|
|
if($result) {
|
|
// return new iterator
|
|
return new dbIterator($result);
|
|
} else {
|
|
return null; // ??
|
|
}
|
|
*/
|
|
}
|
|
|
|
/*
|
|
* Like fetch(), accepts any number of arguments
|
|
* The first argument is an sprintf-ready query stringTypes
|
|
* */
|
|
function dbFetchRow($sql = null, $parameters = array()) {
|
|
global $db_stats;
|
|
|
|
$time_start = microtime(true);
|
|
$result = dbQuery($sql, $parameters);
|
|
if($result) {
|
|
$row = mysql_fetch_assoc($result);
|
|
mysql_free_result($result);
|
|
$time_end = microtime(true);
|
|
|
|
$db_stats['fetchrow_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['fetchrow']++;
|
|
|
|
return $row;
|
|
} else {
|
|
return null;
|
|
}
|
|
$time_start = microtime(true);
|
|
|
|
}
|
|
|
|
/*
|
|
* Fetches the first call from the first row returned by the query
|
|
* */
|
|
function dbFetchCell($sql, $parameters = array()) {
|
|
global $db_stats;
|
|
$time_start = microtime(true);
|
|
$row = dbFetchRow($sql, $parameters);
|
|
if($row) {
|
|
return array_shift($row); // shift first field off first row
|
|
}
|
|
$time_end = microtime(true);
|
|
|
|
$db_stats['fetchcell_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['fetchcell']++;
|
|
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* This method is quite different from fetchCell(), actually
|
|
* It fetches one cell from each row and places all the values in 1 array
|
|
* */
|
|
function dbFetchColumn($sql, $parameters = array()) {
|
|
global $db_stats;
|
|
$time_start = microtime(true);
|
|
$cells = array();
|
|
foreach(dbFetch($sql, $parameters) as $row) {
|
|
$cells[] = array_shift($row);
|
|
}
|
|
$time_end = microtime(true);
|
|
|
|
$db_stats['fetchcol_sec'] += number_format($time_end - $time_start, 8);
|
|
$db_stats['fetchcol']++;
|
|
|
|
return $cells;
|
|
}
|
|
|
|
/*
|
|
* Should be passed a query that fetches two fields
|
|
* The first will become the array key
|
|
* The second the key's value
|
|
*/
|
|
function dbFetchKeyValue($sql, $parameters = array()) {
|
|
$data = array();
|
|
foreach(dbFetch($sql, $parameters) as $row) {
|
|
$key = array_shift($row);
|
|
if(sizeof($row) == 1) { // if there were only 2 fields in the result
|
|
// use the second for the value
|
|
$data[ $key ] = array_shift($row);
|
|
} else { // if more than 2 fields were fetched
|
|
// use the array of the rest as the value
|
|
$data[ $key ] = $row;
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/*
|
|
* This combines a query and parameter array into a final query string for execution
|
|
* PDO drivers don't need to use this
|
|
*/
|
|
function dbMakeQuery($sql, $parameters) {
|
|
// bypass extra logic if we have no parameters
|
|
|
|
if(sizeof($parameters) == 0)
|
|
return $sql;
|
|
|
|
$parameters = dbPrepareData($parameters);
|
|
// separate the two types of parameters for easier handling
|
|
$questionParams = array();
|
|
$namedParams = array();
|
|
foreach($parameters as $key => $value) {
|
|
if(is_numeric($key)) {
|
|
$questionParams[] = $value;
|
|
} else {
|
|
$namedParams[ ':' . $key ] = $value;
|
|
}
|
|
}
|
|
|
|
// sort namedParams in reverse to stop substring squashing
|
|
krsort($namedParams);
|
|
|
|
// split on question-mark and named placeholders
|
|
$result = preg_split('/(\?|:[a-zA-Z0-9_-]+)/', $sql, -1, PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
|
|
|
|
// every-other item in $result will be the placeholder that was found
|
|
|
|
$query = '';
|
|
for($i = 0; $i < sizeof($result); $i+=2) {
|
|
$query .= $result[ $i ];
|
|
|
|
$j = $i+1;
|
|
if(array_key_exists($j, $result)) {
|
|
$test = $result[ $j ];
|
|
if($test == '?') {
|
|
$query .= array_shift($questionParams);
|
|
} else {
|
|
$query .= $namedParams[ $test ];
|
|
}
|
|
}
|
|
}
|
|
return $query;
|
|
}
|
|
|
|
|
|
function dbPrepareData($data) {
|
|
$values = array();
|
|
|
|
foreach($data as $key=>$value) {
|
|
$escape = true;
|
|
// don't quote or esc if value is an array, we treat it
|
|
// as a "decorator" that tells us not to escape the
|
|
// value contained in the array
|
|
if(is_array($value) && !is_object($value)) {
|
|
$escape = false;
|
|
$value = array_shift($value);
|
|
}
|
|
// it's not right to worry about invalid fields in this method because we may be operating on fields
|
|
// that are aliases, or part of other tables through joins
|
|
//if(!in_array($key, $columns)) // skip invalid fields
|
|
// continue;
|
|
if($escape) {
|
|
$values[$key] = "'" . mysql_real_escape_string($value) . "'";
|
|
} else
|
|
$values[$key] = $value;
|
|
}
|
|
return $values;
|
|
}
|
|
|
|
|
|
/*
|
|
* Given a data array, this returns an array of placeholders
|
|
* These may be question marks, or ":email" type
|
|
*/
|
|
function dbPlaceHolders($values) {
|
|
$data = array();
|
|
foreach($values as $key => $value) {
|
|
if(is_numeric($key))
|
|
$data[] = '?';
|
|
else
|
|
$data[] = ':' . $key;
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
function dbBeginTransaction() {
|
|
mysql_query('begin');
|
|
}
|
|
|
|
function dbCommitTransaction() {
|
|
mysql_query('commit');
|
|
}
|
|
|
|
function dbRollbackTransaction() {
|
|
mysql_query('rollback');
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
class dbIterator implements Iterator {
|
|
private $result;
|
|
private $i;
|
|
|
|
public function __construct($r) {
|
|
$this->result = $r;
|
|
$this->i = 0;
|
|
}
|
|
public function rewind() {
|
|
mysql_data_seek($this->result, 0);
|
|
$this->i = 0;
|
|
}
|
|
public function current() {
|
|
$a = mysql_fetch_assoc($this->result);
|
|
return $a;
|
|
}
|
|
public function key() {
|
|
return $this->i;
|
|
}
|
|
public function next() {
|
|
$this->i++;
|
|
$a = mysql_data_seek($this->result, $this->i);
|
|
if($a === false) {
|
|
$this->i = 0;
|
|
}
|
|
return $a;
|
|
}
|
|
public function valid() {
|
|
return ($this->current() !== false);
|
|
}
|
|
}
|
|
*/
|
|
|
|
?>
|