diff --git a/lib/dml/adodb_moodle_database.php b/lib/dml/adodb_moodle_database.php index b0b5de02039..e07e9336760 100644 --- a/lib/dml/adodb_moodle_database.php +++ b/lib/dml/adodb_moodle_database.php @@ -238,13 +238,22 @@ abstract class adodb_moodle_database extends moodle_database { * @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 success or new id */ - public function insert_record_raw($table, $params, $returnid=true, $bulk=false) { + public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) { if (!is_array($params)) { $params = (array)$params; } - unset($params['id']); + + if ($customsequence) { + if (!isset($params['id'])) { + return false; + } + $returnid = false; + } else { + unset($params['id']); + } if (empty($params)) { return false; diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 605b939796a..b37ef39361f 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -984,9 +984,10 @@ abstract class moodle_database { * @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 success or new id */ - public abstract function insert_record_raw($table, $params, $returnid=true, $bulk=false); + public abstract function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false); /** * Insert a record into a table and return the "id" field if required. @@ -1001,6 +1002,16 @@ abstract class moodle_database { */ public abstract function insert_record($table, $dataobject, $returnid=true, $bulk=false); + /** + * Import a record into a table, id field is required. + * Safety checks are NOT carried out. Lobs are supported. + * + * @param string $table name of database table to be inserted into + * @param object $dataobject A data object with values for one or more fields in the record + * @return bool success + */ + public abstract function import_record($table, $dataobject); + /** * Update record in database, as fast as possible, no safety checks, lobs not supported. * @param string $table name diff --git a/lib/dml/mssql_adodb_moodle_database.php b/lib/dml/mssql_adodb_moodle_database.php index f3500446420..c9350e1450d 100644 --- a/lib/dml/mssql_adodb_moodle_database.php +++ b/lib/dml/mssql_adodb_moodle_database.php @@ -365,4 +365,58 @@ class mssql_adodb_moodle_database extends adodb_moodle_database { } return $this->change_database_structure("DBCC CHECKIDENT ('$this->prefix$table', RESEED, $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(); + + 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; + } + + if (!$this->insert_record_raw($table, $cleaned, false, true, true)) { + return false; + } + + if (empty($blobs)) { + return true; + } + + /// We have BLOBs to postprocess + + foreach ($blobs as $key=>$value) { + $this->writes++; + if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id")) { + return false; + } + } + + return true; + } } diff --git a/lib/dml/mysqli_adodb_moodle_database.php b/lib/dml/mysqli_adodb_moodle_database.php index a3f2cb2ca9d..a231208b7d1 100644 --- a/lib/dml/mysqli_adodb_moodle_database.php +++ b/lib/dml/mysqli_adodb_moodle_database.php @@ -289,4 +289,31 @@ class mysqli_adodb_moodle_database extends adodb_moodle_database { $value++; return $this->change_database_structure("ALTER TABLE $this->prefix$table AUTO_INCREMENT = $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; + + if (empty($dataobject->id)) { + return false; + } + + $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); + } } \ No newline at end of file diff --git a/lib/dml/oci8po_adodb_moodle_database.php b/lib/dml/oci8po_adodb_moodle_database.php index 1b754713be1..3d02f662d8c 100644 --- a/lib/dml/oci8po_adodb_moodle_database.php +++ b/lib/dml/oci8po_adodb_moodle_database.php @@ -450,13 +450,22 @@ class oci8po_adodb_moodle_database extends adodb_moodle_database { * @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 success or new id */ - public function insert_record_raw($table, $params, $returnid=true, $bulk=false) { + public function insert_record_raw($table, $params, $returnid=true, $bulk=false, $customsequence=false) { if (!is_array($params)) { $params = (array)$params; } - unset($params['id']); + + if ($customsequence) { + if (!isset($params['id'])) { + return false; + } + $returnid = false; + } else { + unset($params['id']); + } if ($returnid) { $dbman = $this->get_manager(); @@ -631,4 +640,71 @@ class oci8po_adodb_moodle_database extends adodb_moodle_database { $this->change_database_structure("DROP SEQUENCE $seqname"); return $this->change_database_structure("CREATE SEQUENCE $seqname START WITH $value INCREMENT BY 1 NOMAXVALUE"); } + + /** + * 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; + } + + if (!$this->insert_record_raw($table, $cleaned, false, true, true)) { + return false; + } + + if (empty($blobs) and empty($clobs)) { + return true; + } + + /// We have BLOBs or CLOBs to postprocess + + foreach ($blobs as $key=>$value) { + $this->writes++; + if (!$this->adodb->UpdateBlob($this->prefix.$table, $key, $value, "id = $id")) { + return false; + } + } + + foreach ($clobs as $key=>$value) { + $this->writes++; + if (!$this->adodb->UpdateClob($this->prefix.$table, $key, $value, "id = $id")) { + return false; + } + } + + return true; + } } diff --git a/lib/dml/pdo_moodle_database.php b/lib/dml/pdo_moodle_database.php index fbc8369fe70..7e150ee69ee 100644 --- a/lib/dml/pdo_moodle_database.php +++ b/lib/dml/pdo_moodle_database.php @@ -57,7 +57,7 @@ abstract class pdo_moodle_database extends moodle_database { protected function get_dsn() { return 'mysql:host='.$this->dbhost.';dbname='.$this->dbname; } - + /** * Returns the driver-dependent connection attributes for PDO based on members stored by connect. * Must be called after $dbname, $dbhost, etc. members have been set. @@ -66,7 +66,7 @@ abstract class pdo_moodle_database extends moodle_database { protected function get_pdooptions() { return array(PDO::ATTR_PERSISTENT => $this->dbpersist); } - + protected function configure_dbconnection() { ///TODO: not needed preconfigure_dbconnection() stuff for PDO drivers? } @@ -86,7 +86,7 @@ abstract class pdo_moodle_database extends moodle_database { * @return string */ public function get_name() { - return get_string($this->get_dbtype() . '_pdo', 'install'); + return get_string($this->get_dbtype() . '_pdo', 'install'); } /** @@ -112,7 +112,7 @@ abstract class pdo_moodle_database extends moodle_database { } catch(PDOException $ex) {} return $result; } - + /** * Returns supported query parameter types * @return bitmask @@ -120,7 +120,7 @@ abstract class pdo_moodle_database extends moodle_database { protected function allowed_param_types() { return SQL_PARAMS_QM | SQL_PARAMS_NAMED; } - + /** * Returns last error reported by database engine. */ @@ -170,7 +170,7 @@ abstract class pdo_moodle_database extends moodle_database { } echo '