- Introducing the first version of the new mssql_n adodb driver (not finished, just for experimenting).

- Now insert_record() is handling Oracle CLOBS and BLOBS properly (really annoying the number of hacks needed).
- Creating one new global object to cache $db->MetaColumns() calls per request, because it's being used
in a lot of places inside dmllib.
TODO: hack update_record() and set_field() to allow Oracle LOBs
      enclose all the Oracle function calls into one db transaction
This commit is contained in:
stronk7
2006-10-15 16:38:22 +00:00
parent ed0dd58cf2
commit 6880e3bb16
+108 -9
View File
@@ -38,6 +38,7 @@
/// GLOBAL CONSTANTS /////////////////////////////////////////////////////////
$empty_rs_cache = array(); // Keeps copies of the recordsets used in one invocation
$metadata_cache = array(); // Keeps copies of the MetaColumns() for each table used in one invocations
/// FUNCTIONS FOR DATABASE HANDLING ////////////////////////////////
@@ -1132,7 +1133,7 @@ function insert_record($table, $dataobject, $returnid=true, $primarykey='id') {
if ($CFG->dbtype == 'oci8po' && !empty($dataobject->{$primarykey})) {
$foundclobs = array();
$foundblobs = array();
///TODO
oracle_detect_lobs($table, $dataobject, $foundclobs, $foundblobs);
}
/// Get the correct SQL from adoDB
@@ -1144,7 +1145,8 @@ function insert_record($table, $dataobject, $returnid=true, $primarykey='id') {
/// if we know we have some of them in the query
if ($CFG->dbtype == 'oci8po' && !empty($dataobject->{$primarykey}) &&
(!empty($foundclobs) || !empty($foundblobs))) {
///TODO
$insertSQL = str_replace("'@#CLOB#@'", 'empty_clob()', $insertSQL);
$insertSQL =str_replace("'@#BLOB#@'", 'empty_blob()', $insertSQL);
}
/// Run the SQL statement
@@ -1161,7 +1163,7 @@ function insert_record($table, $dataobject, $returnid=true, $primarykey='id') {
/// if we know we have some of them in the query
if ($CFG->dbtype == 'oci8po' && !empty($dataobject->{$primarykey}) &&
(!empty($foundclobs) || !empty($foundblobs))) {
//TODO
oracle_update_lobs($table, $dataobject->{$primarykey}, $foundclobs, $foundblobs);
}
/// If a return ID is not needed then just return true now
@@ -1424,6 +1426,7 @@ function sql_order_by_text($fieldname, $numchars=32) {
switch ($CFG->dbtype) {
case 'mssql':
case 'mssql_n':
case 'odbc_mssql':
return 'CONVERT(varchar, ' . $fieldname . ', ' . $numchars . ')';
break;
@@ -1575,6 +1578,7 @@ function configure_dbconnection() {
}
break;
case 'mssql':
case 'mssql_n':
case 'odbc_mssql':
/// No need to set charset. It must be specified in the driver conf
/// Allow quoted identifiers
@@ -1586,6 +1590,7 @@ function configure_dbconnection() {
ini_set('magic_quotes_sybase', '1');
/// NOTE: Not 100% useful because GPC has been addslashed with the setting off
/// so IT'S MANDATORY TO CHANGE THIS UNDER php.ini or .htaccess for this DB
/// or to turn off magic_quotes to allow Moodle to do it properly
break;
case 'oci8po':
/// No need to set charset. It must be specified by the NLS_LANG env. variable
@@ -1593,6 +1598,7 @@ function configure_dbconnection() {
ini_set('magic_quotes_sybase', '1');
/// NOTE: Not 100% useful because GPC has been addslashed with the setting off
/// so IT'S MANDATORY TO ENABLE THIS UNDER php.ini or .htaccess for this DB
/// or to turn off magic_quotes to allow Moodle to do it properly
break;
}
}
@@ -1607,6 +1613,8 @@ function configure_dbconnection() {
* 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 dmllib at all
*
* @param $table string the table where the record is going to be inserted/updated (without prefix)
* @param $dataobject object the object to be inserted/updated
* @param $usecache boolean flag to determinate if we must use the per request cache of metadata
@@ -1614,11 +1622,11 @@ function configure_dbconnection() {
*/
function oracle_dirty_hack ($table, &$dataobject, $usecache = true) {
global $CFG, $db;
global $CFG, $db, $metadata_cache;
/// Init and delete metadata cache
if (!isset($metadatacache) || !$usecache) {
static $metadatacache = array();
if (!isset($metadata_cache) || !$usecache) {
$metadata_cache = array();
}
/// For Oracle DB, empty strings are converted to NULLs in DB
@@ -1638,10 +1646,10 @@ function oracle_dirty_hack ($table, &$dataobject, $usecache = true) {
}
/// Get Meta info to know what to change, using the cached meta if exists
if (!isset($metadatacache[$table])) {
$metadatacache[$table] = array_change_key_case($db->MetaColumns($CFG->prefix . $table), CASE_LOWER);
if (!isset($metadata_cache[$table])) {
$metadata_cache[$table] = array_change_key_case($db->MetaColumns($CFG->prefix . $table), CASE_LOWER);
}
$columns = $metadatacache[$table];
$columns = $metadata_cache[$table];
/// Iterate over all the fields in the insert, transforming values
/// in the best possible form
foreach ($dataobject as $fieldname => $fieldvalue) {
@@ -1677,4 +1685,95 @@ function oracle_dirty_hack ($table, &$dataobject, $usecache = true) {
}
/// End of DIRTY HACK
/**
* This function will search for all the CLOBs and BLOBs fields passed in the dataobject, replacing
* their contents by the fixed strings '@#CLOB#@' and '@#BLOB' and returning one array for all the
* found CLOBS and another for all the found BLOBS
* Used by Oracle drivers to perform the two-step insertion/update of LOBs
*
* This function is private and must not be used outside dmllib at all
*
* @param $table string the table where the record is going to be inserted/updated (without prefix)
* @param $dataobject object the object to be inserted/updated
* @param $clobs array of clobs detected
* @param $dataobject array of blobs detected
* @param $usecache boolean flag to determinate if we must use the per request cache of metadata
* true to use it, false to ignore and delete it
*/
function oracle_detect_lobs ($table, &$dataobject, &$clobs, &$blobs,$usecache = true) {
global $CFG, $db, $metadata_cache;
/// Init and delete metadata cache
if (!isset($metadata_cache) || !$usecache) {
$metadata_cache = array();
}
/// If the db isn't Oracle, return without modif
if ( $CFG->dbtype != 'oci8po') {
return;
}
/// Get Meta info to know what to change, using the cached meta if exists
if (!isset($metadata_cache[$table])) {
$metadata_cache[$table] = array_change_key_case($db->MetaColumns($CFG->prefix . $table), CASE_LOWER);
}
$columns = $metadata_cache[$table];
foreach ($dataobject as $fieldname => $fieldvalue) {
/// If the field doesn't exist in metadata, skip
if (!isset($columns[strtolower($fieldname)])) {
continue;
}
/// If the field is CLOB, update its value to '@#CLOB#@' and store it in the $clobs array
if ($columns[strtolower($fieldname)]->type == 'CLOB') {
$clobs[$fieldname] = $dataobject->$fieldname;
$dataobject->$fieldname = '@#CLOB#@';
continue;
}
/// If the field is BLOB, update its value to '@#BLOB#@' and store it in the $blobs array
if ($columns[strtolower($fieldname)]->type == 'BLOB') {
$clobs[$fieldname] = $dataobject->$fieldname;
$dataobject->$fieldname = '@#BLOB#@';
continue;
}
}
}
/**
* This function will iterate over $clobs and $blobs array, executing the needed
* UpdateClob() and UpdateBlob() ADOdb function calls to store LOBs contents properly
* Records to be updated are always searched by PK (id always!)
*
* This function is private and must not be used outside dmllib at all
*
* @param $table string the table where the record is going to be inserted/updated (without prefix)
* @param $primaryvalue integer value of the primary key (to identify the record to be updated)
* @param $clobs array of clobs to be updated
* @param $dataobject array of blobs to be updated
*/
function oracle_update_lobs ($table, $primaryvalue, &$clobs, &$blobs) {
global $CFG, $db;
/// If the db isn't Oracle, return without modif
if ( $CFG->dbtype != 'oci8po') {
return;
}
/// Update all the clobs
if ($clobs) {
foreach ($clobs as $key => $value) {
$db->UpdateClob($CFG->prefix.$table, $key, $value, 'id='.$primaryvalue);
}
}
/// Update all the blobs
if ($blobs) {
foreach ($blobs as $key => $value) {
$db->UpdateBlob($CFG->prefix.$table, $key, $value, 'id='.$primaryvalue);
}
}
}
?>