/* GDA SQLite provider * Copyright (C) 1998-2002 The GNOME Foundation. * * AUTHORS: * Rodrigo Moya * Carlos Perelló Marín * * This Library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this Library; see the file COPYING.LIB. If not, * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #if defined(HAVE_CONFIG_H) #endif #include #include #include #include #include "gda-sqlite.h" #include "gda-sqlite-provider.h" #include "gda-sqlite-recordset.h" static void gda_sqlite_provider_class_init (GdaSqliteProviderClass *klass); static void gda_sqlite_provider_init (GdaSqliteProvider *provider, GdaSqliteProviderClass *klass); static void gda_sqlite_provider_finalize (GObject *object); static const gchar *gda_sqlite_provider_get_version (GdaServerProvider *provider); static gboolean gda_sqlite_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc, GdaQuarkList *params, const gchar *username, const gchar *password); static gboolean gda_sqlite_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc); static const gchar *gda_sqlite_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc); static const gchar *gda_sqlite_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc); static gboolean gda_sqlite_provider_change_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name); static gboolean gda_sqlite_provider_create_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name); static gboolean gda_sqlite_provider_drop_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name); static GList *gda_sqlite_provider_execute_command (GdaServerProvider *provider, GdaConnection *cnc, GdaCommand *cmd, GdaParameterList *params); static gboolean gda_sqlite_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc, GdaTransaction *xaction); static gboolean gda_sqlite_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc, GdaTransaction *xaction); static gboolean gda_sqlite_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection * cnc, GdaTransaction *xaction); static gboolean gda_sqlite_provider_single_command (const GdaSqliteProvider *provider, GdaConnection *cnc, const gchar *command); static gboolean gda_sqlite_provider_supports (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature); static GdaDataModel *gda_sqlite_provider_get_schema (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionSchema schema, GdaParameterList *params); static GObjectClass *parent_class = NULL; /* * GdaSqliteProvider class implementation */ static void gda_sqlite_provider_class_init (GdaSqliteProviderClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GdaServerProviderClass *provider_class = GDA_SERVER_PROVIDER_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gda_sqlite_provider_finalize; provider_class->get_version = gda_sqlite_provider_get_version; provider_class->open_connection = gda_sqlite_provider_open_connection; provider_class->close_connection = gda_sqlite_provider_close_connection; provider_class->get_server_version = gda_sqlite_provider_get_server_version; provider_class->get_database = gda_sqlite_provider_get_database; provider_class->change_database = gda_sqlite_provider_change_database; provider_class->create_database = gda_sqlite_provider_create_database; provider_class->drop_database = gda_sqlite_provider_drop_database; provider_class->execute_command = gda_sqlite_provider_execute_command; provider_class->begin_transaction = gda_sqlite_provider_begin_transaction; provider_class->commit_transaction = gda_sqlite_provider_commit_transaction; provider_class->rollback_transaction = gda_sqlite_provider_rollback_transaction; provider_class->supports = gda_sqlite_provider_supports; provider_class->get_schema = gda_sqlite_provider_get_schema; } static void gda_sqlite_provider_init (GdaSqliteProvider *sqlite_prv, GdaSqliteProviderClass *klass) { } static void gda_sqlite_provider_finalize (GObject *object) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) object; g_return_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv)); /* chain to parent class */ parent_class->finalize (object); } GType gda_sqlite_provider_get_type (void) { static GType type = 0; if (!type) { static GTypeInfo info = { sizeof (GdaSqliteProviderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gda_sqlite_provider_class_init, NULL, NULL, sizeof (GdaSqliteProvider), 0, (GInstanceInitFunc) gda_sqlite_provider_init }; type = g_type_register_static (PARENT_TYPE, "GdaSqliteProvider", &info, 0); } return type; } GdaServerProvider * gda_sqlite_provider_new (void) { GdaSqliteProvider *provider; provider = g_object_new (gda_sqlite_provider_get_type (), NULL); return GDA_SERVER_PROVIDER (provider); } /* get_version handler for the GdaSqliteProvider class */ static const gchar * gda_sqlite_provider_get_version (GdaServerProvider *provider) { return PACKAGE_VERSION; } /* open_connection handler for the GdaSqliteProvider class */ static gboolean gda_sqlite_provider_open_connection (GdaServerProvider *provider, GdaConnection *cnc, GdaQuarkList *params, const gchar *username, const gchar *password) { const gchar *t_filename = NULL; gint errmsg; SQLITEcnc *scnc; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); /* get all parameters received */ t_filename = gda_quark_list_find (params, "URI"); if (!t_filename || *t_filename != '/') { gda_connection_add_error_string ( cnc, _("A full path must be specified on the " "connection string to open a database.")); return FALSE; } scnc = g_new0 (SQLITEcnc, 1); errmsg = sqlite3_open (t_filename, &scnc->connection); scnc->file = g_strdup (t_filename); if (errmsg != SQLITE_OK) { printf("error %s", sqlite3_errmsg(scnc->connection)); gda_connection_add_error_string (cnc, sqlite3_errmsg(scnc->connection)); sqlite3_close(scnc->connection); g_free (scnc->file); g_free (scnc); return FALSE; } g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE, scnc); /* set SQLite library options */ if (!gda_sqlite_provider_single_command (sqlite_prv, cnc, "PRAGMA empty_result_callbacks = ON")) gda_connection_add_error_string (cnc, _("Could not set empty_result_callbacks SQLite option")); return TRUE; } /* close_connection handler for the GdaSqliteProvider class */ static gboolean gda_sqlite_provider_close_connection (GdaServerProvider *provider, GdaConnection *cnc) { SQLITEcnc *scnc; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); scnc = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE); if (!scnc) { gda_connection_add_error_string (cnc, _("Invalid SQLite handle")); return FALSE; } sqlite3_close (scnc->connection); g_free (scnc->file); g_free (scnc); g_object_set_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE, NULL); return TRUE; } static gchar ** sql_split (const gchar *sql) { GSList *string_list = NULL, *slist; gchar **str_array; guint n = 0; const gchar *remainder = sql, *next = sql; while ((next = (const gchar *) strchr (next, ';')) != NULL) { gchar *tmp = g_strndup (remainder, next - remainder + 1); if (sqlite_complete (tmp)) { string_list = g_slist_prepend (string_list, tmp); n++; remainder = (const gchar *) (next + 1); } else { g_free (tmp); } next++; } if (*remainder) { n++; string_list = g_slist_prepend (string_list, g_strdup (remainder)); } str_array = g_new (gchar*, n + 1); str_array[n--] = NULL; for (slist = string_list; slist; slist = slist->next) str_array[n--] = slist->data; g_slist_free (string_list); return str_array; } static GList * process_sql_commands (GList *reclist, GdaConnection *cnc, const gchar *sql, GdaCommandOptions options) { SQLITEcnc *scnc; gchar *errmsg; gchar **arr; scnc = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE); if (!scnc) { gda_connection_add_error_string (cnc, _("Invalid SQLITE handle")); return NULL; } /* parse SQL string, which can contain several commands, separated by ';' */ arr = sql_split (sql); if (arr) { gint n = 0; while (arr[n]) { SQLITEresult *sres; GdaDataModel *recset; gint status, i; sres = g_new0 (SQLITEresult, 1); status = sqlite3_get_table (scnc->connection, arr[n], &sres->data, &sres->nrows, &sres->ncols, &errmsg); if (options & GDA_COMMAND_OPTION_IGNORE_ERRORS || status == SQLITE_OK) { recset = gda_sqlite_recordset_new (cnc, sres); if (GDA_IS_DATA_MODEL (recset)) { gda_data_model_set_command_text (recset, arr[n]); gda_data_model_set_command_type (recset, GDA_COMMAND_TYPE_SQL); for (i = sres->ncols; i >= 0; i--) gda_data_model_set_column_title (recset, i, sres->data[i]); reclist = g_list_append (reclist, recset); } } else { GdaError *error = gda_error_new (); gda_error_set_description (error, errmsg); gda_connection_add_error (cnc, error); g_list_foreach (reclist, (GFunc) g_object_unref, NULL); g_list_free (reclist); free (errmsg); reclist = NULL; break; } n++; } g_strfreev (arr); } return reclist; } static const gchar * gda_sqlite_provider_get_server_version (GdaServerProvider *provider, GdaConnection *cnc) { static gchar *version_string = NULL; if (!version_string) version_string = g_strdup_printf ("SQLite version %s", SQLITE_VERSION); return (const gchar *) version_string; } static const gchar * gda_sqlite_provider_get_database (GdaServerProvider *provider, GdaConnection *cnc) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; SQLITEcnc *scnc; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), NULL); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); scnc = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE); if (!scnc) { gda_connection_add_error_string (cnc, _("Invalid SQLite handle")); return NULL; } return scnc->file; } /* change_database handler for the GdaSqliteProvider class */ static gboolean gda_sqlite_provider_change_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); gda_connection_add_error_string (cnc, _("Only one database per connection is allowed")); return FALSE; } /* create_database handler for the GdaSqliteProvider class */ static gboolean gda_sqlite_provider_create_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); gda_connection_add_error_string (cnc, _("Only one database per connection is allowed")); return FALSE; } static gboolean gda_sqlite_provider_drop_database (GdaServerProvider *provider, GdaConnection *cnc, const gchar *name) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); gda_connection_add_error_string (cnc, _("To remove a SQLite database you should remove the database file by hand")); return FALSE; } /* execute_command handler for the GdaSqliteProvider class */ static GList * gda_sqlite_provider_execute_command (GdaServerProvider *provider, GdaConnection *cnc, GdaCommand *cmd, GdaParameterList *params) { GList *reclist = NULL; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; GdaCommandOptions options; gchar **arr; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), NULL); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); g_return_val_if_fail (cmd != NULL, NULL); options = gda_command_get_options (cmd); switch (gda_command_get_command_type (cmd)) { case GDA_COMMAND_TYPE_SQL: reclist = process_sql_commands (reclist, cnc, gda_command_get_text (cmd), options); break; case GDA_COMMAND_TYPE_XML: /* FIXME: Implement me */ return NULL; case GDA_COMMAND_TYPE_PROCEDURE: /* FIXME: Implement me */ return NULL; case GDA_COMMAND_TYPE_TABLE: /* there can be multiple table names */ arr = g_strsplit (gda_command_get_text (cmd), ";", 0); if (arr) { GString *str = NULL; gint n = 0; while (arr[n]) { if (!str) str = g_string_new ("SELECT * FROM "); else str = g_string_append (str, "; SELECT * FROM "); str = g_string_append (str, arr[n]); n++; } reclist = process_sql_commands (reclist, cnc, str->str, options); g_string_free (str, TRUE); g_strfreev (arr); } break; case GDA_COMMAND_TYPE_SCHEMA: /* FIXME: Implement me */ return NULL; case GDA_COMMAND_TYPE_INVALID: return NULL; } return reclist; } static gboolean gda_sqlite_provider_begin_transaction (GdaServerProvider *provider, GdaConnection *cnc, GdaTransaction *xaction) { gboolean status; gchar *sql; gchar *name; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); g_return_val_if_fail (GDA_IS_TRANSACTION (xaction), FALSE); if (gda_connection_get_options (cnc) & GDA_CONNECTION_OPTIONS_READ_ONLY) { gda_connection_add_error_string (cnc, _("Transactions are not supported in read-only mode")); return FALSE; } name = gda_transaction_get_name (xaction); if (name) sql = g_strdup_printf ("BEGIN TRANSACTION %s", name); else sql = g_strdup_printf ("BEGIN TRANSACTION"); status = gda_sqlite_provider_single_command (sqlite_prv, cnc, sql); g_free (sql); return status; } static gboolean gda_sqlite_provider_commit_transaction (GdaServerProvider *provider, GdaConnection *cnc, GdaTransaction *xaction) { gboolean status; gchar *sql; gchar *name; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); g_return_val_if_fail (GDA_IS_TRANSACTION (xaction), FALSE); name = gda_transaction_get_name (xaction); if (name) sql = g_strdup_printf ("COMMIT TRANSACTION %s", name); else sql = g_strdup_printf ("COMMIT TRANSACTION"); status = gda_sqlite_provider_single_command (sqlite_prv, cnc, sql); g_free (sql); return status; } static gboolean gda_sqlite_provider_rollback_transaction (GdaServerProvider *provider, GdaConnection *cnc, GdaTransaction *xaction) { gboolean status; gchar *sql; gchar *name; GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE); g_return_val_if_fail (GDA_IS_TRANSACTION (xaction), FALSE); name = gda_transaction_get_name (xaction); if (name) sql = g_strdup_printf ("ROLLBACK TRANSACTION %s", name); else sql = g_strdup_printf ("ROLLBACK TRANSACTION"); status = gda_sqlite_provider_single_command (sqlite_prv, cnc, sql); g_free (sql); return status; } static gboolean gda_sqlite_provider_single_command (const GdaSqliteProvider *provider, GdaConnection *cnc, const gchar *command) { SQLITEcnc *scnc; gboolean result; gint status; gchar *errmsg = NULL; scnc = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE); if (!scnc) { gda_connection_add_error_string (cnc, _("Invalid SQLite handle")); return FALSE; } status = sqlite3_exec (scnc->connection, command, NULL, NULL, &errmsg); if (status == SQLITE_OK) result = TRUE; else { GdaError *error = gda_error_new (); gda_error_set_description (error, errmsg); gda_connection_add_error (cnc, error); result = FALSE; } free (errmsg); return result; } static gboolean gda_sqlite_provider_supports (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionFeature feature) { GdaSqliteProvider *sqlite_prv = (GdaSqliteProvider *) provider; g_return_val_if_fail (GDA_IS_SQLITE_PROVIDER (sqlite_prv), FALSE); switch (feature) { case GDA_CONNECTION_FEATURE_SQL : case GDA_CONNECTION_FEATURE_TRANSACTIONS : case GDA_CONNECTION_FEATURE_AGGREGATES : case GDA_CONNECTION_FEATURE_INDEXES : case GDA_CONNECTION_FEATURE_PROCEDURES : case GDA_CONNECTION_FEATURE_TRIGGERS : case GDA_CONNECTION_FEATURE_VIEWS : return TRUE; default: ; } return FALSE; } static void add_type_row (GdaDataModelArray *recset, const gchar *name, const gchar *owner, const gchar *comments, GdaValueType type) { GList *value_list; value_list = g_list_append (NULL, gda_value_new_string (name)); value_list = g_list_append (value_list, gda_value_new_string (owner)); value_list = g_list_append (value_list, gda_value_new_string (comments)); value_list = g_list_append (value_list, gda_value_new_type (type)); gda_data_model_append_row (GDA_DATA_MODEL (recset), value_list); g_list_foreach (value_list, (GFunc) gda_value_free, NULL); g_list_free (value_list); } static GdaDataModel * get_table_fields (GdaConnection *cnc, GdaParameterList *params) { struct { gchar *col_name; GdaValueType type; } cols[9] = { { N_("Field name") , GDA_VALUE_TYPE_STRING }, { N_("Data type") , GDA_VALUE_TYPE_STRING }, { N_("Size") , GDA_VALUE_TYPE_INTEGER }, { N_("Scale") , GDA_VALUE_TYPE_INTEGER }, { N_("Not null?") , GDA_VALUE_TYPE_BOOLEAN }, { N_("Primary key?") , GDA_VALUE_TYPE_BOOLEAN }, { N_("Unique index?") , GDA_VALUE_TYPE_BOOLEAN }, { N_("References") , GDA_VALUE_TYPE_STRING }, { N_("Default value") , GDA_VALUE_TYPE_STRING } }; GdaParameter *par; const gchar *tblname; GList *reclist; GdaDataModelArray *recset; gchar *sql; gint i; par = gda_parameter_list_find (params, "name"); g_return_val_if_fail (par != NULL, NULL); tblname = gda_value_get_string ((GdaValue *) gda_parameter_get_value (par)); g_return_val_if_fail (tblname != NULL, NULL); /* get the table */ sql = g_strdup_printf ("SELECT * FROM %s", tblname); reclist = process_sql_commands (NULL, cnc, sql, 0); g_free (sql); if (!reclist) return NULL; /* create the recordset to return */ recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new (sizeof cols / sizeof cols[0])); for (i = 0; i < sizeof cols / sizeof cols[0]; i++) gda_data_model_set_column_title (GDA_DATA_MODEL (recset), i, _(cols[i].col_name)); for (i = 0; i < gda_data_model_get_n_columns (GDA_DATA_MODEL (reclist->data)); i++) { GdaFieldAttributes *fa; GList *value_list = NULL; fa = gda_data_model_describe_column (GDA_DATA_MODEL (reclist->data), i); if (!fa) { gda_connection_add_error_string (cnc, _("Could not retrieve information for field")); g_object_unref (G_OBJECT (recset)); recset = NULL; break; } value_list = g_list_append ( value_list, gda_value_new_string (gda_field_attributes_get_name (fa))); value_list = g_list_append ( value_list, gda_value_new_string (gda_type_to_string (gda_field_attributes_get_gdatype (fa)))); value_list = g_list_append ( value_list, gda_value_new_integer (gda_field_attributes_get_defined_size (fa))); value_list = g_list_append ( value_list, gda_value_new_integer (gda_field_attributes_get_scale (fa))); value_list = g_list_append ( value_list, gda_value_new_boolean (!gda_field_attributes_get_allow_null (fa))); value_list = g_list_append ( value_list, gda_value_new_boolean (gda_field_attributes_get_primary_key (fa))); value_list = g_list_append ( value_list, gda_value_new_boolean (gda_field_attributes_get_unique_key (fa))); value_list = g_list_append ( value_list, gda_value_new_string (gda_field_attributes_get_references (fa))); value_list = g_list_append (value_list, gda_value_new_string (NULL)); gda_data_model_append_row (GDA_DATA_MODEL (recset), value_list); g_list_foreach (value_list, (GFunc) gda_value_free, NULL); g_list_free (value_list); } /* free memory */ g_list_foreach (reclist, (GFunc) g_object_unref, NULL); g_list_free (reclist); return recset ? GDA_DATA_MODEL (recset) : NULL; } static GdaDataModel * get_tables (GdaConnection *cnc) { SQLITEcnc *scnc; GList *reclist; gchar *sql; GdaDataModel *model; scnc = g_object_get_data (G_OBJECT (cnc), OBJECT_DATA_SQLITE_HANDLE); if (!scnc) { gda_connection_add_error_string (cnc, _("Invalid SQLite handle")); return FALSE; } sql = g_strdup_printf ("SELECT name, 'system', NULL, sql " " FROM (SELECT * FROM sqlite_master UNION ALL " " SELECT * FROM sqlite_temp_master) " " WHERE type = 'table' " " ORDER BY name"); reclist = process_sql_commands (NULL, cnc, sql, 0); g_free (sql); if (!reclist) return NULL; model = GDA_DATA_MODEL (reclist->data); g_object_ref (G_OBJECT (model)); g_list_foreach (reclist, (GFunc) g_object_unref, NULL); g_list_free (reclist); return model; } static GdaDataModel * get_types (void) { GdaDataModelArray *recset; /* create the recordset */ recset = GDA_DATA_MODEL_ARRAY (gda_data_model_array_new (4)); gda_data_model_set_column_title (GDA_DATA_MODEL (recset), 0, _("Type")); gda_data_model_set_column_title (GDA_DATA_MODEL (recset), 1, _("Owner")); gda_data_model_set_column_title (GDA_DATA_MODEL (recset), 2, _("Comments")); gda_data_model_set_column_title (GDA_DATA_MODEL (recset), 3, _("GDA type")); add_type_row (recset, "string", "system", "Character string", GDA_VALUE_TYPE_STRING); return GDA_DATA_MODEL (recset); } static GdaDataModel * gda_sqlite_provider_get_schema (GdaServerProvider *provider, GdaConnection *cnc, GdaConnectionSchema schema, GdaParameterList *params) { g_return_val_if_fail (GDA_IS_SERVER_PROVIDER (provider), NULL); g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL); switch (schema) { case GDA_CONNECTION_SCHEMA_FIELDS : return get_table_fields (cnc, params); case GDA_CONNECTION_SCHEMA_TABLES : return get_tables (cnc); case GDA_CONNECTION_SCHEMA_TYPES : return get_types (); default: ; } return NULL; }