+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * General adodb database driver.
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_recordset.php');
-
-/**
- * Abstract moodle database class
- */
-abstract class adodb_moodle_database extends moodle_database {
-
- protected $adodb;
-
- /**
- * Returns general database library name
- * Note: can be used before connect()
- * @return string db type adodb, pdo, native
- */
- protected function get_dblibrary() {
- return 'adodb';
- }
-
- /**
- * Returns localised database type name
- * Note: can be used before connect()
- * @return string
- */
- public function get_name() {
- $dbtype = $this->get_dbtype();
- return get_string($dbtype, 'install');
- }
-
- /**
- * Returns localised database configuration help.
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_help() {
- $dbtype = $this->get_dbtype();
- return get_string($dbtype.'help', 'install');
- }
-
- /**
- * Adodb preconnection routines, ususally sets up needed defines;
- */
- protected abstract function preconfigure_dbconnection();
-
- public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) {
- global $CFG;
-
- $driverstatus = $this->driver_installed();
-
- if ($driverstatus !== true) {
- throw new dml_exception('dbdriverproblem', $driverstatus);
- }
-
- ob_start();
-
- $this->store_settings($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
-
- $this->preconfigure_dbconnection();
-
- require_once($CFG->libdir.'/adodb/adodb.inc.php');
-
- $this->adodb = ADONewConnection($this->get_dbtype());
-
- // See MDL-6760 for why this is necessary. In Moodle 1.8, once we start using NULLs properly,
- // we probably want to change this value to ''.
- $this->adodb->null2null = 'A long random string that will never, ever match something we want to insert into the database, I hope. \'';
-
-
- if (!empty($this->dboptions['dbpersist'])) { // Use persistent connection
- $connected = $this->adodb->PConnect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname);
- } else { // Use single connection
- $connected = $this->adodb->Connect($this->dbhost, $this->dbuser, $this->dbpass, $this->dbname);
- }
-
- $dberr = ob_get_contents();
- ob_end_clean();
-
- if (!$connected) {
- throw new dml_connection_exception($dberr);
- }
-
- $this->configure_dbconnection();
-
- return true;
- }
-
- /**
- * Adodb post connection routines, usually sets up encoding,e tc.
- */
- protected abstract function configure_dbconnection();
-
- /**
- * Close database connection and release all resources
- * and memory (especially circular memory references).
- * Do NOT use connect() again, create a new instance if needed.
- */
- public function dispose() {
- parent::dispose(); // Call parent dispose to write/close session and other common stuff before clossing conn
- if ($this->adodb) {
- $this->adodb->Close();
- }
- }
-
- public function query_log($error=false) {
- // no logging for obsoleted adodb - it would require a lot more fixing
- return;
- }
-
- /**
- * Returns database server info array
- * @return array
- */
- public function get_server_info() {
- $this->query_start("--adodb-ServerInfo", null, SQL_QUERY_AUX);
- $info = $this->adodb->ServerInfo();
- $this->query_end(true);
- return $info;
- }
-
- /**
- * Return tables in database WITHOUT current prefix
- * @return array of table names in lowercase and without prefix
- */
- public function get_tables($usecache=true) {
- $this->query_start("--adodb-MetaTables", null, SQL_QUERY_AUX);
- $metatables = $this->adodb->MetaTables();
- $this->query_end(true);
-
- $tables = array();
-
- foreach ($metatables as $table) {
- $table = strtolower($table);
- if (empty($this->prefix) || strpos($table, $this->prefix) === 0) {
- $tablename = substr($table, strlen($this->prefix));
- $tables[$tablename] = $tablename;
- }
- }
- return $tables;
- }
-
- /**
- * Return table indexes - everything lowercased
- * @return array of arrays
- */
- public function get_indexes($table) {
- $this->query_start("--adodb-MetaIndexes", null, SQL_QUERY_AUX);
- $indexes = $this->adodb->MetaIndexes($this->prefix.$table);
- $this->query_end(true);
-
- if (!$indexes) {
- return array();
- }
- $indexes = array_change_key_case($indexes, CASE_LOWER);
- foreach ($indexes as $indexname => $index) {
- $columns = $index['columns'];
- /// column names always lowercase
- $columns = array_map('strtolower', $columns);
- $indexes[$indexname]['columns'] = $columns;
- }
-
- return $indexes;
- }
-
- public function get_columns($table, $usecache=true) {
- if ($usecache and isset($this->columns[$table])) {
- return $this->columns[$table];
- }
-
- $this->query_start("--adodb-MetaColumns", null, SQL_QUERY_AUX);
- $columns = $this->adodb->MetaColumns($this->prefix.$table);
- $this->query_end(true);
-
- if (!$columns) {
- return array();
- }
-
- $this->columns[$table] = array();
-
- foreach ($columns as $column) {
- // colum names must be lowercase
- $column->meta_type = substr($this->adodb->MetaType($column), 0 ,1); // only 1 character
- if (!empty($column->enums)) {
- // hack: fix the 'quotes' surrounding the values itroduced by adodb
- foreach ($column->enums as $key=>$value) {
- if (strpos($value, "'") === 0 and strlen($value) > 2) {
- $column->enums[$key] = substr($value, 1, strlen($value)-2);
- }
- }
- }
- $this->columns[$table][$column->name] = new database_column_info($column);
- }
-
- return $this->columns[$table];
- }
-
- public function get_last_error() {
- return $this->adodb->ErrorMsg();
- }
-
- /**
- * Do NOT use in code, to be used by database_manager only!
- * @param string $sql query
- * @return bool true
- * @throws dml_exception if error
- */
- public function change_database_structure($sql) {
- $this->reset_caches();
-
- $this->query_start($sql, null, SQL_QUERY_STRUCTURE);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- $rs->Close();
-
- return true;
- }
-
- /**
- * Execute general sql query. Should be used only when no other method suitable.
- * Do NOT use this to make changes in db structure, use database_manager::execute_sql() instead!
- * @param string $sql query
- * @param array $params query parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function execute($sql, array $params=null) {
- list($sql, $params, $type) = $this->fix_sql_params($sql, $params);
-
- if (strpos($sql, ';') !== false) {
- throw new coding_exception('moodle_database::execute() Multiple sql statements found or bound parameters not used properly in query!');
- }
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- $rs->Close();
-
- return true;
- }
-
- /**
- * Insert new record into database, as fast as possible, no safety checks, lobs not supported.
- * @param string $table name
- * @param mixed $params data record as object or array
- * @param bool $returnit return it of inserted record
- * @param bool $bulk true means repeated inserts expected
- * @param bool $customsequence true if 'id' included in $params, disables $returnid
- * @return mixed true or new id
- * @throws dml_exception if error
- */
- public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) {
- if (!is_array($params)) {
- $params = (array)$params;
- }
-
- if ($customsequence) {
- if (!isset($params['id'])) {
- throw new coding_exception('moodle_database::insert_record_raw() id field must be specified if custom sequences used.');
- }
- $returnid = false;
- } else {
- unset($params['id']);
- }
-
- if (empty($params)) {
- throw new coding_exception('moodle_database::insert_record_raw() no fields found.');
- }
-
- $fields = implode(',', array_keys($params));
- $qms = array_fill(0, count($params), '?');
- $qms = implode(',', $qms);
-
- $sql = "INSERT INTO {$this->prefix}$table ($fields) VALUES($qms)";
-
- $this->query_start($sql, $params, SQL_QUERY_INSERT);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- $rs->Close();
-
- if (!$returnid) {
- return true;
- }
-
- if (!$id = $this->adodb->Insert_ID()) {
- throw new dml_write_exception('unknown error fetching inserted id');
- }
-
- return (int)$id;
- }
-
- /**
- * Update record in database, as fast as possible, no safety checks, lobs not supported.
- * @param string $table name
- * @param mixed $params data record as object or array
- * @param bool true means repeated updates expected
- * @return bool true
- * @throws dml_exception if error
- */
- public function update_record_raw($table, $params, $bulk=false) {
- if (!is_array($params)) {
- $params = (array)$params;
- }
- if (!isset($params['id'])) {
- throw new coding_exception('moodle_database::update_record_raw() id field must be specified.');
- }
- $id = $params['id'];
- unset($params['id']);
-
- if (empty($params)) {
- throw new coding_exception('moodle_database::update_record_raw() no fields found.');
- }
-
- $sets = array();
- foreach ($params as $field=>$value) {
- $sets[] = "$field = ?";
- }
-
- $params[] = $id; // last ? in WHERE condition
-
- $sets = implode(',', $sets);
- $sql = "UPDATE {$this->prefix}$table SET $sets WHERE id=?";
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- $rs->Close();
-
- return true;
- }
-
- /**
- * Delete one or more records from a table
- *
- * @param string $table The database table to be checked against.
- * @param string $select A fragment of SQL to be used in a where clause in the SQL call (used to define the selection criteria).
- * @param array $params array of sql parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function delete_records_select($table, $select, array $params=null) {
- if ($select) {
- $select = "WHERE $select";
- }
- $sql = "DELETE FROM {$this->prefix}$table $select";
-
- list($sql, $params, $type) = $this->fix_sql_params($sql, $params);
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- $rs->Close();
-
- return true;
- }
-
- /**
- * Get a number of records as an moodle_recordset. $sql must be a complete SQL query.
- * Since this method is a little less readable, use of it should be restricted to
- * code where it's possible there might be large datasets being returned. For known
- * small datasets use get_records_sql - it leads to simpler code.
- *
- * The return type is as for @see function get_recordset.
- *
- * @param string $sql the SQL select query to execute.
- * @param array $params array of sql parameters
- * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
- * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
- * @return object moodle_recordset instance
- * @throws dml_exception if error
- */
- public function get_recordset_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
- list($sql, $params, $type) = $this->fix_sql_params($sql, $params);
-
- if ($limitfrom || $limitnum) {
- ///Special case, 0 must be -1 for ADOdb
- $limitfrom = empty($limitfrom) ? -1 : $limitfrom;
- $limitnum = empty($limitnum) ? -1 : $limitnum;
- $this->query_start($sql." --LIMIT $limitfrom, $limitnum", $params, SQL_QUERY_SELECT);
- $rs = $this->adodb->SelectLimit($sql, $limitnum, $limitfrom, $params);
- $this->query_end($rs);
- return $this->create_recordset($rs);
- }
-
- $this->query_start($sql, $params, SQL_QUERY_SELECT);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- return $this->create_recordset($rs);
- }
-
- protected function create_recordset($rs) {
- return new adodb_moodle_recordset($rs);
- }
-
- /**
- * Get a number of records as an array of objects.
- *
- * Return value as for @see function get_records.
- *
- * @param string $sql the SQL select query to execute. The first column of this SELECT statement
- * must be a unique value (usually the 'id' field), as it will be used as the key of the
- * returned array.
- * @param array $params array of sql parameters
- * @param int $limitfrom return a subset of records, starting at this point (optional, required if $limitnum is set).
- * @param int $limitnum return a subset comprising this many records (optional, required if $limitfrom is set).
- * @return array of objects indexed by first column
- * @throws dml_exception if error
- */
- public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) {
- list($sql, $params, $type) = $this->fix_sql_params($sql, $params);
-
- $rs = null;
- if ($limitfrom || $limitnum) {
- ///Special case, 0 must be -1 for ADOdb
- $limitfrom = empty($limitfrom) ? -1 : $limitfrom;
- $limitnum = empty($limitnum) ? -1 : $limitnum;
- $this->query_start($sql." --LIMIT $limitfrom, $limitnum", $params, SQL_QUERY_SELECT);
- $rs = $this->adodb->SelectLimit($sql, $limitnum, $limitfrom, $params);
- $this->query_end($rs);
- } else {
- $this->query_start($sql, $params, SQL_QUERY_SELECT);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- }
- $return = $this->adodb_recordset_to_array($rs);
- $rs->Close();
-
- return $return;
- }
-
- /**
- * Selects rows and return values of first column as array.
- *
- * @param string $sql The SQL query
- * @param array $params array of sql parameters
- * @return mixed array of values
- * @throws dml_exception if error
- */
- public function get_fieldset_sql($sql, array $params=null) {
- list($sql, $params, $type) = $this->fix_sql_params($sql, $params);
-
- $this->query_start($sql, $params, SQL_QUERY_SELECT);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- $results = array();
- while (!$rs->EOF) {
- $res = reset($rs->fields);
- $results[] = $res;
- $rs->MoveNext();
- }
- $rs->Close();
- return $results;
- }
-
- protected function adodb_recordset_to_array($rs) {
- $debugging = debugging('', DEBUG_DEVELOPER);
-
- if ($rs->EOF) {
- // BIIIG change here - return empty array() if nothing found (2.0)
- return array();
- }
-
- $objects = array();
- /// First of all, we are going to get the name of the first column
- /// to introduce it back after transforming the recordset to assoc array
- /// See http://docs.moodle.org/en/XMLDB_Problems, fetch mode problem.
- $firstcolumn = $rs->FetchField(0);
- /// Get the whole associative array
- if ($records = $rs->GetAssoc(true)) {
- foreach ($records as $key => $record) {
- $record = array($firstcolumn->name=>$key) + $record; /// Re-add the assoc field (as FIRST element since 2.0)
- $objects[$key] = (object) $record; /// To object
- }
- if ($debugging) {
- if (count($objects) != $rs->_numOfRows) {
- debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate values found in column '".$firstcolumn->name."'.", DEBUG_DEVELOPER);
- }
- }
- return $objects;
- /// Fallback in case we only have 1 field in the recordset. MDL-5877
- } else if ($rs->_numOfFields == 1 and $records = $rs->GetRows()) {
- foreach ($records as $key => $record) {
- if ($debugging && array_key_exists($record[$firstcolumn->name], $objects)) {
- debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate value '".$record[$firstcolumn->name]."' found in column '".$firstcolumn->name."'.", DEBUG_DEVELOPER);
- }
- $objects[$record[$firstcolumn->name]] = (object) $record; /// The key is the first column value (like Assoc)
- }
- return $objects;
- } else {
- // weird error?
- return false;
- }
- }
-
- public function sql_concat() {
- $args = func_get_args();
- return call_user_func_array(array($this->adodb, 'Concat'), $args);
- }
-
- public function sql_concat_join($separator="' '", $elements=array()) {
- // Intersperse $elements in the array.
- // Add items to the array on the fly, walking it
- // _backwards_ splicing the elements in. The loop definition
- // should skip first and last positions.
- for ($n=count($elements)-1; $n > 0 ; $n--) {
- array_splice($elements, $n, 0, $separator);
- }
- return call_user_func_array(array($this->adodb, 'Concat'), $elements);
- }
-
- public function begin_sql() {
- if (!parent::begin_sql()) {
- return false;
- }
- $this->adodb->BeginTrans();
- return true;
- }
- public function commit_sql() {
- if (!parent::commit_sql()) {
- return false;
- }
- $this->adodb->CommitTrans();
- return true;
- }
- public function rollback_sql() {
- if (!parent::rollback_sql()) {
- return false;
- }
- $this->adodb->RollbackTrans();
- return true;
- }
-
- /**
- * Very ugly hack which emulates bound parameters in mssql queries
- * where params not supported (UpdateBlob) :-(
- */
- protected function emulate_bound_params($sql, array $params=null) {
- if (empty($params)) {
- return $sql;
- }
- /// ok, we have verified sql statement with ? and correct number of params
- $return = strtok($sql, '?');
- foreach ($params as $param) {
- if (is_bool($param)) {
- $return .= (int)$param;
- } else if (is_null($param)) {
- $return .= 'NULL';
- } else if (is_number($param)) { // we can not use is_numeric() because it eats leading zeros from strings like 0045646
- $return .= $param;
- } else if (is_float($param)) {
- $return .= $param;
- } else {
- $param = $this->adodb->qstr($param);
- $return .= "$param";
- }
- $return .= strtok('?');
- }
- return $return;
- }
-}
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * General adodb recordset.
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_recordset.php');
-
-/**
- * Adodb basic moodle recordset class
- */
-class adodb_moodle_recordset extends moodle_recordset {
-
- protected $rs; ///ADOdb recordset
-
- public function __construct($rs) {
- $this->rs = $rs;
- }
-
- public function current() {
- return (object)$this->rs->fields;
- }
-
- public function key() {
- /// return first column value as key
- return reset($this->rs->fields);
- }
-
- public function next() {
- $this->rs->MoveNext();
- }
-
- public function valid() {
- return !$this->rs->EOF;
- }
-
- public function close() {
- $this->rs->Close();
- $this->rs = null;
- }
-}
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected abstract function get_dblibrary();
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * MSSQL database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-
-/**
- * MSSQL database class using adodb backend
- */
-class mssql_adodb_moodle_database extends adodb_moodle_database {
- /**
- * Ungly mssql hack needed for temp table names starting with '#'
- */
- public $temptables;
-
- public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) {
- if ($prefix == '' and !$this->external) {
- //Enforce prefixes for everybody but mysql
- throw new dml_exception('prefixcannotbeempty', $this->get_dbfamily());
- }
- return parent::connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
- }
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not connect to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!function_exists('mssql_connect')) {
- return get_string('mssqlextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- protected function preconfigure_dbconnection() {
- if (!defined('ADODB_ASSOC_CASE')) {
- define ('ADODB_ASSOC_CASE', 2);
- }
- }
-
- protected function configure_dbconnection() {
- $this->adodb->SetFetchMode(ADODB_FETCH_ASSOC);
-
- /// No need to set charset. It must be specified in the driver conf
- /// Allow quoted identifiers
- $sql = "SET QUOTED_IDENTIFIER ON";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
- /// Force ANSI nulls so the NULL check was done by IS NULL and NOT IS NULL
- /// instead of equal(=) and distinct(<>) simbols
- $sql = "SET ANSI_NULLS ON";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- return true;
- }
-
- /**
- * Returns database family type
- * @return string db family name (mysql, postgres, mssql, oracle, etc.)
- */
- public function get_dbfamily() {
- return 'mssql';
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'mssql';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- $str = get_string('databasesettingssub_mssql', 'install');
- $str .= "<p style='text-align:right'><a href=\"javascript:void(0)\" ";
- $str .= "onclick=\"return window.open('http://docs.moodle.org/en/Installing_MSSQL_for_PHP')\"";
- $str .= ">";
- $str .= '<img src="pix/docs.gif' . '" alt="Docs" class="iconhelp" />';
- $str .= get_string('moodledocslink', 'install') . '</a></p>';
- return $str;
- }
-
- /**
- * Converts short table name {tablename} to real table name
- * @param string sql
- * @return string sql
- */
- protected function fix_table_names($sql) {
- // look for temporary tables, they must start with #
- if (preg_match_all('/\{([a-z][a-z0-9_]*)\}/', $sql, $matches)) {
- foreach($matches[0] as $key=>$match) {
- $name = $matches[1][$key];
- if (empty($this->temptables[$name])) {
- $sql = str_replace($match, $this->prefix.$name, $sql);
- } else {
- $sql = str_replace($match, '#'.$this->prefix.$name, $sql);
- }
- }
- }
- return $sql;
- }
-
- /**
- * Returns supported query parameter types
- * @return bitmask
- */
- protected function allowed_param_types() {
- return SQL_PARAMS_QM;
- }
-
- public function sql_ceil($fieldname) {
- return ' CEILING(' . $fieldname . ')';
- }
-
- public function sql_cast_char2int($fieldname, $text=false) {
- if (!$text) {
- return ' CAST(' . $fieldname . ' AS INT) ';
- } else {
- return ' CAST(' . $this->sql_compare_text($fieldname) . ' AS INT) ';
- }
- }
-
- public function sql_order_by_text($fieldname, $numchars=32) {
- return ' CONVERT(varchar, ' . $fieldname . ', ' . $numchars . ')';
- }
-
- /**
- * Returns the SQL text to be used to calculate the length in characters of one expression.
- * @param string fieldname or expression to calculate its length in characters.
- * @return string the piece of SQL code to be used in the statement.
- */
- public function sql_length($fieldname) {
- return ' LEN(' . $fieldname . ')';
- }
-
- /**
- * Returns the SQL for returning searching one string for the location of another.
- */
- public function sql_position($needle, $haystack) {
- return "CHARINDEX(($needle), ($haystack))";
- }
-
- public function sql_isempty($tablename, $fieldname, $nullablefield, $textfield) {
- if ($textfield) {
- return $this->sql_compare_text($fieldname)." = '' ";
- } else {
- return " $fieldname = '' ";
- }
- }
-
- /**
- * Returns the proper substr() function for each DB.
- * NOTE: this was originally returning only function name
- *
- * @param string $expr some string field, no aggregates
- * @param mixed $start integer or expresion evaluating to int
- * @param mixed $length optional integer or expresion evaluating to int
- * @return string sql fragment
- */
- public function sql_substr($expr, $start, $length=false) {
- if (count(func_get_args()) < 2) {
- throw new coding_exception('moodle_database::sql_substr() requires at least two parameters', 'Originaly this function was only returning name of SQL substring function, it now requires all parameters.');
- }
- if ($length === false) {
- return "SUBSTRING($expr, $start, (LEN($expr) - $start + 1))";
- } else {
- return "SUBSTRING($expr, $start, $length)";
- }
- }
-
- /**
- * Update a record in a table
- *
- * $dataobject is an object containing needed data
- * Relies on $dataobject having a variable "id" to
- * specify the record to update
- *
- * @param string $table The database table to be checked against.
- * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
- * @param bool true means repeated updates expected
- * @return bool true
- * @throws dml_exception if error
- */
- public function update_record($table, $dataobject, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { /// Non-existing table field, skip it
- continue;
- }
- $column = $columns[$field];
-
- if (is_bool($value)) { /// Always, convert boolean to int
- $value = (int)$value;
- }
-
- if ($column->meta_type == 'B') { /// BLOBs (IMAGE) columns need to be updated apart
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- $value = null; /// Set the default value to be inserted in first instance
- }
-
- } else if ($column->meta_type == 'X') { /// MSSQL doesn't cast from int to text, so if text column
- if (is_numeric($value)) { /// and is numeric value
- $value = (string)$value; /// cast to string
- }
-
- } else if ($value === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
- $cleaned[$field] = $value;
- }
-
- if (empty($blobs)) { /// Without BLOBs, execute the raw update and return
- return $this->update_record_raw($table, $cleaned, $bulk);
- }
-
- /// We have BLOBs to postprocess, execute the raw update and then update blobs
- $this->update_record_raw($table, $cleaned, $bulk);
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = {$dataobject->id}");
- $this->query_end($result);
- }
-
- return true;
- }
-
- /**
- * Set a single field in every table row where the select statement evaluates to true.
- *
- * @param string $table The database table to be checked against.
- * @param string $newfield the field to set.
- * @param string $newvalue the value to set the field to.
- * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
- * @param array $params array of sql parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function set_field_select($table, $newfield, $newvalue, $select, array $params=null) {
-
- if (is_null($params)) {
- $params = array();
- }
- list($select, $params, $type) = $this->fix_sql_params($select, $params);
-
- $columns = $this->get_columns($table);
- $column = $columns[$newfield];
-
- if ($column->meta_type == 'B') { /// If the column is a BLOB (IMAGE)
- /// Update BLOB column and return
- $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-(
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select);
- $this->query_end($result);
- return true;
- }
-
- /// Arrived here, normal update (without BLOBs)
-
- if (is_bool($newvalue)) { /// Always, convert boolean to int
- $newvalue = (int)$newvalue;
- }
-
- if (is_null($newvalue)) {
- $newfield = "$newfield = NULL";
- } else {
- if ($column->meta_type == 'X') { /// MSSQL doesn't cast from int to text, so if text column
- if (is_numeric($newvalue)) { /// and is numeric value
- $newvalue = (string)$newvalue; /// cast to string in PHP
- }
-
- } else if ($newvalue === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $newvalue = 0; // prevent '' problems in numeric fields
- }
- }
-
- $newfield = "$newfield = ?";
- array_unshift($params, $newvalue); // add as first param
- }
- $select = !empty($select) ? "WHERE $select" : '';
- $sql = "UPDATE {$this->prefix}$table SET $newfield $select";
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
- $rs->Close();
-
- return true;
- }
-
- /**
- * Insert a record into a table and return the "id" field if required,
- * Some conversions and safety checks are carried out. Lobs are supported.
- * If the return ID isn't required, then this just reports success as true/false.
- * $data is an object containing needed data
- * @param string $table The database table to be inserted into
- * @param object $data A data object with values for one or more fields in the record
- * @param bool $returnid Should the id of the newly created record entry be returned? If this option is not requested then true/false is returned.
- * @param bool $bulk true means repeated inserts expected
- * @return mixed true or new id
- * @throws dml_exception if error
- */
- public function insert_record($table, $dataobject, $returnid=true, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- unset($dataobject->id);
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { /// Non-existing table field, skip it
- continue;
- }
- $column = $columns[$field];
-
- if (is_bool($value)) { /// Always, convert boolean to int
- $value = (int)$value;
- }
-
- if ($column->meta_type == 'B') { /// BLOBs (IMAGE) columns need to be updated apart
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- $value = null; /// Set the default value to be inserted in first instance
- }
-
- } else if ($column->meta_type == 'X') { /// MSSQL doesn't cast from int to text, so if text column
- if (is_numeric($value)) { /// and is numeric value
- $value = (string)$value; /// cast to string
- }
-
- } else if ($value === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
- $cleaned[$field] = $value;
- }
-
- if (empty($blobs)) { /// Without BLOBs, execute the raw insert and return
- return $this->insert_record_raw($table, $cleaned, $returnid, $bulk);
- }
-
- /// We have BLOBs to postprocess, insert the raw record fetching the id to be used later
- $id = $this->insert_record_raw($table, $cleaned, true, $bulk);
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- return ($returnid ? $id : true);
- }
-
- /**
- * Import a record into a table, id field is required.
- * Basic safety checks only. Lobs are supported.
- * @param string $table name of database table to be inserted into
- * @param mixed $dataobject object or array with fields in the record
- * @return bool true
- * @throws dml_exception if error
- */
- public function import_record($table, $dataobject) {
- $dataobject = (object)$dataobject;
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { // Non-existing table field, skip it
- continue;
- }
- $column = $columns[$field];
- if ($column->meta_type == 'B') { // BLOBs (IMAGE) columns need to be updated apart
- if (!is_null($value)) { // If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- $value = null; // Set the default value to be inserted in first instance
- }
- } else if ($column->meta_type == 'X') { // MSSQL doesn't cast from int to text, so if text column
- if (is_numeric($value)) { // and is numeric value
- $value = (string)$value; // cast to string
- }
- }
-
- $cleaned[$field] = $value;
- }
-
- $this->insert_record_raw($table, $cleaned, false, true, true);
-
- if (empty($blobs)) {
- return true;
- }
-
- /// We have BLOBs to postprocess
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- return true;
- }
-
- public function get_columns($table, $usecache=true) {
- if ($usecache and isset($this->columns[$table])) {
- return $this->columns[$table];
- }
-
- $this->columns[$table] = array();
-
- $tablename = strtoupper($this->prefix.$table);
-
- $sql = "SELECT column_name AS name,
- data_type AS type,
- numeric_precision AS max_length,
- character_maximum_length AS char_max_length,
- numeric_scale AS scale,
- is_nullable AS is_nullable,
- columnproperty(object_id(quotename(TABLE_SCHEMA) + '.' +
- quotename(TABLE_NAME)), COLUMN_NAME, 'IsIdentity') AS auto_increment,
- column_default AS default_value
- FROM INFORMATION_SCHEMA.Columns
- WHERE TABLE_NAME = '$tablename'
- ORDER BY ordinal_position";
-
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- $columns = $this->adodb_recordset_to_array($rs);
- $rs->Close();
-
- if (!$columns) {
- return array();
- }
-
- $this->columns[$table] = array();
-
- foreach ($columns as $column) {
- $dict = NewDataDictionary($this->adodb); // use dictionary because mssql driver lacks proper MetaType() function
- $column->meta_type = substr($dict->MetaType($column), 0 ,1); // only 1 character
- $column->meta_type = $column->meta_type == 'F' ? 'N' : $column->meta_type; // floats are numbers for us
- $column->meta_type = ($column->auto_increment && $column->meta_type == 'I') ? 'R' : $column->meta_type; // Proper 'R'
- $column->max_length = $column->meta_type == 'C' ? $column->char_max_length : $column->max_length; //Pick correct for Chars
- $column->max_length = ($column->meta_type == 'X' || $column->meta_type == 'B') ? -1 : $column->max_length; // -1 for xLOB
- $column->auto_increment = $column->auto_increment ? true : false;
- $column->not_null = $column->is_nullable == 'NO' ? true : false; // Process not_null
- $column->has_default = !empty($column->default_value); // Calculate has_default
- $column->default_value = preg_replace("/^[\(N]+[']?(.*?)[']?[\)]+$/", '\\1', $column->default_value); // Clean default
- $this->columns[$table][$column->name] = new database_column_info($column);
- }
-
- return $this->columns[$table];
- }
-
- public function get_indexes($table) {
- $indexes = parent::get_indexes($table); // AdoDB fails here, returning PK index while it shouldn't
-
- // Going to look for the primary key to delete it from the list of indexes
- $tablename = strtoupper($this->prefix.$table);
-
- $sql = "SELECT c.column_name
- FROM INFORMATION_SCHEMA.key_column_usage c
- JOIN INFORMATION_SCHEMA.table_constraints t ON t.constraint_name = c.constraint_name
- WHERE t.table_name = '$tablename'
- AND t.constraint_type = 'PRIMARY KEY'
- ORDER BY t.constraint_name, c.ordinal_position";
-
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- $columns = $this->adodb_recordset_to_array($rs);
- $rs->Close();
- /// Mimic one index array structure for easier search
- $columns = array_keys($columns);
- $primary_key = array('unique' => 1, 'columns' => $columns);
- if ($found = array_search($primary_key, $indexes)) {
- unset($indexes[$found]);
- }
- return $indexes;
- }
-}
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * MSSQL_N database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-require_once($CFG->libdir.'/dml/mssql_adodb_moodle_database.php');
-
-/**
- * MSSQL_N database class using adodb backend
- */
-class mssql_n_adodb_moodle_database extends mssql_adodb_moodle_database {
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'mssql_n';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- $str = get_string('databasesettingssub_mssql_n', 'install');
- $str .= "<p style='text-align:right'><a href=\"javascript:void(0)\" ";
- $str .= "onclick=\"return window.open('http://docs.moodle.org/en/Installing_MSSQL_for_PHP')\"";
- $str .= ">";
- $str .= '<img src="pix/docs.gif' . '" alt="Docs" class="iconhelp" />';
- $str .= get_string('moodledocslink', 'install') . '</a></p>';
- return $str;
- }
-
-}
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected function get_dblibrary() {
return 'native';
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Legacy MySQL database class using adodb backend.
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-require_once($CFG->libdir.'/dml/mysqli_adodb_moodle_database.php');
-
-/**
- * Legacy MySQL database class using adodb backend
- */
-class mysql_adodb_moodle_database extends mysqli_adodb_moodle_database {
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not try to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!extension_loaded('mysql')) {
- return get_string('mysqlextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'mysql';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- return get_string('databasesettingssub_mysql', 'install');
- }
-
-}
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Legacy MySQL database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-
-/**
- * Legacy MySQL database class using adodb backend
- */
-class mysqli_adodb_moodle_database extends adodb_moodle_database {
-
- /**
- * Attempt to create the database
- * @param string $dbhost
- * @param string $dbuser
- * @param string $dbpass
- * @param string $dbname
- * @return bool success
- * @throws dml_exception if error
- */
- public function create_database($dbhost, $dbuser, $dbpass, $dbname, array $dboptions=null) {
- $this->adodb->database = ''; // reset database name cached by ADODB. Trick from MDL-9609
- if ($this->adodb->Connect($dbhost, $dbuser, $dbpass)) { /// Try to connect without DB
- if ($this->adodb->Execute("CREATE DATABASE $dbname DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci")) {
- $this->adodb->Disconnect();
- return true;
- } else {
- return false;
- }
- }
- }
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not connect to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!extension_loaded('mysqli')) {
- return get_string('mysqliextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- protected function preconfigure_dbconnection() {
- if (!defined('ADODB_ASSOC_CASE')) {
- define ('ADODB_ASSOC_CASE', 2);
- }
- }
-
- protected function configure_dbconnection() {
- $this->adodb->SetFetchMode(ADODB_FETCH_ASSOC);
-
- $sql = "SET NAMES 'utf8'";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $result = $this->adodb->Execute($sql);
- $this->query_end($result);
-
- return true;
- }
-
- /**
- * Returns database family type
- * @return string db family name (mysql, postgres, mssql, oracle, etc.)
- */
- public function get_dbfamily() {
- return 'mysql';
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'mysqli';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- return get_string('databasesettingssub_mysqli', 'install');
- }
-
- /**
- * Returns supported query parameter types
- * @return bitmask
- */
- protected function allowed_param_types() {
- return SQL_PARAMS_QM;
- }
-
- /**
- * This method will introspect inside DB to detect it it's a UTF-8 DB or no
- * Used from setup.php to set correctly "set names" when the installation
- * process is performed without the initial and beautiful installer
- * @return bool true if db in unicode mode
- */
- function setup_is_unicodedb() {
-
- $sql = "SHOW LOCAL VARIABLES LIKE 'character_set_database'";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- if ($rs && !$rs->EOF) {
- $records = $rs->GetAssoc(true);
- $encoding = $records['character_set_database']['Value'];
- if (strtoupper($encoding) == 'UTF8') {
- return true;
- }
- }
- return false;
- }
-
- /**
- /* Tries to change default db encoding to utf8, if empty db
- * @return bool sucecss
- * @throws dml_exception if error
- */
- public function change_db_encoding() {
- // try forcing utf8 collation, if mysql db and no tables present
- $this->query_start("--adodb-MetaTables", null, SQL_QUERY_AUX);
- // TODO: maybe add separate empty database test because this ignores tables without prefix
- $metatables = $this->adodb->MetaTables();
- $this->query_end(true);
-
- if (!$metatables) {
- $sql = "ALTER DATABASE $this->dbname CHARACTER SET utf8";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
- if ($this->setup_is_unicodedb()) {
- $this->configure_dbconnection();
- return true;
- } else {
- return false;
- }
- } else {
- return false;
- }
- }
-
- /**
- * Insert a record into a table and return the "id" field if required,
- * Some conversions and safety checks are carried out. Lobs are supported.
- * If the return ID isn't required, then this just reports success as true/false.
- * $data is an object containing needed data
- * @param string $table The database table to be inserted into
- * @param object $data A data object with values for one or more fields in the record
- * @param bool $returnid Should the id of the newly created record entry be returned? If this option is not requested then true/false is returned.
- * @param bool $bulk true means repeated inserts expected
- * @return true or new id
- * @throws dml_exception if error
- */
- public function insert_record($table, $dataobject, $returnid=true, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
-
- unset($dataobject->id);
- $cleaned = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- $column = $columns[$field];
- if (is_bool($value)) {
- $value = (int)$value; // prevent "false" problems
- }
- if (!empty($column->enums)) {
- // workaround for problem with wrong enums in mysql
- if (is_null($value) and !$column->not_null) {
- // ok - nulls allowed
- } else {
- if (!in_array((string)$value, $column->enums)) {
- throw new dml_write_exception('Enum value '.s($value).' not allowed in field '.$field.' table '.$table.'.');
- }
- }
- }
- $cleaned[$field] = $value;
- }
-
- return $this->insert_record_raw($table, $cleaned, $returnid, $bulk);
- }
-
- /**
- * Update a record in a table
- *
- * $dataobject is an object containing needed data
- * Relies on $dataobject having a variable "id" to
- * specify the record to update
- *
- * @param string $table The database table to be checked against.
- * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
- * @param bool true means repeated updates expected
- * @return bool true
- * @throws dml_exception if error
- */
- public function update_record($table, $dataobject, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
- $cleaned = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- if (is_bool($value)) {
- $value = (int)$value; // prevent "false" problems
- }
- $cleaned[$field] = $value;
- }
-
- return $this->update_record_raw($table, $cleaned, $bulk);
- }
-
- /**
- * Set a single field in every table row where the select statement evaluates to true.
- *
- * @param string $table The database table to be checked against.
- * @param string $newfield the field to set.
- * @param string $newvalue the value to set the field to.
- * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
- * @param array $params array of sql parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function set_field_select($table, $newfield, $newvalue, $select, array $params=null) {
- if ($select) {
- $select = "WHERE $select";
- }
- if (is_null($params)) {
- $params = array();
- }
- list($select, $params, $type) = $this->fix_sql_params($select, $params);
-
- if (is_bool($newvalue)) {
- $newvalue = (int)$newvalue; // prevent "false" problems
- }
- if (is_null($newvalue)) {
- $newfield = "$newfield = NULL";
- } else {
- $newfield = "$newfield = ?";
- array_unshift($params, $newvalue);
- }
- $sql = "UPDATE {$this->prefix}$table SET $newfield $select";
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- return true;
- }
-
-
- public function sql_cast_char2int($fieldname, $text=false) {
- return ' CAST(' . $fieldname . ' AS SIGNED) ';
- }
-
- /**
- * Returns the SQL text to be used to calculate the length in characters of one expression.
- * @param string fieldname or expression to calculate its length in characters.
- * @return string the piece of SQL code to be used in the statement.
- */
- public function sql_length($fieldname) {
- return ' CHAR_LENGTH(' . $fieldname . ')';
- }
-
- /**
- * Does this driver suppoer regex syntax when searching
- */
- public function sql_regex_supported() {
- return true;
- }
-
- /**
- * Return regex positive or negative match sql
- * @param bool $positivematch
- * @return string or empty if not supported
- */
- public function sql_regex($positivematch=true) {
- return $positivematch ? 'REGEXP' : 'NOT REGEXP';
- }
-
- public function sql_cast_2signed($fieldname) {
- return ' CAST(' . $fieldname . ' AS SIGNED) ';
- }
-
- /**
- * Import a record into a table, id field is required.
- * Basic safety checks only. Lobs are supported.
- * @param string $table name of database table to be inserted into
- * @param mixed $dataobject object or array with fields in the record
- * @return bool true
- * @throws dml_exception if error
- */
- public function import_record($table, $dataobject) {
- $dataobject = (object)$dataobject;
-
- $columns = $this->get_columns($table);
- $cleaned = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- $cleaned[$field] = $value;
- }
-
- return $this->insert_record_raw($table, $cleaned, false, true, true);
- }
-}
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected function get_dblibrary() {
return 'native';
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Oracle database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-require_once($CFG->libdir.'/dml/oci8po_adodb_moodle_recordset.php');
-
-/**
- * Oracle database class using adodb backend
- */
-class oci8po_adodb_moodle_database extends adodb_moodle_database {
-
- public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) {
- if ($prefix == '' and !$this->external) {
- //Enforce prefixes for everybody but mysql
- throw new dml_exception('prefixcannotbeempty', $this->get_dbfamily());
- }
- if (!$this->external and strlen($prefix) > 2) {
- //Max prefix length for Oracle is 2cc
- $a = (object)array('dbfamily'=>'oracle', 'maxlength'=>2);
- throw new dml_exception('prefixtoolong', $a);
- }
- return parent::connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
- }
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not connect to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!extension_loaded('oci8')) {
- return get_string('ociextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- protected function preconfigure_dbconnection() {
- if (!defined('ADODB_ASSOC_CASE')) {
- define ('ADODB_ASSOC_CASE', 0); /// Use lowercase fieldnames for ADODB_FETCH_ASSOC
- /// (only meaningful for oci8po, it's the default
- /// for other DB drivers so this won't affect them)
- }
- /// Row prefetching uses a bit of memory but saves a ton
- /// of network latency. With current AdoDB and PHP, only
- /// Oracle uses this setting.
- if (!defined('ADODB_PREFETCH_ROWS')) {
- define ('ADODB_PREFETCH_ROWS', 1000);
- }
- }
-
- protected function configure_dbconnection() {
- $this->adodb->SetFetchMode(ADODB_FETCH_ASSOC);
-
- /// No need to set charset. It must be specified by the NLS_LANG env. variable
- /// Now set the decimal separator to DOT, Moodle & PHP will always send floats to
- /// DB using DOTS. Manually introduced floats (if using other characters) must be
- /// converted back to DOTs (like gradebook does)
- $sql = "ALTER SESSION SET NLS_NUMERIC_CHARACTERS='.,'";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- return true;
- }
-
- /**
- * Returns database family type
- * @return string db family name (mysql, postgres, mssql, oracle, etc.)
- */
- public function get_dbfamily() {
- return 'oracle';
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'oci8po';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- $str = get_string('databasesettingssub_oci8po', 'install');
- $str .= "<p style='text-align:right'><a href=\"javascript:void(0)\" ";
- $str .= "onclick=\"return window.open('http://docs.moodle.org/en/Installing_Oracle_for_PHP')\"";
- $str .= ">";
- $str .= '<img src="pix/docs.gif' . '" alt="Docs" class="iconhelp" />';
- $str .= get_string('moodledocslink', 'install') . '</a></p>';
- return $str;
- }
-
- /**
- * Returns supported query parameter types
- * @return bitmask
- */
- protected function allowed_param_types() {
- return SQL_PARAMS_QM;
- }
-
- /**
- * This method will introspect inside DB to detect it it's a UTF-8 DB or no
- * Used from setup.php to set correctly "set names" when the installation
- * process is performed without the initial and beautiful installer
- * @return bool true if db in unicode mode
- */
- function setup_is_unicodedb() {
- $sql = "SELECT parameter, value FROM nls_database_parameters where parameter = 'NLS_CHARACTERSET'";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- if ($rs && !$rs->EOF) {
- $encoding = $rs->fields['value'];
- if (strtoupper($encoding) == 'AL32UTF8') {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Selects rows and return values of first column as array.
- *
- * @param string $sql The SQL query
- * @param array $params array of sql parameters
- * @return mixed array of values
- * @throws dml_exception if error
- */
- public function get_fieldset_sql($sql, array $params=null) {
- if ($result = parent::get_fieldset_sql($sql, $params)) {
- array_walk($result, array('oci8po_adodb_moodle_database', 'onespace2empty'));
- }
- return $result;
- }
-
- protected function create_recordset($rs) {
- return new oci8po_adodb_moodle_recordset($rs);
- }
-
- protected function adodb_recordset_to_array($rs) {
- /// Really DIRTY HACK for Oracle - needed because it can not see difference from NULL and ''
- /// this can not be removed even if we chane db defaults :-(
- if ($result = parent::adodb_recordset_to_array($rs)) {
- foreach ($result as $key=>$row) {
- $row = (array)$row;
- array_walk($row, array('oci8po_adodb_moodle_database', 'onespace2empty'));
- $result[$key] = (object)$row;
- }
- }
-
- return $result;
- }
-
- public function sql_bitand($int1, $int2) {
- return 'bitand((' . $int1 . '), (' . $int2 . '))';
- }
-
- public function sql_bitnot($int1) {
- return '((0 - (' . $int1 . ')) - 1)';
- }
-
- public function sql_bitor($int1, $int2) {
- return '((' . $int1 . ') + (' . $int2 . ') - ' . $this->sql_bitand($int1, $int2) . ')';
- }
-
- public function sql_bitxor($int1, $int2) {
- return '(' . $this->sql_bitor($int1, $int2) . ' - ' . $this->sql_bitand($int1, $int2) . ')';
- }
-
- /**
- * Returns the SQL text to be used in order to perform module '%'
- * opration - remainder after division
- *
- * @param integer int1 first integer in the operation
- * @param integer int2 second integer in the operation
- * @return string the piece of SQL code to be used in your statement.
- */
- public function sql_modulo($int1, $int2) {
- return 'MOD(' . $int1 . ', ' . $int2 . ')';
- }
-
- function sql_null_from_clause() {
- return ' FROM dual';
- }
-
- public function sql_cast_char2int($fieldname, $text=false) {
- if (!$text) {
- return ' CAST(' . $fieldname . ' AS INT) ';
- } else {
- return ' CAST(' . $this->sql_compare_text($fieldname) . ' AS INT) ';
- }
- }
-
- public function sql_order_by_text($fieldname, $numchars=32) {
- return 'dbms_lob.substr(' . $fieldname . ', ' . $numchars . ',1)';
- }
-
- /**
- * Returns the SQL for returning searching one string for the location of another.
- */
- public function sql_position($needle, $haystack) {
- return "INSTR(($haystack), ($needle))";
- }
-
- public function sql_isempty($tablename, $fieldname, $nullablefield, $textfield) {
- if ($nullablefield) {
- return " $fieldname IS NULL "; /// empties in nullable fields are stored as
- } else { /// NULLs
- if ($textfield) {
- return " ".$this->sql_compare_text($fieldname)." = ' ' "; /// oracle_dirty_hack inserts 1-whitespace
- } else { /// in NOT NULL varchar and text columns so
- return " $fieldname = ' ' "; /// we need to look for that in any situation
- }
- }
- }
-
- function sql_empty() {
- return ' ';
- }
-
- /**
- * Update a record in a table
- *
- * $dataobject is an object containing needed data
- * Relies on $dataobject having a variable "id" to
- * specify the record to update
- *
- * @param string $table The database table to be checked against.
- * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
- * @param bool true means repeated updates expected
- * @return bool true
- * @throws dml_exception if error
- */
- public function update_record($table, $dataobject, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $clobs = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { /// Non-existing table field, skip it
- continue;
- }
- /// Apply Oracle dirty hack to value, to have "correct" empty values for Oracle
- $value = $this->oracle_dirty_hack($table, $field, $value);
-
- /// Get column metadata
- $column = $columns[$field];
- if ($column->meta_type == 'B') { /// BLOB columns need to be updated apart
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- continue; /// We don't want this column to be processed by update_record_raw() at all.
- /// $value = 'empty_blob()'; /// Set the default value to be inserted in first instance. Not needed to initialize lob storage in updates
- }
-
- } else if ($column->meta_type == 'X' && strlen($value) > 4000) { /// CLOB columns need to be updated apart (if lenght > 4000)
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- continue; /// We don't want this column to be processed by update_record_raw() at all.
- /// $value = 'empty_clob()'; /// Set the default value to be inserted in first instance. Not needed to initialize lob storage in updates
- }
-
- } else if (is_bool($value)) {
- $value = (int)$value; // prevent "false" problems
-
- } else if ($value === '' || $value === ' ') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
- $cleaned[$field] = $value;
- }
-
-
- if (empty($blobs) && empty($clobs)) { /// Without BLOBs and CLOBs, execute the raw update and return
- return $this->update_record_raw($table, $cleaned, $bulk);
- }
-
- /// We have BLOBs or CLOBs to postprocess, execute the raw update and then update blobs
- $this->update_record_raw($table, $cleaned, $bulk);
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = {$dataobject->id}");
- $this->query_end($result);
- }
-
- foreach ($clobs as $key=>$value) {
- $this->query_start('--adodb-UpdateClob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = {$dataobject->id}");
- $this->query_end($result);
- }
-
- return true;
- }
-
- /**
- * Insert a record into a table and return the "id" field if required,
- * Some conversions and safety checks are carried out. Lobs are supported.
- * If the return ID isn't required, then this just reports success as true/false.
- * $data is an object containing needed data
- * @param string $table The database table to be inserted into
- * @param object $data A data object with values for one or more fields in the record
- * @param bool $returnid Should the id of the newly created record entry be returned? If this option is not requested then true/false is returned.
- * @param bool $bulk true means repeated inserts expected
- * @return true or new id
- * @throws dml_exception if error
- */
- public function insert_record($table, $dataobject, $returnid=true, $bulk=false) {
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- unset($dataobject->id);
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
- $clobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { /// Non-existing table field, skip it
- continue;
- }
- /// Apply Oracle dirty hack to value, to have "correct" empty values for Oracle
- $value = $this->oracle_dirty_hack($table, $field, $value);
-
- /// Get column metadata
- $column = $columns[$field];
- if ($column->meta_type == 'B') { /// BLOBs columns need to be updated apart
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- $value = 'empty_blob()'; /// Set the default value to be inserted (preparing lob storage for next update)
- }
-
- } else if ($column->meta_type == 'X' && strlen($value) > 4000) { /// CLOB columns need to be updated apart (if lenght > 4000)
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $clobs[$field] = $value;
- $value = 'empty_clob()'; /// Set the default value to be inserted (preparing lob storage for next update)
- }
-
- } else if (is_bool($value)) {
- $value = (int)$value; // prevent "false" problems
-
- } else if ($value === '' || $value === ' ') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
- $cleaned[$field] = $value;
- }
-
- if (empty($blobs) && empty($clobs)) { /// Without BLOBs and CLOBs, execute the raw insert and return
- return $this->insert_record_raw($table, $cleaned, $returnid, $bulk);
- }
-
- /// We have BLOBs or CLOBs to postprocess, insert the raw record fetching the id to be used later
- $id = $this->insert_record_raw($table, $cleaned, true, $bulk);
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- foreach ($clobs as $key=>$value) {
- $this->query_start('--adodb-UpdateClob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- return ($returnid ? $id : true);
- }
-
- /**
- * Set a single field in every table row where the select statement evaluates to true.
- *
- * @param string $table The database table to be checked against.
- * @param string $newfield the field to set.
- * @param string $newvalue the value to set the field to.
- * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
- * @param array $params array of sql parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function set_field_select($table, $newfield, $newvalue, $select, array $params=null) {
-
- if (is_null($params)) {
- $params = array();
- }
- list($select, $params, $type) = $this->fix_sql_params($select, $params);
-
- /// Apply Oracle dirty hack to value, to have "correct" empty values for Oracle
- $newvalue = $this->oracle_dirty_hack($table, $newfield, $newvalue);
-
- /// Get column metadata
- $columns = $this->get_columns($table);
- $column = $columns[$newfield];
-
- if ($column->meta_type == 'B') { /// If the column is a BLOB
- /// Update BLOB column and return
- $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-(
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select);
- $this->query_end($result);
- return true;
- }
-
- if ($column->meta_type == 'X' && strlen($newvalue) > 4000) { /// If the column is a CLOB with lenght > 4000
- /// Update BLOB column and return
- $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-(
- $this->query_start('--adodb-UpdateClob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateClob($this->prefix.$table, $newfield, $newvalue, $select);
- $this->query_end($result);
- return true;
- }
-
- /// Arrived here, normal update (without BLOBs)
- if (is_null($newvalue)) {
- $newfield = "$newfield = NULL";
- } else {
- if (is_bool($newvalue)) {
- $newvalue = (int)$newvalue; // prevent "false" problems
- } else if ($newvalue === '' || $newvalue === ' ') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $newvalue = 0; // prevent '' problems in numeric fields
- }
- }
-
- $newfield = "$newfield = ?";
- array_unshift($params, $newvalue); // add as first param
- }
- $select = !empty($select) ? "WHERE $select" : '';
- $sql = "UPDATE {$this->prefix}$table SET $newfield $select";
-
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- return true;
- }
-
- /**
- * Insert new record into database, as fast as possible, no safety checks, lobs not supported.
- * (overloaded from adodb_moodle_database because of sequence numbers and empty_blob()/empty_clob())
- * @param string $table name
- * @param mixed $params data record as object or array
- * @param bool $returnit return it of inserted record
- * @param bool $bulk true means repeated inserts expected
- * @param bool $customsequence true if 'id' included in $params, disables $returnid
- * @return true or new id
- * @throws dml_exception if error
- */
- public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) {
- if (!is_array($params)) {
- $params = (array)$params;
- }
-
- if ($customsequence) {
- if (!isset($params['id'])) {
- throw new coding_exception('moodle_database::insert_record_raw() id field must be specified if custom sequences used.');
- }
- $returnid = false;
- } else {
- unset($params['id']);
- }
-
- if ($returnid) {
- $dbman = $this->get_manager();
- $xmldb_table = new xmldb_table($table);
- $this->query_start('--find_sequence_name', null, SQL_QUERY_AUX);
- $seqname = $dbman->find_sequence_name($xmldb_table);
- $this->query_end(true);
- if (!$seqname) {
- /// Fallback, seqname not found, something is wrong. Inform and use the alternative getNameForObject() method
- $generator = $this->get_dbman()->generator;
- $generator->setPrefix($this->getPrefix());
- $seqname = $generator->getNameForObject($table, 'id', 'seq');
- }
- $xmldb_table = new xmldb_table($table);
- $this->query_start('--adodb-GenID', null, SQL_QUERY_AUX);
- $nextval = $this->adodb->GenID($seqname);
- $this->query_end(true);
-
- if ($nextval) {
- $params['id'] = (int)$nextval;
- }
- }
-
- if (empty($params)) {
- throw new coding_exception('moodle_database::insert_record_raw() no fields found.');
- }
-
- $fields = implode(',', array_keys($params));
- $qms = array();
- /// Look for 'empty_clob() and empty_blob() params to replace question marks properly
- /// Oracle requires those function calls on insert to prepare blob/clob storage, so we
- /// specify them as SQL, deleting them from parameters
- foreach ($params as $key=>$param) {
- if ($param === 'empty_blob()') {
- $qms[] = 'empty_blob()';
- unset($params[$key]);
- } else if ($param === 'empty_clob()') {
- $qms[] = 'empty_clob()';
- unset($params[$key]);
- } else {
- $qms[] = '?';
- }
- }
- $qms = implode(',', $qms);
-
- $sql = "INSERT INTO {$this->prefix}$table ($fields) VALUES($qms)";
-
- $this->query_start($sql, $params, SQL_QUERY_INSERT);
- $rs = $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- if (!$returnid) {
- return true;
- }
- if (!empty($params['id'])) {
- return (int)$params['id'];
- }
-
- throw new dml_write_exception('unknown error fetching inserted id');
- }
-
- /**
- * This function is used to convert all the Oracle 1-space defaults to the empty string
- * like a really DIRTY HACK to allow it to work better until all those NOT NULL DEFAULT ''
- * fields will be out from Moodle.
- * @param string the string to be converted to '' (empty string) if it's ' ' (one space)
- * @param mixed the key of the array in case we are using this function from array_walk,
- * defaults to null for other (direct) uses
- * @return boolean always true (the converted variable is returned by reference)
- */
- static function onespace2empty(&$item, $key=null) {
- $item = $item == ' ' ? '' : $item;
- return true;
- }
-
- /**
- * This function will handle all the records before being inserted/updated to DB for Oracle
- * installations. This is because the "special feature" of Oracle where the empty string is
- * equal to NULL and this presents a problem with all our currently NOT NULL default '' fields.
- *
- * Once Moodle DB will be free of this sort of false NOT NULLS, this hack could be removed safely
- *
- * Note that this function is 100% private and should be used, exclusively by DML functions
- * in this file. Also, this is considered a DIRTY HACK to be removed when possible. (stronk7)
- *
- * This function is private and must not be used outside this driver at all
- *
- * @param $table string the table where the record is going to be inserted/updated (without prefix)
- * @param $field string the field where the record is going to be inserted/updated
- * @param $value mixed the value to be inserted/updated
- */
- private function oracle_dirty_hack ($table, $field, $value) {
-
- /// Get metadata
- $columns = $this->get_columns($table);
- if (!isset($columns[$field])) {
- return $value;
- }
- $column = $columns[$field];
-
- /// For Oracle DB, empty strings are converted to NULLs in DB
- /// and this breaks a lot of NOT NULL columns currenty Moodle. In the future it's
- /// planned to move some of them to NULL, if they must accept empty values and this
- /// piece of code will become less and less used. But, for now, we need it.
- /// What we are going to do is to examine all the data being inserted and if it's
- /// an empty string (NULL for Oracle) and the field is defined as NOT NULL, we'll modify
- /// such data in the best form possible ("0" for booleans and numbers and " " for the
- /// rest of strings. It isn't optimal, but the only way to do so.
- /// In the oppsite, when retrieving records from Oracle, we'll decode " " back to
- /// empty strings to allow everything to work properly. DIRTY HACK.
-
- /// If the field ins't VARCHAR or CLOB, skip
- if ($column->meta_type != 'C' and $column->meta_type != 'X') {
- return $value;
- }
-
- /// If the field isn't NOT NULL, skip (it's nullable, so accept empty-null values)
- if (!$column->not_null) {
- return $value;
- }
-
- /// If the value isn't empty, skip
- if (!empty($value)) {
- return $value;
- }
-
- /// Now, we have one empty value, going to be inserted to one NOT NULL, VARCHAR2 or CLOB field
- /// Try to get the best value to be inserted
-
- /// The '0' string doesn't need any transformation, skip
- if ($value === '0') {
- return $value;
- }
-
- /// Transformations start
- if (gettype($value) == 'boolean') {
- return '0'; /// Transform false to '0' that evaluates the same for PHP
-
- } else if (gettype($value) == 'integer') {
- return '0'; /// Transform 0 to '0' that evaluates the same for PHP
-
- } else if (gettype($value) == 'NULL') {
- return '0'; /// Transform NULL to '0' that evaluates the same for PHP
-
- } else if ($value === '') {
- return ' '; /// Transform '' to ' ' that DONT'T EVALUATE THE SAME
- /// (we'll transform back again on get_records_XXX functions and others)!!
- }
-
- /// Fail safe to original value
- return $value;
- }
-
- /**
- * Import a record into a table, id field is required.
- * Basic safety checks only. Lobs are supported.
- * @param string $table name of database table to be inserted into
- * @param mixed $dataobject object or array with fields in the record
- * @return bool success
- */
- public function import_record($table, $dataobject) {
- $dataobject = (object)$dataobject;
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
- $clobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) { /// Non-existing table field, skip it
- continue;
- }
- /// Apply Oracle dirty hack to value, to have "correct" empty values for Oracle
- $value = $this->oracle_dirty_hack($table, $field, $value);
-
- /// Get column metadata
- $column = $columns[$field];
- if ($column->meta_type == 'B') { /// BLOBs columns need to be updated apart
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $blobs[$field] = $value;
- $value = 'empty_blob()'; /// Set the default value to be inserted (preparing lob storage for next update)
- }
-
- } else if ($column->meta_type == 'X' && strlen($value) > 4000) { /// CLOB columns need to be updated apart (if lenght > 4000)
- if (!is_null($value)) { /// If value not null, add it to the list of BLOBs to update later
- $clobs[$field] = $value;
- $value = 'empty_clob()'; /// Set the default value to be inserted (preparing lob storage for next update)
- }
- }
-
- $cleaned[$field] = $value;
- }
-
- $this->insert_record_raw($table, $cleaned, false, true, true);
-
- if (empty($blobs) and empty($clobs)) {
- return true;
- }
-
- /// We have BLOBs or CLOBs to postprocess
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- foreach ($clobs as $key=>$value) {
- $this->query_start('--adodb-UpdateClob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = $id");
- $this->query_end($result);
- }
-
- return true;
- }
-}
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Oracle moodle recordest with special hacks
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/adodb_moodle_recordset.php');
-
-/**
- * Oracle moodle recordest with special hacks
- */
-class oci8po_adodb_moodle_recordset extends adodb_moodle_recordset {
-
- public function current() {
- /// Really DIRTY HACK for Oracle - needed because it can not see difference from NULL and ''
- /// this can not be removed even if we change db defaults :-(
- $fields = $this->rs->fields;
- array_walk($fields, array('oci8po_adodb_moodle_database', 'onespace2empty'));
- return (object)$fields;
- }
-}
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected function get_dblibrary() {
return 'native';
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Experimenta mssql odbc database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-require_once($CFG->libdir.'/dml/mssql_adodb_moodle_database.php');
-
-/**
- * Experimenta mssql odbc database class using adodb backend
- */
-class odbc_mssql_adodb_moodle_database extends mssql_adodb_moodle_database {
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not connect to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!extension_loaded('odbc')) {
- return get_string('odbcextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'odbc_mssql';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- $str = get_string('databasesettingssub_odbc_mssql', 'install');
- $str .= "<p style='text-align:right'><a href=\"javascript:void(0)\" ";
- $str .= "onclick=\"return window.open('http://docs.moodle.org/en/Installing_MSSQL_for_PHP')\"";
- $str .= ">";
- $str .= '<img src="pix/docs.gif' . '" alt="Docs" class="iconhelp" />';
- $str .= get_string('moodledocslink', 'install') . '</a></p>';
- return $str;
- }
-
-}
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected function get_dblibrary() {
return 'pdo';
/**
* Returns general database library name
* Note: can be used before connect()
- * @return string db type adodb, pdo, native
+ * @return string db type pdo, native
*/
protected function get_dblibrary() {
return 'native';
+++ /dev/null
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
-
-
-/**
- * Postgresql database class using adodb backend
- *
- * TODO: delete before branching 2.0
- *
- * @package moodlecore
- * @subpackage DML
- * @copyright 2008 Petr Skoda (http://skodak.org)
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-require_once($CFG->libdir.'/dml/moodle_database.php');
-require_once($CFG->libdir.'/dml/adodb_moodle_database.php');
-
-/**
- * Postgresql database class using adodb backend
- */
-class postgres7_adodb_moodle_database extends adodb_moodle_database {
-
- public function connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, array $dboptions=null) {
- if ($prefix == '' and !$this->external) {
- //Enforce prefixes for everybody but mysql
- throw new dml_exception('prefixcannotbeempty', $this->get_dbfamily());
- }
- return parent::connect($dbhost, $dbuser, $dbpass, $dbname, $prefix, $dboptions);
- }
-
- /**
- * Detects if all needed PHP stuff installed.
- * Do not connect to connect to db if this test fails.
- * @return mixed true if ok, string if something
- */
- public function driver_installed() {
- if (!extension_loaded('pgsql')) {
- return get_string('pgsqlextensionisnotpresentinphp', 'install');
- }
- return true;
- }
-
- protected function preconfigure_dbconnection() {
- if (!defined('ADODB_ASSOC_CASE')) {
- define ('ADODB_ASSOC_CASE', 2);
- }
- }
-
- protected function configure_dbconnection() {
- $this->adodb->SetFetchMode(ADODB_FETCH_ASSOC);
-
- $sql = "SET NAMES 'utf8'";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $result = $this->adodb->Execute($sql);
- $this->query_end($result);
-
- return true;
- }
-
- /**
- * Returns database family type
- * @return string db family name (mysql, postgres, mssql, oracle, etc.)
- */
- public function get_dbfamily() {
- return 'postgres';
- }
-
- /**
- * Returns database type
- * @return string db type mysql, mysqli, postgres7
- */
- protected function get_dbtype() {
- return 'postgres7';
- }
-
- /**
- * Returns localised database description
- * Note: can be used before connect()
- * @return string
- */
- public function get_configuration_hints() {
- return get_string('databasesettingssub_postgres7', 'install');
- }
-
- /**
- * Returns db related part of config.php
- * @return object
- */
- public function export_dbconfig() {
- $cfg = new stdClass();
- $cfg->dbtype = $this->get_dbtype();
- $cfg->dblibrary = $this->get_dblibrary();
- if ($this->dbhost == 'localhost' or $this->dbhost == '127.0.0.1') {
- $cfg->dbhost = "user='{$this->dbuser}' password='{$this->dbpass}' dbname='{$this->dbname}'";
- $cfg->dbname = '';
- $cfg->dbuser = '';
- $cfg->dbpass = '';
- } else {
- $cfg->dbhost = $this->dbhost;
- $cfg->dbname = $this->dbname;
- $cfg->dbuser = $this->dbuser;
- $cfg->dbpass = $this->dbpass;
- }
- $cfg->prefix = $this->prefix;
- if ($this->dboptions) {
- $cfg->dboptions = $this->dboptions;
- }
-
- return $cfg;
- }
-
- /**
- * Returns supported query parameter types
- * @return bitmask
- */
- protected function allowed_param_types() {
- return SQL_PARAMS_QM;
- }
-
- public function get_columns($table, $usecache=true) {
- if ($usecache and isset($this->columns[$table])) {
- return $this->columns[$table];
- }
-
- $this->query_start("--adodb-MetaColumns", null, SQL_QUERY_AUX);
- $columns = $this->adodb->MetaColumns($this->prefix.$table);
- $this->query_end(true);
-
- if (!$columns) {
- return array();
- }
-
- $this->columns[$table] = array();
-
- foreach ($columns as $column) {
- // colum names must be lowercase
- $column->meta_type = substr($this->adodb->MetaType($column), 0 ,1); // only 1 character
- // Let's fix the wrong meta type retrieved because of default blobSize=100 in AdoDB
- if ($column->type == 'varchar' && $column->meta_type == 'X') {
- $column->meta_type = 'C';
- }
- if ($column->has_default) {
- if ($pos = strpos($column->default_value, '::')) {
- if (strpos($column->default_value, "'") === 0) {
- $column->default_value = substr($column->default_value, 1, $pos-2);
- } else {
- $column->default_value = substr($column->default_value, 0, $pos);
- }
- }
- } else {
- $column->default_value = null;
- }
- $this->columns[$table][$column->name] = new database_column_info($column);
- }
-
- return $this->columns[$table];
- }
-
- /**
- * This method will introspect inside DB to detect it it's a UTF-8 DB or no
- * Used from setup.php to set correctly "set names" when the installation
- * process is performed without the initial and beautiful installer
- * @return bool true if db in unicode mode
- */
- function setup_is_unicodedb() {
- /// Get PostgreSQL server_encoding value
- $sql = "SHOW server_encoding";
- $this->query_start($sql, null, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql);
- $this->query_end($rs);
-
- if ($rs && !$rs->EOF) {
- $encoding = $rs->fields['server_encoding'];
- if (strtoupper($encoding) == 'UNICODE' || strtoupper($encoding) == 'UTF8') {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Insert new record into database, as fast as possible, no safety checks, lobs not supported.
- * (overloaded from adodb_moodle_database because of sequence numbers
- * @param string $table name
- * @param mixed $params data record as object or array
- * @param bool $returnit return it of inserted record
- * @param bool $bulk true means repeated inserts expected
- * @param bool $customsequence true if 'id' included in $params, disables $returnid
- * @return true or new id
- * @throws dml_exception if error
- */
- public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) {
- if (!is_array($params)) {
- $params = (array)$params;
- }
-
- if ($customsequence) {
- if (!isset($params['id'])) {
- throw new coding_exception('moodle_database::insert_record_raw() id field must be specified if custom sequences used.');
- }
- $returnid = false;
-
- } else {
- unset($params['id']);
- /// Postgres doesn't have the concept of primary key built in
- /// and will return the OID which isn't what we want.
- /// The efficient and transaction-safe strategy is to
- /// move the sequence forward first, and make the insert
- /// with an explicit id.
- if ($returnid) {
- $seqname = "{$this->prefix}{$table}_id_seq";
- $this->query_start('--adodb-GenID', null, SQL_QUERY_AUX);
- $nextval = $this->adodb->GenID($seqname);
- $this->query_end(true);
- if ($nextval) {
- $params['id'] = (int)$nextval;
- }
- }
- }
-
- if (empty($params)) {
- throw new coding_exception('moodle_database::insert_record_raw() no fields found.');
- }
-
- $fields = implode(',', array_keys($params));
- $qms = array_fill(0, count($params), '?');
- $qms = implode(',', $qms);
-
- $sql = "INSERT INTO {$this->prefix}$table ($fields) VALUES($qms)";
- $this->query_start($sql, $params, SQL_QUERY_INSERT);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- if (!$returnid) {
- return true;
- }
- if (!empty($params['id'])) {
- return (int)$params['id'];
- }
-
- $oid = $this->adodb->Insert_ID();
-
- // try to get the primary key based on id
- $sql = "SELECT id FROM {$this->prefix}$table WHERE oid = $oid";
- $this->query_start($sql, $params, SQL_QUERY_AUX);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- if ( $rs && ($rs->RecordCount() == 1) ) {
- trigger_error("Retrieved id using oid on table $table because we could not find the sequence.");
- return (integer)reset($rs->fields);
- }
- throw new dml_write_exception('unknown error fetching inserted id');
- }
-
- /**
- * Insert a record into a table and return the "id" field if required,
- * Some conversions and safety checks are carried out. Lobs are supported.
- * If the return ID isn't required, then this just reports success as true/false.
- * $data is an object containing needed data
- * @param string $table The database table to be inserted into
- * @param object $data A data object with values for one or more fields in the record
- * @param bool $returnid Should the id of the newly created record entry be returned? If this option is not requested then true/false is returned.
- * @param bool $bulk true means repeated inserts expected
- * @return true or new id
- * @throws dml_exception if error
- */
- public function insert_record($table, $dataobject, $returnid=true, $bulk=false) {
- //TODO: add support for blobs BYTEA
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
- unset($dataobject->id);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- $column = $columns[$field];
- if ($column->meta_type == 'B') {
- if (is_null($value)) {
- $cleaned[$field] = null;
- } else {
- $blobs[$field] = $value;
- $cleaned[$field] = '@#BLOB#@';
- }
- continue;
-
- } else if (is_bool($value)) {
- $value = (int)$value; // prevent false '' problems
-
- } else if ($value === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
-
- $cleaned[$field] = $value;
- }
-
- if (empty($blobs)) {
- return $this->insert_record_raw($table, $cleaned, $returnid, $bulk);
- }
-
- $id = $this->insert_record_raw($table, $cleaned, true, $bulk);
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id", 'BLOB');// adodb does not use bound parameters for blob updates :-(
- $this->query_end($result);
- }
-
- return ($returnid ? $id : true);
- }
-
- /**
- * Update a record in a table
- *
- * $dataobject is an object containing needed data
- * Relies on $dataobject having a variable "id" to
- * specify the record to update
- *
- * @param string $table The database table to be checked against.
- * @param object $dataobject An object with contents equal to fieldname=>fieldvalue. Must have an entry for 'id' to map to the table specified.
- * @param bool true means repeated updates expected
- * @return bool true
- * @throws dml_exception if error
- */
- public function update_record($table, $dataobject, $bulk=false) {
- //TODO: add support for blobs BYTEA
- if (!is_object($dataobject)) {
- $dataobject = (object)$dataobject;
- }
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- $column = $columns[$field];
- if ($column->meta_type == 'B') {
- if (is_null($value)) {
- $cleaned[$field] = null;
- } else {
- $blobs[$field] = $value;
- $cleaned[$field] = '@#BLOB#@';
- }
- continue;
-
- } else if (is_bool($value)) {
- $value = (int)$value; // prevent "false" problems
-
- } else if ($value === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $value = 0; // prevent '' problems in numeric fields
- }
- }
- $cleaned[$field] = $value;
- }
-
- $this->update_record_raw($table, $cleaned, $bulk);
-
- if (empty($blobs)) {
- return true;
- }
-
- $id = $dataobject->id;
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id", 'BLOB');// adodb does not use bound parameters for blob updates :-(
- $this->query_end($result);
- }
-
- return true;
- }
-
- /**
- * Set a single field in every table row where the select statement evaluates to true.
- *
- * @param string $table The database table to be checked against.
- * @param string $newfield the field to set.
- * @param string $newvalue the value to set the field to.
- * @param string $select A fragment of SQL to be used in a where clause in the SQL call.
- * @param array $params array of sql parameters
- * @return bool true
- * @throws dml_exception if error
- */
- public function set_field_select($table, $newfield, $newvalue, $select, array $params=null) {
- $params = (array)$params;
- list($select, $params, $type) = $this->fix_sql_params($select, $params);
-
- $columns = $this->get_columns($table);
- $column = $columns[$newfield];
-
- if ($column->meta_type == 'B') {
- /// update blobs and return
- $select = $this->emulate_bound_params($select, $params); // adodb does not use bound parameters for blob updates :-(
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $newfield, $newvalue, $select, 'BLOB');
- $this->query_end($result);
- return true;
- }
-
- if ($select) {
- $select = "WHERE $select";
- }
-
- /// normal field update
- if (is_null($newvalue)) {
- $newfield = "$newfield = NULL";
- } else {
- if (is_bool($newvalue)) {
- $newvalue = (int)$newvalue; // prevent "false" problems
- } else if ($newvalue === '') {
- if ($column->meta_type == 'I' or $column->meta_type == 'F' or $column->meta_type == 'N') {
- $newvalue = 0; // prevent '' problems in numeric fields
- }
- }
-
- $newfield = "$newfield = ?";
- array_unshift($params, $newvalue); // add as first param
- }
- $sql = "UPDATE {$this->prefix}$table SET $newfield $select";
- $this->query_start($sql, $params, SQL_QUERY_UPDATE);
- $rs = $this->adodb->Execute($sql, $params);
- $this->query_end($rs);
-
- return true;
- }
-
- public function sql_ilike() {
- return 'ILIKE';
- }
-
- public function sql_concat() {
- $args = func_get_args();
- /// PostgreSQL requires at least one char element in the concat, let's add it
- /// here (at the beginning of the array) until ADOdb fixes it
- if (is_array($args)) {
- array_unshift($args , "''");
- }
- return call_user_func_array(array($this->adodb, 'Concat'), $args);
- }
-
- public function sql_bitxor($int1, $int2) {
- return '(' . $this->sql_bitor($int1, $int2) . ' - ' . $this->sql_bitand($int1, $int2) . ')';
- }
-
- public function sql_cast_char2int($fieldname, $text=false) {
- return ' CAST(' . $fieldname . ' AS INT) ';
- }
-
- public function sql_cast_char2real($fieldname, $text=false) {
- return " $fieldname::real ";
- }
-
- /**
- * Does this driver suppoer regex syntax when searching
- */
- public function sql_regex_supported() {
- return true;
- }
-
- /**
- * Return regex positive or negative match sql
- * @param bool $positivematch
- * @return string or empty if not supported
- */
- public function sql_regex($positivematch=true) {
- return $positivematch ? '~*' : '!~*';
- }
-
- /**
- * Import a record into a table, id field is required.
- * Basic safety checks only. Lobs are supported.
- * @param string $table name of database table to be inserted into
- * @param mixed $dataobject object or array with fields in the record
- * @return bool true
- * @throws dml_exception if error
- */
- public function import_record($table, $dataobject) {
- $dataobject = (object)$dataobject;
-
- $columns = $this->get_columns($table);
- $cleaned = array();
- $blobs = array();
-
- foreach ($dataobject as $field=>$value) {
- if (!isset($columns[$field])) {
- continue;
- }
- $column = $columns[$field];
- if ($column->meta_type == 'B') {
- if (!is_null($value)) {
- $blobs[$field] = $value;
- $cleaned[$field] = '@#BLOB#@';
- continue;
- }
- }
- $cleaned[$field] = $value;
- }
-
- $this->insert_record_raw($table, $cleaned, false, true, true);
-
- if (empty($blobs)) {
- return true;
- }
-
- /// We have BLOBs to postprocess
-
- foreach ($blobs as $key=>$value) {
- $this->query_start('--adodb-UpdateBlob', null, SQL_QUERY_UPDATE);
- $result = $this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id", 'BLOB');
- $this->query_end($result);
- }
-
- return true;
- }
-}