We were unable to use the Oracle database because the Oracle extension for PHP is not installed. Check your PHP.ini to see how you can enable it.
');
//create a book page about Oracle support.
exit;
}
$url = parse_url($url);
//print_r($url);
//die();
// Decode url-encoded information in the db connection string
$url['user'] = urldecode($url['user']);
$url['pass'] = urldecode($url['pass']);
$url['host'] = urldecode($url['host']);
$url['path'] = urldecode($url['path']);
// Allow for non-standard Oracle port.
if (isset($url['port'])) {
$url['host'] = $url['host'] .':'. $url['port'];
}
$string_db = '//'.$url['host'].'/'.substr($url['path'], 1);
//TODO: investigate for the use of charset parameter.
//TODO: Currently, this requires that the $url['path'] value be
// set in the TNSNAMES.ora file on the local system. Investigate
// how to specify server, port and DB Instance.
/*
Re: TODO above, using a connection string like this might work
$db="(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS =
(COMMUNITY = xxx)
(PROTOCOL = TCP)
(Host = xxx)
(Port = xxx)
)
)
(CONNECT_DATA = (SID = xxx)
)
)";
*/
$connection = @oci_connect($url['user'], $url['pass'], substr($url['path'], 1));
if (!$connection) {
drupal_maintenance_theme();
drupal_set_title('Unable to connect to database server');
$error = ocierror();
print theme('maintenance_page', 'This either means that the username and password information in your settings.php file is incorrect or we can\'t contact the Oracle database server. This could mean your hosting provider\'s database server is down.
The Oracle error was: '. theme('placeholder', $error['message']) .'.
Currently, the username is '. theme('placeholder', $url['user']) .' and the database server is '. theme('placeholder', $url['host']) .'.
- Are you sure you have the correct username and password?
- Are you sure that you have typed the correct hostname?
- Are you sure that the database server is running?
For more help, see the Installation and upgrading handbook. If you are unsure what these terms mean you should probably contact your hosting provider.
');
exit;
}
return $connection;
}
/**
* Sanitize query adding "" around Oracle SQL reserved column names.
*/
function _db_reserved_words($part) {
$part = " " . $part . " "; //hack to get around the fact that the column name might be at the front or at the end of the string
$db_reserved_words = array ('access', 'comment', 'mode', 'session', 'uid');
foreach ($db_reserved_words as $word) {
$part = eregi_replace('([[:space:],\.\(<>\+-=!*])'.$word.'([[:space:],\.\)<>\+-=!*])','\\1"'.$word.'"\\2', $part);
}
return substr($part,1,-1);
}
/**
* Helper function for db_query().
*/
function _db_query($query, $debug = 0) {
global $counterS;
$counterS++;
global $active_db, $last_result, $_query_rc_result, $queries;
if (variable_get('dev_query', 0)) {
list($usec, $sec) = explode(' ', microtime());
$timer = (float)$usec + (float)$sec;
}
if (!isset($_query_rc_result)) {
$_query_rc_result = array();
}
//Rewrite all INSERT/UPDATE statements to check and handle LOBs since Oracle
// cannot handle them as just strings of text delimited by single quote
// marks (') once they go over 4000 charecters (common in Drupal).
if (eregi('^(INSERT INTO )', $query)) {
//Rewrite INSERT INTO statement
//$query = "INSERT INTO boxes (title, body, info, format) VALUES ('', '', 'a', 1)";
//echo "
------------------------------------
Step $counterS
";
//echo $query . "
";
/*
* Split statement into three groups - the table name, the field list
* (if provided) and "VALUES" and the value list. Then, further split
* the column list and value list into arrays.
*/
//$re = "/^insert into ([a-z0-9_\"]+)(?:\s*\((.*)\))? values \((.*)\)$/Dsi";
$re = "/^insert into ([a-z0-9_\"]+)(?:\s*\((.*)\))? values\s+\((.*)\)$/Dsi";
preg_match($re, $query, $parts);
//print_r($parts); echo "
";
// die();
$tablename = _db_reserved_words($parts[1]);
$col_list = _db_reserved_words($parts[2]);
$val_list = $parts[3];
$col_arr = explode(",",$col_list); //the column list is strictly delimited by ","
//However, the value list is not strictly delimited by ",", use a regex to break it up
$re="/,(?=(?:[^']*'[^']*')*(?![^']*'))/";
$results=preg_split($re, trim($val_list));
$val_arr = preg_replace("/^\"(.*)\"$/","$1", $results);
/*
* Determine whether or not each column is a LOB (CLOB or BLOB) and
* substitute a bind variable. If the column list is not provided,
* we'll need to obtain it from the DB.
*/
//TODO: Augment this query with some sort of caching system, so it knows
// which columns are LOBs without having to ask the DB every time.
$col_query = "select column_name, data_type, column_id
from USER_TAB_COLUMNS
where table_name = '" . strtoupper($tablename) . "'
order by column_id";
$col_result = ociparse($active_db, $col_query);
OCIExecute($col_result , OCI_DEFAULT);
ocifetchstatement($col_result, $ora_cols, 0, -1, OCI_ASSOC);
// Check + Build $col_arr
if (! is_array($col_arr)) {
//populate $col_list
$col_arr = $ora_cols['COLUMN_NAME'];
for($i=0; $i < count($col_arr);$i++) {
// If column name is in lower case, it needs to have "" around it since its a reserved word
if ($col_arr[$i] == strtolower($col_arr[$i])){
$col_arr[$i] = "\"" . $col_arr[$i] . "\"";
}
}
array_change_key_case($col_arr, CASE_LOWER);
}
//Clean $col_arr and $val_arr
foreach ($col_arr as $key => $value) {
$col_arr[$key] = trim($value);
}
foreach ($val_arr as $key => $value) {
$val_arr[$key] = trim($value);
}
// $lob_cols[n] => [0] Column Name, [1] Value to be stored
$lob_cols = array();
// Check for CLOB/BLOB
for($i=0; $i < count($col_arr);$i++) {
$query_col = trim(str_replace("\"", "", strtolower($col_arr[$i])));
for($j=0; $j < count($ora_cols['COLUMN_NAME']);$j++) {
$ora_col = trim(strtolower($ora_cols['COLUMN_NAME'][$j]));
if ($query_col == $ora_col) {
if ($ora_cols['DATA_TYPE'][$j] == "CLOB" || $ora_cols['DATA_TYPE'][$j] == "BLOB") {
// Replace that value with a bind variable if the data is not ''
if ($val_arr[$i] != "''") {
$lob_cols[] = array($col_arr[$i], $val_arr[$i]);
}
$val_arr[$i] = "EMPTY_" . $ora_cols['DATA_TYPE'][$j] . "()";
}
break;
}
}
}
//Rebuild Query
$newquery = "INSERT INTO " . $tablename . " (" . implode(",", $col_arr) . ") ";
$newquery .= "VALUES (" . implode(",", $val_arr) . ")";
//Build RETURNING string
if (count($lob_cols) > 0) {
$lobcollist = null;
$bindvarlist = null;
for($i=0;$i < count($lob_cols);$i++) {
$lobcollist .= "," . $lob_cols[$i][0];
$bindvarlist .= "," . ":" . $lob_cols[$i][0];
}
$lobcollist = substr($lobcollist,1);
$bindvarlist = substr($bindvarlist,1);
$newquery .= " RETURNING " . $lobcollist . " INTO " . $bindvarlist;
}
//echo $newquery . "
";
$result = OCIParse($active_db, $newquery);
$clobs = array();
//Create bind variables
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = ocinewdescriptor($active_db, OCI_D_LOB);
ocibindbyname($result, ':' . $lob_cols[$i][0], $clob, -1, OCI_B_CLOB);
$clobs[] = $clob;
}
}
OCIExecute($result, OCI_DEFAULT) or die($newquery);
//Bind CLOB data
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = $clobs[$i];
$data = $lob_cols[$i][1];
//Strip ' from the beginning and end of the string (since they'll be
// interpreted literally and not as string encapsulators)
if (substr($data,0,1) == "'" && substr($data,-1,1) == "'") {
$data = substr($data,1,-1);
}
// In order to update the table, a row must have been found in the where clause!
if (ocirowcount($result) > 0) {
$clob->save($data);
}
}
}
OCICommit($active_db);
//Free CLOBs
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = $clobs[$i];
$clob->free();
}
}
//print $query.'
';
}
else if (eregi('^(UPDATE )', $query)) {
//Rewrite UPDATE statement
/*
* Split statement into three groups - the table name, the field and
* value list, and the WHERE clause (if provided). Then, further split
* the column list and value list into arrays.
*/
$re = "/update\\s*([a-z0-9_\"]+)\\s*set\\s*(.*)\\s*where\\s*(.*)/si";
preg_match($re, $query, $parts);
$tablename = _db_reserved_words($parts[1]);
$item_list = $parts[2];
$whereclause = _db_reserved_words($parts[3]);
$re="/,(?=(?:[^']*'[^']*')*(?![^']*'))/";
$results=preg_split($re, trim($item_list));
$item_arr = preg_replace("/^\"(.*)\"$/","$1", $results);
//Split item array into column and value arrays
$col_arr = array();
$val_arr = array();
for($i=0; $i < count($item_arr);$i++) {
$pos = strpos($item_arr[$i], "=");
$col_arr[] = trim(substr($item_arr[$i],0,$pos-1));
$val_arr[] = trim(substr($item_arr[$i],$pos+1));
}
$col_arr = explode(",",_db_reserved_words(implode(",", $col_arr)));
/*
* Determine whether or not each column is a LOB (CLOB or BLOB) and
* substitute a bind variable. If the column list is not provided,
* we'll need to obtain it from the DB.
*/
//TODO: Augment this query with some sort of caching system, so it knows
// which columns are LOBs without having to ask the DB every time.
$col_query = "select column_name, data_type, column_id
from USER_TAB_COLUMNS
where table_name = '" . strtoupper($tablename) . "'
order by column_id";
$col_result = OCIParse($active_db, $col_query);
OCIExecute($col_result , OCI_DEFAULT);
ocifetchstatement($col_result, $ora_cols, 0, -1, OCI_ASSOC);
// Check + Build $col_arr
if (! is_array($col_arr)) {
//populate $col_list
$col_arr = $ora_cols['COLUMN_NAME'];
for($i=0; $i < count($col_arr);$i++) {
// If column name is in lower case, it needs to have "" around it since its a reserved word
if ($col_arr[$i] == strtolower($col_arr[$i])){
$col_arr[$i] = "\"" . $col_arr[$i] . "\"";
}
}
array_change_key_case($col_arr, CASE_LOWER);
}
//Clean $col_arr and $val_arr
foreach ($col_arr as $key => $value) {
$col_arr[$key] = trim($value);
}
foreach ($val_arr as $key => $value) {
$val_arr[$key] = trim($value);
}
//array of arrays, the items below are defined as...
// $lob_cols[n] => [0] Column Name, [1] Value to be stored
$lob_cols = array();
// Check for CLOB/BLOB
for($i=0; $i < count($col_arr);$i++) {
$query_col = trim(str_replace("\"", "", strtolower($col_arr[$i])));
for($j=0; $j < count($ora_cols['COLUMN_NAME']);$j++) {
$ora_col = trim(strtolower($ora_cols['COLUMN_NAME'][$j]));
if ($query_col == $ora_col) {
if ($ora_cols['DATA_TYPE'][$j] == "CLOB" || $ora_cols['DATA_TYPE'][$j] == "BLOB") {
// Replace that value with a bind variable if the data is not ''
if ($val_arr[$i] != "''") {
$lob_cols[] = array($col_arr[$i], $val_arr[$i]);
}
$val_arr[$i] = "EMPTY_" . $ora_cols['DATA_TYPE'][$j] . "()";
}
break;
}
}
}
//Rebuild Query
$newquery = "UPDATE " . $tablename . " SET ";
for($i=0; $i < count($col_arr); $i++) {
$newquery .= $col_arr[$i] . " = " . $val_arr[$i];
if ($i < (count($col_arr)-1)) $newquery .= ", ";
}
if ($whereclause != "") {
$newquery .= " where " . $whereclause;
}
//Build RETURNING string
if (count($lob_cols) > 0) {
$lobcollist = null;
$bindvarlist = null;
for($i=0;$i < count($lob_cols);$i++) {
$lobcollist .= "," . $lob_cols[$i][0];
$bindvarlist .= "," . ":" . $lob_cols[$i][0];
}
$lobcollist = substr($lobcollist,1);
$bindvarlist = substr($bindvarlist,1);
$newquery .= " RETURNING " . $lobcollist . " INTO " . $bindvarlist;
}
//echo $newquery . "
";
$result = OCIParse($active_db, $newquery);
$clobs = array();
//Create bind variables
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = ocinewdescriptor($active_db, OCI_D_LOB);
ocibindbyname($result, ':' . $lob_cols[$i][0], $clob, -1, OCI_B_CLOB);
$clobs[] = $clob;
}
}
OCIExecute($result, OCI_DEFAULT) or die($newquery);
//Bind CLOB data
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = $clobs[$i];
$data = $lob_cols[$i][1];
//Strip ' from the beginning and end of the string (since they'll be
// interpreted literally and not as string encapsulators)
if (substr($data,0,1) == "'" && substr($data,-1,1) == "'") {
$data = substr($data,1,-1);
}
// In order to update the table, a row must have been found in the where clause!
if (ocirowcount($result) > 0) {
$clob->save($data);
}
}
}
OCICommit($active_db);
//Free CLOBs
if (count($lob_cols) > 0) {
for($i=0;$i < count($lob_cols);$i++) {
$clob = $clobs[$i];
$clob->free();
}
}
}
else if (ereg('^(SELECT DISTINCT)', $query)) {
// Oracle cannot SELECT DISTINCT(clob_field) ...
//echo $query . "
";
$query = str_replace("DISTINCT", "", $query);
$query = _db_reserved_words($query);
$result = OCIParse($active_db, $query);
OCIExecute($result, OCI_DEFAULT) or die($query);
//Re-execute query for when the app requests a rowcount (so it wont disturb the cursor of the real result set)
$result_rc = OCIParse($active_db, $query);
OCIExecute($result_rc, OCI_DEFAULT) or die($query);
$_query_rc_result[$result] = $result_rc;
}
else if (ereg('^(LOCK TABLE)', $query)) {
//Lock Table has a keyword thats in the reserved word list, we don't want it in ""s
//echo $query . "
";
$re = "/^(lock table\s+)([a-z0-9]+)(\\s+.*)$/si";
preg_match($re, $query, $parts);
$parts[2] = _db_reserved_words($parts[2]);
array_shift($parts); //shift off the entire string
$query = implode("",$parts);
$result = OCIParse($active_db, $query);
OCIExecute($result, OCI_DEFAULT);
}
else if (ereg('^(SELECT)', $query)) {
//Limit double query for row count to SELECT statements
//echo $query . "
";
//$query = _db_reserved_words($query);
// Parsing SELECT query, because we need to manage CLOB and BLOBs in WHERE clause
// This is only for simple queries
// TODO: think of better $re to handle complex queries (JOINS)
if (strpos($query, 'JOIN') || strpos($query, 'ORDER') || strpos($query, 'GROUP') || strpos($query, 'LIKE') || !strpos($query, 'WHERE')) {
$query = _db_reserved_words($query);
$result = OCIParse($active_db, $query);
OCIExecute($result, OCI_DEFAULT);
//Re-execute query for when the app requests a rowcount (so it wont disturb the cursor of the real result set)
$result_rc = OCIParse($active_db, $query);
OCIExecute($result_rc, OCI_DEFAULT);
$_query_rc_result[$result] = $result_rc;
}
else {
$re = "/from\s*(\w+)/si";
//$re = "/select\\s*(.*)\\s*from\\s*(.*)\\s*where\\s*(.*)/si";
preg_match($re, $query, $tmpArr);
$tablename = trim($tmpArr[1]);
//echo $query . "
";
//echo $tablename . "
";
/*
* Determine whether or not each column is a LOB (CLOB or BLOB) and
* substitute a bind variable. If the column list is not provided,
* we'll need to obtain it from the DB.
*/
//TODO: Augment this query with some sort of caching system, so it knows
// which columns are LOBs without having to ask the DB every time.
$col_query = "select column_name, data_type, column_id
from USER_TAB_COLUMNS
where table_name = '" . strtoupper($tablename) . "'
order by column_id";
$col_result = oci_parse($active_db, $col_query);
oci_execute($col_result , OCI_DEFAULT);
oci_fetch_all($col_result, $ora_cols, 0, -1, OCI_ASSOC);
for ($i=0; $i 0 ", $sql);
}
$newSQL = str_replace(chr(0), "\'", $sql);
$newSQL = _db_reserved_words($newSQL);
}
$result = OCIParse($active_db, $newSQL) or die($newSQL);
OCIExecute($result, OCI_DEFAULT) or die($newSQL);
//Re-execute query for when the app requests a rowcount (so it wont disturb the cursor of the real result set)
$result_rc = OCIParse($active_db, $newSQL);
OCIExecute($result_rc, OCI_DEFAULT);
$_query_rc_result[$result] = $result_rc;
}
//echo $query . "
";
}
else {
//echo $query . "
";
$query = _db_reserved_words($query);
$result = OCIParse($active_db, $query);
OCIExecute($result, OCI_DEFAULT) or die($query);
}
$last_result = $result;
$error = ocierror($result);
if (variable_get('dev_query', 0)) {
$bt = debug_backtrace();
$query = $bt[2]['function'] . "\n" . $query;
list($usec, $sec) = explode(' ', microtime());
$stop = (float)$usec + (float)$sec;
$diff = $stop - $timer;
$queries[] = array($query, $diff);
}
if ($debug) {
print 'query: '. $query .'
error:'. $error['message'] .'
';
}
if ($last_result !== FALSE) {
return $result;
}
else {
trigger_error(check_plain($error['message']."\nquery: ". $error['sqltext']), E_USER_WARNING);
return FALSE;
}
}
/*
// For debugging purposes only
function userErrorHandler($errno, $errmsg, $filename, $linenum, $vars)
{
echo "";
echo "ERR: ";
echo $errmsg . " | ";
echo $filename . " | ";
echo $errmsg . " | ";
echo $linenum . " | ";
print_r($vars);
echo "
";
}
*/
/**
* Fetch one result row from the previous query as an object.
*
* @param $result
* A database query result resource, as returned from db_query().
* @return
* An object representing the next row of the result. The attributes of this
* object are the table fields selected by the query.
*
* NOTE: - Oracle returns table fields in uppercase, so we convert them into lowercase.
* - Oracle will return the " marks around reserved column names - remove then or
* it will break other items down the line.
* - Oracle Clob are Objects, so we read their value.
* - To maintain compatibility with PHP4 as well as PHP5, OCI_FETCH_OBJECT is
* not used (it does not exist in PHP4), instead OCIFETCHINTO is used.
*/
function db_fetch_object($result, $debug = 0) {
if ($result) {
$new_obj = null;
//ocifetchinto($result, $arr, OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); // To return LOBs as strings of text automatically
ocifetchinto($result, $arr, OCI_ASSOC+OCI_RETURN_NULLS);
if ($myerr = ocierror($result)) print_r($myerr);
/*if ($debug) {
print_r($arr);
}*/
if (is_array($arr)) {
foreach ($arr as $key => $value) {
//if ($debug) print 'key:'.$key.'-value:'.$value.'
';
$lower_key = str_replace("\"","",strtolower($key));
//Return LOB value.
if (is_object($value)) {
//TODO: use OCI-Lob->load instead ?
$new_obj->$lower_key = $value->load();
/*if ($debug) {
print 'name:'.$lower_key.'-value:'.$value->read($value->size()).'
';
}*/
}
else {
$new_obj->$lower_key = $value;
///if ($debug) print 'key:'.$lower_key.'-value:'.$value.'
';
}
}
}
/*if ($debug) {
print_r($new_obj);
}*/
return $new_obj;
}
}
/**
* Fetch one result row from the previous query as an array.
*
* @param $result
* A database query result resource, as returned from db_query().
* @return
* An associative array representing the next row of the result. The keys of
* this object are the names of the table fields selected by the query, and
* the values are the field values for this result row.
*
* NOTE: - Oracle returns table fields in uppercase, so we convert them into lowercase.
*/
function db_fetch_array($result) {
if ($result) {
ocifetchinto($result, $array_result, OCI_ASSOC + OCI_RETURN_NULLS + OCI_RETURN_LOBS);
if (is_array($array_result)) {
return array_change_key_case($array_result, CASE_LOWER);
}
else {
return FALSE;
}
}
}
/**
* Determine how many result rows were found by the preceding query.
*
* @param $result
* A database query result resource, as returned from db_query().
* @return
* The number of result rows.
*
* NOTE: ocirowcount doesn't return the number of lines selected in a SELECT query. It
* cannot be used here. Further, there is no way to implement this function cleanly
* with an Oracle DB. Oracle stores its query results on the server side, therefore
* the client does not have to download the entire result set when the query is
* executed. However, since the client can not see the entire result set, it cant
* (from within the client only) determine how many rows were selected.
*
* Unfortunately, the cleanest possible way I could figure out was to have two
* result resources for SELECT statements, one for retrieving data and the other
* for counting rows. The alternate resource is set above in _db_query.
*/
function db_num_rows($result) {
global $_query_rc_result;
$result_rc = $_query_rc_result[$result];
if ($result_rc) {
// Reset result cursor and count
ociexecute($result_rc, OCI_COMMIT_ON_SUCCESS);
ocifetchstatement($result_rc,$rows, 0, 1, OCI_FETCHSTATEMENT_BY_ROW);
$num_rows = count($rows);
return $num_rows;
}
else {
//Just test $result with OCIROWCOUNT (this is appropriate for INSERT/UPDATE/DELETE statements)
return ocirowcount($result);
}
}
/**
* Return an individual result field from the previous query.
*
* Only use this function if exactly one field is being selected; otherwise,
* use db_fetch_object() or db_fetch_array().
*
* @param $result
* A database query result resource, as returned from db_query().
* @param $row
* The index of the row whose result is needed.
* @return
* The resulting field.
*/
function db_result($result, $row = 0) {
//First we have to fetch the first row then we return the first column.
//TODO: validate the number of rows ? This would generate problems for
// db_next_id query as we need to run query one time to get the number
// of rows, and then run it a second time to get the result, so we will
// "jumped" some id.
ocifetch($result);
return ociresult($result, 1);
//}
}
/**
* Determine whether the previous query caused an error.
*/
function db_error() {
$error = ocierror();
return $error['message'];
}
/**
* Return a new unique ID in the given sequence.
*
* For compatibility reasons, Drupal does not use auto-numbered fields in its
* database tables. Instead, this function is used to return a new unique ID
* of the type requested. With the Oracle DB implementation, all sequences
* must be created at the time of Oracle scema creation.
*/
function db_next_id($name) {
$id = db_result(db_query("SELECT %s_seq.nextval FROM DUAL", db_prefix_tables($name)));
return $id;
}
/**
* Determine the number of rows changed by the preceding query.
*/
function db_affected_rows() {
global $last_result;
return ocirowcount($last_result);
}
/**
* Runs a limited-range query in the active database.
*
* Use this as a substitute for db_query() when a subset of the query is to be
* returned.
* User-supplied arguments to the query should be passed in as separate parameters
* so that they can be properly escaped to avoid SQL injection attacks.
*
* Note that if you need to know how many results were returned, you should do
* a SELECT COUNT(*) on the temporary table afterwards. db_num_rows() and
* db_affected_rows() do not give consistent result across different database
* types in this case.
*
* @param $query
* A string containing an SQL query.
* @param ...
* A variable number of arguments which are substituted into the query
* using printf() syntax. The query arguments can be enclosed in one
* array instead.
* Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
* in '') and %%.
*
* NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
* and TRUE values to decimal 1.
*
* @param $from
* The first result row to return.
* @param $count
* The maximum number of result rows to return.
* @return
* A database query result resource, or FALSE if the query was not executed
* correctly.
*/
function db_query_range($query) {
$args = func_get_args();
$count = (int) array_pop($args);
$from = (int) array_pop($args);
array_shift($args);
$query = db_prefix_tables($query);
if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
$args = $args[0];
}
_db_query_callback($args, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
$query = 'SELECT * FROM (SELECT sub.*, rownum AS line FROM ('. $query .') sub) WHERE line BETWEEN '. ($from + 1) .' AND '. ($from + $count);
return _db_query($query);
}
/**
* Runs a SELECT query and stores its results in a temporary table.
*
* Use this as a substitute for db_query() when the results need to stored
* in a temporary table. Temporary tables exist for the duration of the page
* request.
* User-supplied arguments to the query should be passed in as separate parameters
* so that they can be properly escaped to avoid SQL injection attacks.
*
* Note that if you need to know how many results were returned, you should do
* a SELECT COUNT(*) on the temporary table afterwards. db_num_rows() and
* db_affected_rows() do not give consistent result across different database
* types in this case.
*
* @param $query
* A string containing a normal SELECT SQL query.
* @param ...
* A variable number of arguments which are substituted into the query
* using printf() syntax. The query arguments can be enclosed in one
* array instead.
* Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
* in '') and %%.
*
* NOTE: using this syntax will cast NULL and FALSE values to decimal 0,
* and TRUE values to decimal 1.
*
* @param $table
* The name of the temporary table to select into. This name will not be
* prefixed as there is no risk of collision.
* @return
* A database query result resource, or FALSE if the query was not executed
* correctly.
*/
function db_query_temporary($query) {
$args = func_get_args();
//print_r($args);
$tablename = array_pop($args);
array_shift($args);
_check_table_existance($tablename);
$query = preg_replace('/^SELECT/i', 'CREATE GLOBAL TEMPORARY TABLE '. $tablename .' AS SELECT', db_prefix_tables($query));
if (isset($args[0]) and is_array($args[0])) { // 'All arguments in one array' syntax
$args = $args[0];
}
_db_query_callback($args, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
return _db_query($query);
}
/**
* Returns a properly formatted Binary Large OBject value.
*
* @param $data
* Data to encode.
* @return
* Encoded data.
*/
function db_encode_blob($data) {
//No processing is needed here, since LOBs in Oracle are input via LOB->Save() and
// dont need any escaping of charecters like \ or '
return "'" . $data . "'";
}
/**
* Returns text from a Binary Large Object value.
*
* @param $data
* Data to decode.
* @return
* Decoded data.
*/
function db_decode_blob($data) {
//No processing is needed here, since LOBs in Oracle are read via LOB->Load()
return $data;
}
/**
* Prepare user input for use in a database query, preventing SQL injection attacks.
*/
function db_escape_string($text) {
// Replace any single ' with two '
return str_replace("'", "''",$text);
}
/**
* Lock a table.
*/
function db_lock_table($table) {
//TODO: should we put a NOWAIT clause ?
db_query('LOCK TABLE {%s} IN EXCLUSIVE MODE', $table);
}
/**
* Unlock all locked tables.
*/
function db_unlock_tables() {
db_query('COMMIT');
}
/**
* Checks if table exists and if so, drops it
*/
function _check_table_existance($tableName) {
$tableName = strtoupper($tableName);
$sql = 'SELECT table_name FROM user_tables WHERE table_name = \'' . $tableName . '\' ';
$result = db_query($sql);
$check = db_fetch_object($result);
if ($check->table_name == $tableName) {
$sql = 'DROP TABLE ' . $tableName;
_db_query($sql);
}
}
/**
* @} End of "ingroup database".
*/