sword _bindBlobVariableTowards4D(ORACLE_SQL_CURSOR *cursor, unsigned int pos)
{	
	_cursorClearForVariableDefine(cursor, pos);
	
	sword err = 0;
	
//	sessionInfo *session = _sessionGet(cursor->sessionId);	
	
	/*
	err = OCIDescriptorAlloc(session->envhp, (dvoid **) &cursor->locators.at(pos), OCI_DTYPE_LOB, 0, 0);
	
	if(!err)
	{
		cursor->isLocatorValid.at(pos) = true;
	}
	*/
	
	if(0)
	{
		/*
		err = OCIDefineByPos(cursor->stmtp, 
							  &cursor->defines.at(pos),
							  cursor->errhp, 
							  pos + 1, 
							  &cursor->locators.at(pos), 
							  MINSB4MAXVAL,
							  SQLT_BLOB,
							  &cursor->indicators.at(pos),  
							  0,
							  0, 
							  OCI_DEFAULT);	
		//http://docs.oracle.com/cd/A97630_01/appdev.920/a96584/oci15r34.htm	
		 
		 */
			
	}else{
			
		err = OCIDefineByPos(cursor->stmtp, 
							 &cursor->defines.at(pos),
							 cursor->errhp, 
							 pos + 1, 
							 0, 
							 MINSB4MAXVAL,
							 SQLT_LBI,
							 &cursor->indicators.at(pos),  
							 0,
							 0, 
							 OCI_DYNAMIC_FETCH);	
		
		err = OCIDefineDynamic(cursor->defines.at(pos),
							   cursor->errhp, 
							   &cursor->bytes.at(pos),
							   _get_blob_data);
	}
	
	return err;
}
Esempio n. 2
0
/*
 * the @ps struct is modified and transferred to the new data model created in
 * this function
 */
GdaDataModel *
gda_oracle_recordset_new (GdaConnection *cnc, GdaOraclePStmt *ps, GdaSet *exec_params,
			  GdaDataModelAccessFlags flags, GType *col_types)
{
	GdaOracleRecordset *model;
        OracleConnectionData *cdata;
        gint i;
	GdaDataModelAccessFlags rflags;

	gint nb_rows = -1;

        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
        g_return_val_if_fail (ps != NULL, NULL);

	cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL);
	if (!cdata)
		return NULL;

	/* make sure @ps reports the correct number of columns using the API */
        if (_GDA_PSTMT (ps)->ncols < 0) {
		ub4 ncolumns;
		int result;
		
                /* get the number of columns in the result set */
                result = OCIAttrGet ((dvoid *) ps->hstmt,
                                     (ub4) OCI_HTYPE_STMT,
                                     (dvoid *) &ncolumns,
                                     (ub4 *) 0,
                                     (ub4) OCI_ATTR_PARAM_COUNT,
                                     cdata->herr);
                if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
                                             _("Could not get the number of columns in the result set")))
                        return NULL;
		
                _GDA_PSTMT (ps)->ncols = ncolumns;
	}

        /* completing @ps if not yet done */
        if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
		/* create prepared statement's columns */
		GSList *list;
		GList *ora_values = NULL;

		for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
			_GDA_PSTMT (ps)->tmpl_columns = g_slist_prepend (_GDA_PSTMT (ps)->tmpl_columns, 
									 gda_column_new ());
		_GDA_PSTMT (ps)->tmpl_columns = g_slist_reverse (_GDA_PSTMT (ps)->tmpl_columns);

		/* create prepared statement's types, all types are initialized to GDA_TYPE_NULL */
		_GDA_PSTMT (ps)->types = g_new (GType, _GDA_PSTMT (ps)->ncols);
		for (i = 0; i < _GDA_PSTMT (ps)->ncols; i++)
			_GDA_PSTMT (ps)->types [i] = GDA_TYPE_NULL;

		if (col_types) {
			for (i = 0; ; i++) {
				if (col_types [i] > 0) {
					if (col_types [i] == G_TYPE_NONE)
						break;
					if (i >= _GDA_PSTMT (ps)->ncols) {
						g_warning (_("Column %d out of range (0-%d), ignoring its specified type"), i,
							   _GDA_PSTMT (ps)->ncols - 1);
						break;
					}
					else
						_GDA_PSTMT (ps)->types [i] = col_types [i];
				}
			}
		}
		
		/* fill GdaColumn's data and define the GdaOracleValue structures */
		for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
		     i < GDA_PSTMT (ps)->ncols; 
		     i++, list = list->next) {
			GdaColumn *column;
			int result;
			GdaOracleValue *ora_value;
			gboolean use_callback = FALSE;

			ora_value = g_new0 (GdaOracleValue, 1);
			ora_values = g_list_prepend (ora_values, ora_value);

			/* parameter to get attributes */
			result = OCIParamGet (ps->hstmt,
					      OCI_HTYPE_STMT,
					      cdata->herr,
					      (dvoid **) &(ora_value->pard),
					      (ub4) i+1);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the Oracle parameter descripter in the result set"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}
			
			/* data size */
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->defined_size),
					     0,
					     (ub4) OCI_ATTR_DATA_SIZE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the parameter defined size"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}
			ora_value->defined_size++;
			
			/* data type */
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->sql_type),
					     0,
					     OCI_ATTR_DATA_TYPE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the parameter data type"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->precision),
					     0,
					     OCI_ATTR_PRECISION,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the type's precision"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			result = OCIAttrGet ((dvoid *) (ora_value->pard),
					     OCI_DTYPE_PARAM,
					     &(ora_value->scale),
					     0,
					     OCI_ATTR_SCALE,
					     cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not get the type's scale"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			/* column's name */
			text *name;
			ub4 name_len;
			
			column = GDA_COLUMN (list->data);
			result = OCIAttrGet ((dvoid *) (ora_value->pard),
                                             (ub4) OCI_DTYPE_PARAM,
                                             (dvoid **) &name,
                                             (ub4 *) &name_len,
                                             (ub4) OCI_ATTR_NAME,
                                             (OCIError *) cdata->herr);
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
                                                     _("Could not get column name in the result set"))) {
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
                                return NULL;
			}

			gchar *name_buffer;
			name_buffer = g_new (gchar, name_len + 1);
			memcpy (name_buffer, name, name_len);
                        name_buffer [name_len] = '\0';
			gda_column_set_name (column, name_buffer);
			gda_column_set_description (column, name_buffer);
			g_free (name_buffer);

			/* for data fetching  */
			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
				ora_value->sql_type = _g_type_to_oracle_sqltype (_GDA_PSTMT (ps)->types [i]);

			switch (ora_value->sql_type) {
			case SQLT_CHR: /* for G_TYPE_STRING => request SQLT_CHR */
			case SQLT_STR:
			case SQLT_VCS:
			case SQLT_RID:
			case SQLT_AVC:
			case SQLT_AFC:
				ora_value->sql_type = SQLT_CHR;
				if (ora_value->defined_size == 1)
					use_callback = TRUE;
				break;

			case SQLT_INT:
				ora_value->defined_size = sizeof (gint);
				break;

			case SQLT_FLT:
			case SQLT_BFLOAT:
				ora_value->defined_size = sizeof (gfloat);
				break;

			case SQLT_BDOUBLE:
				ora_value->defined_size = sizeof (gdouble);
				break;
								
			case SQLT_DAT: /* request OCIDate */
				ora_value->sql_type = SQLT_ODT;
				break;

			case SQLT_NUM: /* for GDA_TYPE_NUMERIC => request SQLT_CHR */
			case SQLT_VNU:
				ora_value->sql_type = SQLT_CHR;
				break;
				
			case SQLT_LBI:
			case SQLT_LVB:
			case SQLT_LVC:
			case SQLT_LNG:
			case SQLT_VBI:
			case SQLT_BIN:
				use_callback = TRUE;
				break;
			default:
				use_callback = TRUE;
				break;
			}
			
			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
				ora_value->g_type = _GDA_PSTMT (ps)->types [i];
			else
				ora_value->g_type = _oracle_sqltype_to_g_type (ora_value->sql_type, ora_value->precision, 
									       ora_value->scale);

			if (ora_value->g_type == GDA_TYPE_BLOB) {
				/* allocate a Lob locator */
				OCILobLocator *lob;
				
				result = OCIDescriptorAlloc ((dvoid *) cdata->henv, (dvoid **) &lob,
							     (ub4) gda_oracle_blob_type (ora_value->sql_type), 
							     (size_t) 0, (dvoid **) 0);
				if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
							     _("Could not allocate Lob locator"))) {
					g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
					return NULL;
				}
				ora_value->value = lob;
				ora_value->defined_size = 0;
			}
			else if (use_callback) {
				ora_value->value = NULL;
				ora_value->defined_size = 33554432; /* 32M */
			}
			else
				ora_value->value = g_malloc0 (ora_value->defined_size);
			
			ora_value->s_type = gda_g_type_to_static_type (ora_value->g_type);
			if (_GDA_PSTMT (ps)->types [i] == GDA_TYPE_NULL)
				_GDA_PSTMT (ps)->types [i] = ora_value->g_type;
			gda_column_set_g_type (column, ora_value->g_type);

#ifdef GDA_DEBUG_NO
			g_print ("**COL type is %d, GType is %s, ORA defined size is %d%s\n",
				 ora_value->sql_type,
				 g_type_name (ora_value->g_type),
				 ora_value->defined_size - 1,
				 use_callback ? " using callback": "");
#endif

			ora_value->hdef = (OCIDefine *) 0;
			ora_value->indicator = 0;
			result = OCIDefineByPos ((OCIStmt *) ps->hstmt,
						 (OCIDefine **) &(ora_value->hdef),
						 (OCIError *) cdata->herr,
						 (ub4) i + 1,
						 ora_value->value,
						 ora_value->defined_size,
						 ora_value->sql_type,
						 (dvoid *) &(ora_value->indicator),
						 &(ora_value->rlen),
						 &(ora_value->rcode),
						 (ub4) (use_callback ? OCI_DYNAMIC_FETCH : OCI_DEFAULT));
			if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
						     _("Could not define by position"))) {
				OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
				g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
				return NULL;
			}

			if (use_callback) {
				result = OCIDefineDynamic ((OCIDefine *) (ora_value->hdef),
							   (OCIError *) (cdata->herr),
							   (dvoid*) (ora_value),
							   (OCICallbackDefine) ora_def_callback);
				if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
							     _("Could not define by position"))) {
					OCIDescriptorFree ((dvoid *) ora_value->pard, OCI_DTYPE_PARAM);
					g_list_foreach (ora_values, (GFunc) _gda_oracle_value_free, NULL);
					return NULL;
				}
			}

			ora_value->use_callback = use_callback;
		}

		ps->ora_values = g_list_reverse (ora_values);
        }

	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported; if CURSOR BACKWARD
         * is requested, then we need RANDOM mode */
        if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
                rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
        else if (flags & GDA_DATA_MODEL_ACCESS_CURSOR_BACKWARD)
                rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
        else
                rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;

	ub4 prefetch;
	prefetch = (ub4) (100);
	OCIAttrSet (ps->hstmt, OCI_HTYPE_STMT,
		    &prefetch, 0,
		    OCI_ATTR_PREFETCH_ROWS, cdata->herr);

	/* create data model */
        model = g_object_new (GDA_TYPE_ORACLE_RECORDSET, 
			      "connection", cnc,
			      "prepared-stmt", ps, 
			      "model-usage", rflags, 
			      "exec-params", exec_params, NULL);
	GDA_DATA_SELECT (model)->advertized_nrows = nb_rows;
	
        return GDA_DATA_MODEL (model);
}