Esempio n. 1
0
static GType
fuzzy_get_gtype (SqliteConnectionData *cdata, GdaSqlitePStmt *ps, gint colnum)
{
	const gchar *ctype;
	GType gtype = GDA_TYPE_NULL;
	gint real_col = colnum + ps->nb_rowid_columns;

	if (_GDA_PSTMT (ps)->types [colnum] != GDA_TYPE_NULL)
		return _GDA_PSTMT (ps)->types [colnum];
	
	ctype = SQLITE3_CALL (sqlite3_column_origin_name) (ps->sqlite_stmt, real_col);
	if (ctype && !strcmp (ctype, "rowid"))
		gtype = G_TYPE_INT64;
	else {
		ctype = SQLITE3_CALL (sqlite3_column_decltype) (ps->sqlite_stmt, real_col);
		
		if (ctype) {
			GType *pg;
			pg = g_hash_table_lookup (cdata->types_hash, ctype);
			gtype = pg ? *pg : GDA_TYPE_NULL;
		}
		if (gtype == GDA_TYPE_NULL) 
			gtype = _gda_sqlite_compute_g_type (SQLITE3_CALL (sqlite3_column_type) (ps->sqlite_stmt, real_col));
	}

	return gtype;
}
Esempio n. 2
0
/*
 * the @ps struct is modified and transferred to the new data model created in
 * this function
 *
 * See MySQL's documentation "C API Prepared Statement Type Codes":
 *     http://docs.oracle.com/cd/E17952_01/refman-5.5-en/c-api-prepared-statement-type-codes.html
 */
GdaDataModel *
gda_mysql_recordset_new (GdaConnection            *cnc,
			 GdaMysqlPStmt            *ps,
			 GdaSet                   *exec_params,
			 GdaDataModelAccessFlags   flags,
			 GType                    *col_types)
{
	GdaMysqlRecordset *model;
        MysqlConnectionData *cdata;
        gint i;
	GdaDataModelAccessFlags rflags;

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

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

	g_assert (ps->mysql_stmt);

	/* make sure @ps reports the correct number of columns using the API*/
        if (_GDA_PSTMT (ps)->ncols < 0)
		_GDA_PSTMT(ps)->ncols = mysql_stmt_field_count (ps->mysql_stmt);

        /* completing @ps if not yet done */
	g_assert (! ps->stmt_used);
        ps->stmt_used = TRUE;
        if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
		/* create prepared statement's columns */
		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];
				}
			}
		}
	}

	/* get rid of old bound result if any */
	if (ps->mysql_bind_result) {
		gint i;
		for (i = 0; i < ((GdaPStmt *) ps)->ncols; ++i) {
			g_free (ps->mysql_bind_result[i].buffer);
			g_free (ps->mysql_bind_result[i].is_null);
			g_free (ps->mysql_bind_result[i].length);
		}
		g_free (ps->mysql_bind_result);
		ps->mysql_bind_result = NULL;
	}

	/* fill bind result */
	MYSQL_RES *mysql_res = mysql_stmt_result_metadata (ps->mysql_stmt);
	MYSQL_FIELD *mysql_fields = mysql_fetch_fields (mysql_res);
	
	MYSQL_BIND *mysql_bind_result = g_new0 (MYSQL_BIND, GDA_PSTMT (ps)->ncols);
	GSList *list;

	for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
	     i < GDA_PSTMT (ps)->ncols; 
	     i++, list = list->next) {
		GdaColumn *column = GDA_COLUMN (list->data);
		
		/* use C API to set columns' information using gda_column_set_*() */
		MYSQL_FIELD *field = &mysql_fields[i];
		
		GType gtype = _GDA_PSTMT(ps)->types[i];
		if (gtype == GDA_TYPE_NULL) {
			gtype = _gda_mysql_type_to_gda (cdata, field->type, field->charsetnr);
			_GDA_PSTMT(ps)->types[i] = gtype;
		}
		gda_column_set_g_type (column, gtype);
		gda_column_set_name (column, field->name);
		gda_column_set_description (column, field->name);
		
		/* binding results with types */
		mysql_bind_result[i].buffer_type = field->type;
		mysql_bind_result[i].is_unsigned = field->flags & UNSIGNED_FLAG ? TRUE : FALSE;
		mysql_bind_result[i].is_null = g_malloc0 (sizeof (my_bool));
		
		switch (mysql_bind_result[i].buffer_type) {
		case MYSQL_TYPE_TINY:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (signed char));
			break;
		case MYSQL_TYPE_SHORT:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (short int));
			break;
		case MYSQL_TYPE_INT24:
		case MYSQL_TYPE_LONG:
		case MYSQL_TYPE_YEAR:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (int));
			break;
		case MYSQL_TYPE_LONGLONG:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (long long));
			break;
		case MYSQL_TYPE_NULL:
			break;
		case MYSQL_TYPE_TIME:
		case MYSQL_TYPE_DATE:
		case MYSQL_TYPE_DATETIME:
		case MYSQL_TYPE_TIMESTAMP:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (MYSQL_TIME));
			break;
		case MYSQL_TYPE_FLOAT:
		case MYSQL_TYPE_DOUBLE:
			mysql_bind_result[i].buffer = g_malloc0 (sizeof (double));
			break;
		case MYSQL_TYPE_STRING:
		case MYSQL_TYPE_VAR_STRING:
		case MYSQL_TYPE_BLOB:
		case MYSQL_TYPE_TINY_BLOB:
		case MYSQL_TYPE_MEDIUM_BLOB:
		case MYSQL_TYPE_LONG_BLOB:
		case MYSQL_TYPE_DECIMAL:
		case MYSQL_TYPE_NEWDECIMAL:
		case MYSQL_TYPE_BIT:
			mysql_bind_result[i].buffer = g_malloc0 (field->max_length + 1);
			mysql_bind_result[i].buffer_length = field->max_length + 1;
			mysql_bind_result[i].length = g_malloc0 (sizeof (unsigned long));
			break;
		default:
			g_warning (_("Invalid column bind data type. %d\n"),
				   mysql_bind_result[i].buffer_type);
		}
		/*g_print ("%s(): NAME=%s, TYPE=%d, GTYPE=%s, unsigned: %d\n",
			 __FUNCTION__, field->name, field->type, g_type_name (gtype),
			 field->flags & UNSIGNED_FLAG);*/
	}
	
	if (mysql_stmt_bind_result (ps->mysql_stmt, mysql_bind_result)) {
		g_warning ("mysql_stmt_bind_result failed: %s\n",
			   mysql_stmt_error (ps->mysql_stmt));
	}
	
	mysql_free_result (mysql_res);
	ps->mysql_bind_result = mysql_bind_result;

	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
	if (flags & GDA_DATA_MODEL_ACCESS_RANDOM)
		rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
	else
		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;

	/* create data model */
        model = g_object_new (GDA_TYPE_MYSQL_RECORDSET,
			      "connection", cnc,
			      "prepared-stmt", ps,
			      "model-usage", rflags,
			      "exec-params", exec_params, 
			      NULL);
        model->priv->cnc = cnc;
	g_object_ref (G_OBJECT(cnc));

	model->priv->mysql_stmt = ps->mysql_stmt;

	((GdaDataSelect *) model)->advertized_nrows = mysql_stmt_affected_rows (ps->mysql_stmt);

        return GDA_DATA_MODEL (model);
}
Esempio n. 3
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);
}
Esempio n. 4
0
static GdaRow *
fetch_next_sqlite_row (GdaSqliteRecordset *model, gboolean do_store, GError **error)
{
	int rc;
	SqliteConnectionData *cdata;
	GdaSqlitePStmt *ps;
	GdaRow *prow = NULL;
	GdaConnection *cnc;
	glong length;

	cnc = gda_data_select_get_connection ((GdaDataSelect*) model);
	cdata = (SqliteConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
	if (!cdata)
		return NULL;
	ps = GDA_SQLITE_PSTMT (GDA_DATA_SELECT (model)->prep_stmt);

	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), model);

	if (model->priv->empty_forced)
		rc = SQLITE_DONE;
	else		
		rc = SQLITE3_CALL (sqlite3_step) (ps->sqlite_stmt);
	switch (rc) {
	case  SQLITE_ROW: {
		gint col, real_col;
		prow = gda_row_new (_GDA_PSTMT (ps)->ncols);
		for (col = 0; col < _GDA_PSTMT (ps)->ncols; col++) {
			GValue *value;
			GType type = _GDA_PSTMT (ps)->types [col];
			
			real_col = col + ps->nb_rowid_columns;

			if (type == GDA_TYPE_NULL) {
				type = fuzzy_get_gtype (cdata, ps, col);
				if (type == GDA_TYPE_BLOB) {
					/* extra check: make sure we have a rowid for this blob, or fallback to binary */
					if (ps->rowid_hash) {
						gint oidcol = 0;
						const char *ctable;
						ctable = SQLITE3_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col);
						if (ctable)
							oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
												       ctable));
						if (oidcol == 0) {
							ctable = SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt, real_col);
							if (ctable)
								oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash, 
													       ctable));
						}
						if (oidcol == 0)
							type = GDA_TYPE_BINARY;
					}
					else
						type = GDA_TYPE_BINARY;
				}
				if (type != GDA_TYPE_NULL) {
					GdaColumn *column;
					
					_GDA_PSTMT (ps)->types [col] = type;
					column = gda_data_model_describe_column (GDA_DATA_MODEL (model), col);
					gda_column_set_g_type (column, type);
					column = (GdaColumn *) g_slist_nth_data (_GDA_PSTMT (ps)->tmpl_columns, col);
					gda_column_set_g_type (column, type);
				}
			}
			
			/* fill GValue */
			value = gda_row_get_value (prow, col);
			GError *may_error;
			may_error = (GError*) SQLITE3_CALL (sqlite3_column_blob) (ps->sqlite_stmt, real_col);
			if (may_error && g_hash_table_lookup (error_blobs_hash, may_error)) {
				/*g_print ("Row invalidated: [%s]\n", may_error->message);*/
				gda_row_invalidate_value_e (prow, value, may_error);
				g_hash_table_remove (error_blobs_hash, may_error);
			}
			else if (SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col) == NULL) {
				/* we have a NULL value */
				gda_value_set_null (value);
			}
			else {
				gda_value_reset_with_type (value, type);
				
				if (type == GDA_TYPE_NULL)
					;
				else if (type == G_TYPE_INT) {
					gint64 i;
					i = SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXINT) || (i < G_MININT)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_int (value, (gint) i);
				}
				else if (type == G_TYPE_UINT) {
					guint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if (i > G_MAXUINT) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_uint (value, (gint) i);
				}
				else if (type == G_TYPE_INT64)
					g_value_set_int64 (value, SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col));
				else if (type == G_TYPE_UINT64)
					g_value_set_uint64 (value, (guint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt,
												   real_col));
				else if (type == G_TYPE_DOUBLE)
					g_value_set_double (value, SQLITE3_CALL (sqlite3_column_double) (ps->sqlite_stmt,
											  real_col));
				else if (type == G_TYPE_STRING)
					g_value_set_string (value, (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt,
												  real_col));
				else if (type == GDA_TYPE_BINARY) {
					GdaBinary *bin;
					
					bin = gda_binary_new ();
					length = SQLITE3_CALL (sqlite3_column_bytes) (ps->sqlite_stmt, real_col);
					if (length > 0) {
						gda_binary_set_data (bin, SQLITE3_CALL (sqlite3_column_blob) (ps->sqlite_stmt, /* Flawfinder: ignore */
												       real_col), length);
					}
					gda_value_take_binary (value, bin);
				}
				else if (type == GDA_TYPE_BLOB) {
					GdaBlobOp *bop = NULL;
					gint oidcol = 0;

					if (ps->rowid_hash) {
						const char *ctable;
						ctable = SQLITE3_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col);
						if (ctable)
							oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash,
												       ctable));
						if (oidcol == 0) {
							ctable = SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt, real_col);
							if (ctable)
								oidcol = GPOINTER_TO_INT (g_hash_table_lookup (ps->rowid_hash, 
													       ctable));
						}
					}
					if (oidcol != 0) {
						gint64 rowid;
						rowid = SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, oidcol - 1); /* remove 1
													       because it was added in the first place */
						bop = _gda_sqlite_blob_op_new (cnc,
									       SQLITE3_CALL (sqlite3_column_database_name) (ps->sqlite_stmt, 
													    real_col),
									       SQLITE3_CALL (sqlite3_column_table_name) (ps->sqlite_stmt,
													 real_col),
									       SQLITE3_CALL (sqlite3_column_origin_name) (ps->sqlite_stmt,
													  real_col),
									      rowid);
					}
					if (!bop) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Unable to open BLOB"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						GdaBlob *blob;
						blob = gda_blob_new ();
						gda_blob_set_op (blob, bop);
						g_object_unref (bop);
						gda_value_take_blob (value, blob);
					}
				}
				else if (type == G_TYPE_BOOLEAN)
					g_value_set_boolean (value, SQLITE3_CALL (sqlite3_column_int) (ps->sqlite_stmt, real_col) == 0 ? FALSE : TRUE);
				else if (type == G_TYPE_DATE) {
					GDate date;
					if (!gda_parse_iso8601_date (&date, 
								     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, 
												    real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid date '%s' (date format should be YYYY-MM-DD)"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_boxed (value, &date);
				}
				else if (type == GDA_TYPE_TIME) {
					GdaTime timegda;
					if (!gda_parse_iso8601_time (&timegda, 
								     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, 
												    real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid time '%s' (time format should be HH:MM:SS[.ms])"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						if (timegda.timezone == GDA_TIMEZONE_INVALID)
							timegda.timezone = 0; /* set to GMT */
						gda_value_set_time (value, &timegda);
					}
				}
				else if (type == GDA_TYPE_TIMESTAMP) {
					GdaTimestamp timestamp;
					if (!gda_parse_iso8601_timestamp (&timestamp, 
									  (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt,
													 real_col))) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     _("Invalid timestamp '%s' (format should be YYYY-MM-DD HH:MM:SS[.ms])"), 
							     (gchar *) SQLITE3_CALL (sqlite3_column_text) (ps->sqlite_stmt, real_col));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else {
						if (timestamp.timezone == GDA_TIMEZONE_INVALID)
							timestamp.timezone = 0; /* set to GMT */
						gda_value_set_timestamp (value, &timestamp);
					}
				}
				else if (type == G_TYPE_CHAR) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXINT8) || (i < G_MININT8)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_schar (value, (gchar) i);
				}
				else if (type == G_TYPE_UCHAR) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXUINT8) || (i < 0)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						g_value_set_uchar (value, (guchar) i);
				}
				else if (type == GDA_TYPE_SHORT) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXSHORT) || (i < G_MINSHORT)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						gda_value_set_short (value, (guchar) i);
				}
				else if (type == GDA_TYPE_USHORT) {
					gint64 i;
					i = (gint64) SQLITE3_CALL (sqlite3_column_int64) (ps->sqlite_stmt, real_col);
					if ((i > G_MAXUSHORT) || (i < 0)) {
						GError *lerror = NULL;
						g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
							     GDA_SERVER_PROVIDER_DATA_ERROR,
							     "%s", _("Integer value is too big"));
						gda_row_invalidate_value_e (prow, value, lerror);
					}
					else
						gda_value_set_ushort (value, (guchar) i);
				}
				else {
					GError *lerror = NULL;
					g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
						     GDA_SERVER_PROVIDER_DATA_ERROR,
						     "Unhandled type '%s' in SQLite recordset",
						     gda_g_type_to_string (_GDA_PSTMT (ps)->types [col]));
					gda_row_invalidate_value_e (prow, value, lerror);
				}
			}
		}
		
		if (do_store) {
			/* insert row */
			gda_data_select_take_row (GDA_DATA_SELECT (model), prow, model->priv->next_row_num);
		}
		model->priv->next_row_num ++;
		break;
	}
	case SQLITE_BUSY:
		/* nothing to do */
		break;
	case SQLITE_DONE:
		GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
		break;
	case SQLITE_READONLY:
	case SQLITE_MISUSE:
		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
			     GDA_SERVER_PROVIDER_INTERNAL_ERROR, 
			      "%s", _("SQLite provider fatal internal error"));
		break;
	case SQLITE_ERROR:
	default: {
		GError *lerror = NULL;
		SQLITE3_CALL (sqlite3_reset) (ps->sqlite_stmt);
		if (rc == SQLITE_IOERR_TRUNCATE)
			g_set_error (&lerror, GDA_DATA_MODEL_ERROR,
				     GDA_DATA_MODEL_TRUNCATED_ERROR, "%s", _("Truncated data"));
		else
			g_set_error (&lerror, GDA_SERVER_PROVIDER_ERROR,
				     GDA_SERVER_PROVIDER_INTERNAL_ERROR, 
				     "%s", SQLITE3_CALL (sqlite3_errmsg) (cdata->connection));
		gda_data_select_add_exception (GDA_DATA_SELECT (model), lerror);
		if (rc == SQLITE_ERROR)
			g_propagate_error (error, g_error_copy (lerror));
		GDA_DATA_SELECT (model)->advertized_nrows = model->priv->next_row_num;
		break;
	}
	}

	virt_cnc_set_working_obj (gda_data_select_get_connection ((GdaDataSelect*) model), NULL);

	return prow;
}
Esempio n. 5
0
/*
 * the @ps struct is modified and transferred to the new data model created in
 * this function
 */
GdaDataModel *
_gda_sqlite_recordset_new (GdaConnection *cnc, GdaSqlitePStmt *ps, GdaSet *exec_params,
			   GdaDataModelAccessFlags flags, GType *col_types, gboolean force_empty)
{
	GdaSqliteRecordset *model;
        SqliteConnectionData *cdata;
        gint i;
	GdaDataModelAccessFlags rflags;

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

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

        if (!cdata->types_hash)
                _gda_sqlite_compute_types_hash (cdata);

        /* make sure @ps reports the correct number of columns */
	if (_GDA_PSTMT (ps)->ncols < 0)
		_GDA_PSTMT (ps)->ncols = SQLITE3_CALL (sqlite3_column_count) (ps->sqlite_stmt) -
			ps->nb_rowid_columns;

        /* completing ps */
	g_assert (! ps->stmt_used);
        ps->stmt_used = TRUE;
        if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
		/* create prepared statement's columns */
		GSList *list;
		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);
					else 
						_GDA_PSTMT (ps)->types [i] = col_types [i];
				}
			}
		}
		
		/* fill GdaColumn's data */
		for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
		     i < GDA_PSTMT (ps)->ncols; 
		     i++, list = list->next) {
			GdaColumn *column;
			gint real_col = i + ps->nb_rowid_columns;
			
			column = GDA_COLUMN (list->data);
			gda_column_set_description (column, SQLITE3_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col));
			gda_column_set_name (column, SQLITE3_CALL (sqlite3_column_name) (ps->sqlite_stmt, real_col));
			gda_column_set_dbms_type (column, SQLITE3_CALL (sqlite3_column_decltype) (ps->sqlite_stmt, real_col));
			if (_GDA_PSTMT (ps)->types [i] != GDA_TYPE_NULL)
				gda_column_set_g_type (column, _GDA_PSTMT (ps)->types [i]);
		}
        }

	/* 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;

	/* create data model */
        model = g_object_new (GDA_TYPE_SQLITE_RECORDSET,
			      "connection", cnc,
			      "prepared-stmt", ps, "model-usage", rflags, 
			      "exec-params", exec_params, 
			      "auto-reset", force_empty, NULL);
	gboolean is_virt;
	is_virt = GDA_IS_VCONNECTION_DATA_MODEL (cnc) ? TRUE : FALSE;
	if (is_virt) {
		/* steal the lock */
		_gda_vconnection_change_working_obj ((GdaVconnectionDataModel*) cnc, (GObject*) model);
		_gda_vconnection_set_working_obj ((GdaVconnectionDataModel*) cnc, NULL);
	}

        /* fill the data model */
        read_rows_to_init_col_types (model);

        return GDA_DATA_MODEL (model);
}