setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); self::$_db = &self::$_master_db; } /** returns value from first column of first row of query result. * accepts two types of variable substitution: '?' or ':var', * '?' expects variable parameter list, ':var' expects second argument * to be array working as dictionary * \param $query PgSQL query with optional parameter substitution * \param $params (optional) array or first parameter for '?' type query * \param $... - (optional) following parameters for '?' type query */ public static function fetchValue($query, $params = []) { self::_needsMasterDB(); $sth = self::$_db->prepare($query.';'); if (!is_array($params)) { $params = array_slice(func_get_args(),1); } $sth->execute($params); $result = $sth->fetch(PDO::FETCH_NUM); return isset($result[0]) ? $result[0] : null; } /** returns first first row of query result as assiociative array. * accepts two types of variable substitution: '?' or ':var', * '?' expects variable parameter list, ':var' expects second argument * to be array working as dictionary * \param $query PgSQL query with optional parameter substitution * \param $params (optional) array or first parameter for '?' type query * \param $... - (optional) following parameters for '?' type query */ public static function fetchRow($query, $params = []) { self::_needsMasterDB(); $sth = self::$_db->prepare($query.';'); if (!is_array($params)) { $params = array_slice(func_get_args(),1); } $sth->execute($params); return $sth->fetch(PDO::FETCH_ASSOC); } /** returns whole query result as numbered array of assiociative arrays. * accepts two types of variable substitution: '?' or ':var', * '?' expects variable parameter list, ':var' expects second argument * to be array working as dictionary * \param $query PgSQL query with optional parameter substitution * \param $params (optional) array or first parameter for '?' type query * \param $... - (optional) following parameters for '?' type query */ static public function fetchAll($query, $params = []) { self::_needsMasterDB(); $sth = self::$_db->prepare($query.';'); if (!is_array($params)) { $params = array_slice(func_get_args(),1); } $sth->execute($params); return $sth->fetchAll(PDO::FETCH_ASSOC); } static public function execute($query, $params = []) { self::_needsMasterDB(); $sth = self::$_db->prepare($query.';'); if (!is_array($params)) { $params = array_slice(func_get_args(),1); } $sth->execute($params); return $sth->rowCount(); } static public function insert($table, $values, $functions = []) { self::_needsMasterDB(); list($query,$args) = self::_insert_prepare($table,$values,$functions); $sth = self::$_db->prepare($query.';'); $sth->execute($args); return $sth->rowCount(); } static public function update($table,$values,$whereclause,$functions="") { self::_needsMasterDB(); $query = 'UPDATE "'. $table .'" SET '; $cnt=0; $where = ""; $args = []; foreach ($values as $key => $val) { if ($cnt) { $query .=', '; } $query .= '"'. $key .'"=?'; if (is_bool($val)) { $args[] = ($val) ? 'TRUE' : 'FALSE'; } else { $args[] = $val; } $cnt++; } if ($functions!="") { foreach ($functions as $key => $val) { if ($cnt) { $query .=', '; } $query .= '"'. $key .'"'. $val; $cnt++; } } if (empty($values)) { $query = 'SELECT * FROM '.$table; } if (is_array($whereclause)) { $cnt=0; foreach ($whereclause as $key => $val) { if ($cnt) { $where .=' AND '; } $where .= '("'. $key .'"=?)'; $args[] = $val; $cnt++; } $query .= " WHERE ".$where .";"; } else { $query .= " WHERE ". $whereclause .";"; } $sth = self::$_db->prepare($query.';'); $sth->execute($args); return $sth->rowCount(); } public static function set($table,$values,$wherelist,$functions = []) { $rowsAffected = self::update($table,$values,$wherelist,$functions); if ($rowsAffected == 0) { return self::insert($table,array_merge($values,$wherelist),$functions); } return $rowsAffcted; } public static function delete($table, $values, $extrarules="") { $query = 'DELETE FROM "'. $table .'" WHERE '; $cnt=0; $args = []; foreach ($values as $key => $val) { if ($cnt) { $query .= 'AND'; } $query .= ' ("'. $key .'" = ?)'; $args[] = $val; $cnt++; } if ($extrarules !== "") { $query .= ' AND '.$extrarules; } return self::execute($query,$args); } static private function _insert_prepare($table,$values,$functions = []) { $query = 'INSERT INTO "'. $table .'"('; $cnt=0; $valbuf = ""; $args = []; foreach ($values as $key => $val) { if ($cnt) { $query .=','; $valbuf.=','; } $query .= '"'. $key .'"'; $valbuf .= '?'; if (is_bool($val)) { $args[] = ($val) ? 'TRUE' : 'FALSE'; } elseif ($val===null) { $args[] = NULL; } else { $args[] = $val; } $cnt++; } foreach ($functions as $key => $val) { if ($cnt) { $query .=','; $valbuf .=','; } $query .= '"'. $key .'"'; $valbuf .= $val; $cnt++; } $query .= ") VALUES (". $valbuf .");"; return [$query, $args]; } public static function begin() { self::_needsMasterDB(); if (self::$_transaction_depth == 0) { self::$_db->beginTransaction(); self::$_transaction_depth++; } elseif (self::$_transaction_failed) { throw new Exception("Trying to begin transaction inside of already stopped transaction!"); } else { self::$_transaction_depth++; } } public static function commit() { if (self::$_transaction_depth>0) { if (self::$_transaction_failed) { // I'm not convinced that it's good idea, // but we need to be sure transaction won't go to database. self::rollback(); throw new Exception("Transaction already stopped, couldn't be commited"); } self::$_transaction_depth--; if (self::$_transaction_depth==0) { return self::$_db->commit(); } } else { throw new Exception("To commit transaction it needs to be started first"); } } public static function rollback() { self::$_transaction_failed = true; self::$_transaction_depth--; if (self::$_transaction_depth == 0) { self::$_db->rollback(); self::$_transaction_failed = false; } } public static function inTransaction() { return (self::$_transaction_depth>0); } public static function transactionStateFailed() { return self::$_transaction_failed; } } ?>