/**
 * This private method is used to help construct
 * the update/sql which is generated by GetInsertSQL and GetUpdateSQL.
 * It handles the string construction of 1 column -> sql string based on
 * the column type.  We want to do 'safe' handling of BLOBs
 *
 * @param string the type of sql we are trying to create
 *                'I' or 'U'.
 * @param string column data type from the db::MetaType() method
 * @param string the column name
 * @param array the column value
 *
 * @return string
 *
 */
function _adodb_column_sql_oci8(&$zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq)
{
    $sql = '';
    // Based on the datatype of the field
    // Format the value properly for the database
    switch ($type) {
        case 'B':
            //in order to handle Blobs correctly, we need
            //to do some magic for Oracle
            //we need to create a new descriptor to handle
            //this properly
            if (!empty($zthis->hasReturningInto)) {
                if ($action == 'I') {
                    $sql = 'empty_blob(), ';
                } else {
                    $sql = $fnameq . '=empty_blob(), ';
                }
                //add the variable to the returning clause array
                //so the user can build this later in
                //case they want to add more to it
                $zthis->_returningArray[$fname] = ':xx' . $fname . 'xx';
            } else {
                if (empty($arrFields[$fname])) {
                    if ($action == 'I') {
                        $sql = 'empty_blob(), ';
                    } else {
                        $sql = $fnameq . '=empty_blob(), ';
                    }
                } else {
                    //this is to maintain compatibility
                    //with older adodb versions.
                    $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, false);
                }
            }
            break;
        case "X":
            //we need to do some more magic here for long variables
            //to handle these correctly in oracle.
            //create a safe bind var name
            //to avoid conflicts w/ dupes.
            if (!empty($zthis->hasReturningInto)) {
                if ($action == 'I') {
                    $sql = ':xx' . $fname . 'xx, ';
                } else {
                    $sql = $fnameq . '=:xx' . $fname . 'xx, ';
                }
                //add the variable to the returning clause array
                //so the user can build this later in
                //case they want to add more to it
                $zthis->_returningArray[$fname] = ':xx' . $fname . 'xx';
            } else {
                //this is to maintain compatibility
                //with older adodb versions.
                $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, false);
            }
            break;
        default:
            $sql = _adodb_column_sql($zthis, $action, $type, $fname, $fnameq, $arrFields, $magicq, false);
            break;
    }
    return $sql;
}
 function getInsertValues(&$zthis, &$rs, $arrFields, $magicq = false, $force = 2)
 {
     $tableName = '';
     $values = '';
     $fields = '';
     $recordSet = null;
     $arrFields = _array_change_key_case($arrFields);
     $fieldInsertedCount = 0;
     if (is_string($rs)) {
         //ok we have a table name
         //try and get the column info ourself.
         $tableName = $rs;
         //we need an object for the recordSet
         //because we have to call MetaType.
         //php can't do a $rsclass::MetaType()
         $rsclass = $zthis->rsPrefix . $zthis->databaseType;
         $recordSet = new $rsclass(-1, $zthis->fetchMode);
         $recordSet->connection =& $zthis;
         if (is_string(self::$cacheRS) && self::$cacheRS == $rs) {
             $columns =& self::$cacheCols;
         } else {
             $columns = $zthis->MetaColumns($tableName);
             self::$cacheRS = $tableName;
             self::$cacheCols = $columns;
         }
     } else {
         if (is_subclass_of($rs, 'adorecordset')) {
             if (isset($rs->insertSig) && is_integer(self::$cacheRS) && self::$cacheRS == $rs->insertSig) {
                 $columns =& self::$cacheCols;
             } else {
                 for ($i = 0, $max = $rs->FieldCount(); $i < $max; $i++) {
                     $columns[] = $rs->FetchField($i);
                 }
                 self::$cacheRS = self::$cacheSig;
                 self::$cacheCols = $columns;
                 $rs->insertSig = self::$cacheSig++;
             }
             $recordSet =& $rs;
         } else {
             printf(ADODB_BAD_RS, 'GetInsertSQL');
             return false;
         }
     }
     // Loop through all of the fields in the recordset
     foreach ($columns as $field) {
         $upperfname = strtoupper($field->name);
         if (adodb_key_exists($upperfname, $arrFields, $force)) {
             $bad = false;
             if (strpos($upperfname, ' ') !== false) {
                 $fnameq = $zthis->nameQuote . $upperfname . $zthis->nameQuote;
             } else {
                 $fnameq = $upperfname;
             }
             $type = $recordSet->MetaType($field->type);
             if (is_null($arrFields[$upperfname]) || empty($arrFields[$upperfname]) && strlen($arrFields[$upperfname]) == 0 || $arrFields[$upperfname] === 'null') {
                 switch ($force) {
                     case 0:
                         // we must always set null if missing
                         $bad = true;
                         break;
                     case 1:
                         $values .= "null, ";
                         break;
                     case 2:
                         //Set empty
                         $arrFields[$upperfname] = "";
                         $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
                         break;
                     default:
                     case 3:
                         //Set the value that was given in array, so you can give both null and
                         //empty values
                         if (is_null($arrFields[$upperfname]) || $arrFields[$upperfname] === 'null') {
                             $values .= "null, ";
                         } else {
                             $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
                         }
                         break;
                 }
                 // switch
             } else {
                 //we do this so each driver can customize the sql for
                 //DB specific column types.
                 //Oracle needs BLOB types to be handled with a returning clause
                 //postgres has special needs as well
                 $values .= _adodb_column_sql($zthis, 'I', $type, $upperfname, $fnameq, $arrFields, $magicq);
             }
             if ($bad) {
                 continue;
             }
             // Set the counter for the number of fields that will be inserted.
             $fieldInsertedCount++;
             // Get the name of the fields to insert
             $fields .= $fnameq . ", ";
         }
     }
     // If there were any inserted fields then build the rest of the insert query.
     if ($fieldInsertedCount <= 0) {
         return false;
     }
     // Get the table name from the existing query.
     if (!$tableName) {
         if (!empty($rs->tableName)) {
             $tableName = $rs->tableName;
         } else {
             if (preg_match("/FROM\\s+" . ADODB_TABLE_REGEX . "/is", $rs->sql, $tableName)) {
                 $tableName = $tableName[1];
             } else {
                 return false;
             }
         }
     }
     // Strip off the comma and space on the end of both the fields
     // and their values.
     $fields = substr($fields, 0, -2);
     $values = substr($values, 0, -2);
     return $values;
 }