[libgda] Firebird provider improvements, thanks to Faghmie Davids



commit 9631f452721cb27b6e541df77f4048867c787833
Author: Vivien Malerba <malerba gnome-db org>
Date:   Tue Jan 31 22:56:35 2012 +0100

    Firebird provider improvements, thanks to Faghmie Davids

 providers/firebird/Makefile.am                   |    1 +
 providers/firebird/firebird_specs_dsn.xml.in     |    2 +-
 providers/firebird/firebird_specs_dsn_emb.xml.in |    7 +
 providers/firebird/gda-firebird-meta.c           | 1274 ++++++++++++++++++++--
 providers/firebird/gda-firebird-meta.h           |   16 +-
 providers/firebird/gda-firebird-provider.c       |  787 ++++++++++----
 providers/firebird/gda-firebird-pstmt.c          |   63 +-
 providers/firebird/gda-firebird-pstmt.h          |    2 +-
 providers/firebird/gda-firebird-recordset.c      |  375 +++++---
 providers/firebird/gda-firebird-recordset.h      |    7 +-
 providers/firebird/gda-firebird-util.c           |   26 +-
 providers/firebird/gda-firebird.h                |   17 +-
 providers/firebird/libmain-embed.c               |   13 +-
 13 files changed, 2149 insertions(+), 441 deletions(-)
---
diff --git a/providers/firebird/Makefile.am b/providers/firebird/Makefile.am
index 7394eb2..1e8b9a7 100644
--- a/providers/firebird/Makefile.am
+++ b/providers/firebird/Makefile.am
@@ -65,6 +65,7 @@ libgda_firebird_embed_la_LIBADD = \
 xmldir   = $(datadir)/libgda-5.0
 xml_in_files = \
 	firebird_specs_dsn.xml.in \
+	firebird_specs_dsn_emb.xml.in \
 	firebird_specs_create_table.xml.in 
 
 @INTLTOOL_XML_RULE@
diff --git a/providers/firebird/firebird_specs_dsn.xml.in b/providers/firebird/firebird_specs_dsn.xml.in
index 8880f12..43363dc 100644
--- a/providers/firebird/firebird_specs_dsn.xml.in
+++ b/providers/firebird/firebird_specs_dsn.xml.in
@@ -1,8 +1,8 @@
 <?xml version="1.0"?>
 <data-set-spec>
   <parameters>
+    <parameter id="HOST" _name="Database server" _descr="Host on which the database server is running" gdatype="gchararray"/>
     <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to connect to" gdatype="gchararray" nullok="FALSE"/>
-    <parameter id="CHARACTER_SET" _name="Character Set" _descr="Character set to be used during the connection" gdatype="gchararray"/>
     <!-- FIXME: pre-set values for the SQL_DIALECT values with human readable values -->
     <!--
     <parameter id="SQL_DIALECT" _name="SQL Dialect" _descr="SQL dialect to use during the connection" gdatype="gint"/>
diff --git a/providers/firebird/firebird_specs_dsn_emb.xml.in b/providers/firebird/firebird_specs_dsn_emb.xml.in
new file mode 100644
index 0000000..0a8a835
--- /dev/null
+++ b/providers/firebird/firebird_specs_dsn_emb.xml.in
@@ -0,0 +1,7 @@
+<?xml version="1.0"?>
+<data-set-spec>
+  <parameters>
+    <parameter id="DB_NAME" _name="Database name" _descr="The name of a database to connect to (without the .fdb)" gdatype="gchararray" nullok="FALSE"/>
+    <parameter id="DB_DIR" _name="Directory" _descr="Directory where the database file is stored" gdatype="gchararray" nullok="FALSE" plugin="filesel:MODE=PICKFOLDER"/>
+  </parameters>
+</data-set-spec>
diff --git a/providers/firebird/gda-firebird-meta.c b/providers/firebird/gda-firebird-meta.c
index 052b491..3dbe0a4 100644
--- a/providers/firebird/gda-firebird-meta.c
+++ b/providers/firebird/gda-firebird-meta.c
@@ -25,28 +25,191 @@
 #include <libgda/sql-parser/gda-sql-parser.h>
 #include <glib/gi18n-lib.h>
 #include <libgda/gda-server-provider-extra.h>
+#include <libgda/providers-support/gda-meta-column-types.h>
 #include <libgda/gda-connection-private.h>
 #include <libgda/gda-data-model-array.h>
 #include <libgda/gda-set.h>
 #include <libgda/gda-holder.h>
 
-static gboolean append_a_row (GdaDataModel *to_model, GError **error, gint nb, ...);
+//static gboolean append_a_row (GdaDataModel *to_model, GError **error, gint nb, ...);
 
 /*
  * predefined statements' IDs
  */
 typedef enum {
-        I_STMT_1,
+	I_STMT_CATALOG,
+
+	I_STMT_SCHEMAS,
+
+	I_STMT_SCHEMAS_ALL,
+
+	I_STMT_SCHEMA_NAMED,
+
+	I_STMT_TABLES_ALL,
+
+	I_STMT_TABLES,
+
+	I_STMT_TABLE_NAMED,
+
+	I_STMT_VIEWS_ALL,
+	
+	I_STMT_VIEWS,
+
+	I_STMT_VIEW_NAMED,
+
+	I_STMT_COLUMNS_OF_TABLE,
+
+	I_STMT_COLUMNS_ALL,
+
+	I_STMT_CHARACTER_SETS,
+
+	I_STMT_CHARACTER_SETS_ALL,
+	
+	I_STMT_VIEWS_COLUMNS ,
+	I_STMT_VIEWS_COLUMNS_ALL,
+
+	I_STMT_TABLES_CONSTRAINTS,
+	I_STMT_TABLES_CONSTRAINTS_ALL,
+	I_STMT_TABLES_CONSTRAINTS_NAMED,
+	I_STMT_REF_CONSTRAINTS,
+	I_STMT_REF_CONSTRAINTS_ALL,
+
+	I_STMT_KEY_COLUMN_USAGE,
+	I_STMT_KEY_COLUMN_USAGE_ALL,
+
+	//I_STMT_TRIGGERS,
+	//I_STMT_TRIGGERS_ALL,
+	
+	//I_STMT_ROUTINES,
+	//I_STMT_ROUTINES_ALL,
+	//I_STMT_ROUTINES_ONE,
+	//I_STMT_ROUTINES_PAR_ALL,
+	//I_STMT_ROUTINES_PAR,
+	
+	I_STMT_INDEXES_ALL,
+	I_STMT_INDEXES_TABLE,
+	I_STMT_INDEXES_ONE,
+	I_STMT_INDEX_COLUMNS_ALL,
+	I_STMT_INDEX_COLUMNS_NAMED
+
 } InternalStatementItem;
 
 
 /*
- * predefined statements' SQL
- */
+* predefined statements' SQL
+*/
+#define CATALOG_NAME "'firebird'"
+#define SCHEMA_NAME "'SYS'"
+
 static gchar *internal_sql[] = {
-	"SQL for I_STMT_1"
+	/* I_STMT_CATALOG */
+	"SELECT " CATALOG_NAME " FROM RDB$DATABASE",
+
+	/* I_STMT_SCHEMAS */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, NULL, 1 AS schema_internal FROM RDB$DATABASE",
+
+	/* I_STMT_SCHEMAS_ALL */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, NULL, 1 AS schema_internal FROM RDB$DATABASE",
+
+	/* I_STMT_SCHEMA_NAMED */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, NULL, 1 AS schema_internal FROM RDB$DATABASE",
+
+	/* I_STMT_TABLES_ALL */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RDB$RELATION_NAME), 'BASE TABLE', 1, RDB$RELATION_NAME, TRIM(RDB$RELATION_NAME) AS short_name, TRIM(RDB$OWNER_NAME) || '.' || (TRIM(RDB$RELATION_NAME)) AS table_full_name, TRIM(RDB$OWNER_NAME) FROM RDB$RELATIONS WHERE (RDB$SYSTEM_FLAG = 0) AND (RDB$RELATION_NAME NOT IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS))",
+
+	/* I_STMT_TABLES */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RDB$RELATION_NAME), 'BASE TABLE', 1, RDB$RELATION_NAME, TRIM(RDB$RELATION_NAME) AS short_name, TRIM(RDB$OWNER_NAME) || '.' || (TRIM(RDB$RELATION_NAME)) AS table_full_name, TRIM(RDB$OWNER_NAME) FROM RDB$RELATIONS WHERE (RDB$SYSTEM_FLAG = 0) AND (RDB$RELATION_NAME NOT IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS))",
+
+	/* I_STMT_TABLE_NAMED */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RDB$RELATION_NAME), 'BASE TABLE', 1, RDB$RELATION_NAME, TRIM(RDB$RELATION_NAME) AS short_name, TRIM(RDB$OWNER_NAME) || '.' || (TRIM(RDB$RELATION_NAME)) AS table_full_name, TRIM(RDB$OWNER_NAME) FROM RDB$RELATIONS WHERE (RDB$SYSTEM_FLAG = 0) AND (RDB$RELATION_NAME NOT IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS)) AND (TRIM(RDB$RELATION_NAME)) =  ##tblname::string",
+
+	/* I_STMT_VIEWS_ALL */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RDB$RELATION_NAME), NULL, NULL, 0 FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG = 0 AND RDB$RELATION_NAME IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS)",
+	
+	/* I_STMT_VIEWS */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RDB$RELATION_NAME), NULL, NULL, 0 FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG = 0 AND RDB$RELATION_NAME IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS)",
+
+	/* I_STMT_VIEW_NAMED */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, ((RDB$RELATION_NAME)), NULL, NULL, 0, 0 FROM RDB$RELATIONS WHERE RDB$SYSTEM_FLAG = 0 AND RDB$RELATION_NAME IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS) AND (TRIM(RDB$RELATION_NAME)) =  ##tblname::string",
+
+	/* I_STMT_COLUMNS_OF_TABLE */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RF.RDB$RELATION_NAME), (RF.RDB$FIELD_NAME) AS column_name, RF.RDB$FIELD_POSITION AS ordinal_position, RF.RDB$DEFAULT_VALUE AS column_default, RF.RDB$NULL_FLAG AS is_nullable, LOWER(TRIM(T.RDB$TYPE_NAME)) AS data_type, NULL, 'gchararray', F.RDB$CHARACTER_LENGTH AS character_maximum_length, F.RDB$FIELD_LENGTH AS character_octet_length, F.RDB$FIELD_PRECISION AS numeric_precision, F.RDB$FIELD_SCALE AS numeric_scale, NULL, NULL AS CHAR_SET_CAT, NULL AS CHAR_SET_SCHEMA, NULL AS CHAR_SET_NAME, NULL AS COLLATION_CAT, NULL AS COLLATION_NAME, NULL, NULL AS Extra, RF.RDB$UPDATE_FLAG as is_updatable, '' as column_comment FROM RDB$RELATION_FIELDS AS RF INNER JOIN RDB$RELATIONS R ON R.RDB$RELATION_NAME = RF.RDB$RELATION_NAME INNER JOIN RDB$FIELDS AS F ON ((F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE))  INNER JOIN RDB$TYPES AS T ON (((T.RDB$TYPE = F.RDB$FIELD_TYPE) AND (T.RDB$FIELD_NAME = 'RDB$FIELD_TYPE')))  WHERE RF.R
 DB$SYSTEM_FLAG = 0  AND R.RDB$RELATION_NAME NOT IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS)  AND (RF.RDB$RELATION_NAME) = ##tblname::string  ORDER BY RF.RDB$RELATION_NAME ASC, RDB$FIELD_POSITION ASC",
+
+	/* I_STMT_COLUMNS_ALL */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS schema_name, (RF.RDB$RELATION_NAME), (RF.RDB$FIELD_NAME) AS column_name, RF.RDB$FIELD_POSITION AS ordinal_position, RF.RDB$DEFAULT_VALUE AS column_default, RF.RDB$NULL_FLAG AS is_nullable, LOWER(TRIM(T.RDB$TYPE_NAME)) AS data_type, NULL, 'gchararray', F.RDB$CHARACTER_LENGTH AS character_maximum_length, F.RDB$FIELD_LENGTH AS character_octet_length, F.RDB$FIELD_PRECISION AS numeric_precision, F.RDB$FIELD_SCALE AS numeric_scale, NULL, NULL AS CHAR_SET_CAT, NULL AS CHAR_SET_SCHEMA, NULL AS CHAR_SET_NAME, NULL AS COLLATION_CAT, NULL AS COLLATION_NAME, NULL, NULL AS Extra, RF.RDB$UPDATE_FLAG as is_updatable, '' as column_comment FROM RDB$RELATION_FIELDS AS RF INNER JOIN RDB$RELATIONS R ON R.RDB$RELATION_NAME = RF.RDB$RELATION_NAME INNER JOIN RDB$FIELDS AS F ON ((F.RDB$FIELD_NAME = RF.RDB$FIELD_SOURCE))  INNER JOIN RDB$TYPES AS T ON (((T.RDB$TYPE = F.RDB$FIELD_TYPE) AND (T.RDB$FIELD_NAME = 'RDB$FIELD_TYPE'))) WHERE RF.RD
 B$SYSTEM_FLAG = 0 AND R.RDB$RELATION_NAME NOT IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS) ORDER BY RF.RDB$RELATION_NAME ASC, RDB$FIELD_POSITION ASC",
+
+	/* I_STMT_CHARACTER_SETS */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS character_set_schema, RDB$CHARACTER_SET_NAME, RDB$DEFAULT_COLLATE_NAME, RDB$DEFAULT_COLLATE_NAME, RDB$DEFAULT_COLLATE_NAME, NULL, RDB$CHARACTER_SET_NAME, RDB$CHARACTER_SET_NAME FROM RDB$CHARACTER_SETS WHERE RDB$CHARACTER_SET_NAME = ##char_set_name::string",
+
+	/* I_STMT_CHARACTER_SETS_ALL */
+	"SELECT " CATALOG_NAME " AS catalog_name, " SCHEMA_NAME " AS character_set_schema, RDB$CHARACTER_SET_NAME, RDB$DEFAULT_COLLATE_NAME, RDB$DEFAULT_COLLATE_NAME, RDB$DEFAULT_COLLATE_NAME, NULL, RDB$CHARACTER_SET_NAME, RDB$CHARACTER_SET_NAME FROM RDB$CHARACTER_SETS",
+	
+	/* I_STMT_VIEWS_COLUMNS */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", (RDB$RELATION_NAME), " CATALOG_NAME ", " SCHEMA_NAME ", (RDB$RELATION_NAME), RDB$FIELD_NAME FROM RDB$RELATION_FIELDS WHERE RDB$SYSTEM_FLAG = 0 AND RDB$RELATION_NAME IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS) AND TRIM(RDB$RELATION_NAME) = ##tblname::string",
+
+	/* I_STMT_VIEWS_COLUMNS_ALL */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", (RDB$RELATION_NAME), " CATALOG_NAME ", " SCHEMA_NAME ", (RDB$RELATION_NAME), RDB$FIELD_NAME FROM RDB$RELATION_FIELDS WHERE RDB$SYSTEM_FLAG = 0 AND RDB$RELATION_NAME IN (SELECT RDB$VIEW_NAME FROM RDB$VIEW_RELATIONS)",
+
+	/* I_STMT_TABLES_CONSTRAINTS */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", RDB$CONSTRAINT_NAME, " CATALOG_NAME ", " SCHEMA_NAME ", TRIM(RDB$RELATION_NAME), RDB$CONSTRAINT_TYPE, NULL, CASE WHEN RDB$DEFERRABLE = 'YES' THEN 1 ELSE 0 END, CASE WHEN RDB$INITIALLY_DEFERRED = 'YES' THEN 1 ELSE 0 END FROM RDB$RELATION_CONSTRAINTS WHERE TRIM(RDB$RELATION_NAME) = ##tblname::string",
+
+	/* I_STMT_TABLES_CONSTRAINTS_ALL */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", RDB$CONSTRAINT_NAME, " CATALOG_NAME ", " SCHEMA_NAME ", RDB$RELATION_NAME, RDB$CONSTRAINT_TYPE, NULL, CASE WHEN RDB$DEFERRABLE = 'YES' THEN 1 ELSE 0 END, CASE WHEN RDB$INITIALLY_DEFERRED = 'YES' THEN 1 ELSE 0 END FROM RDB$RELATION_CONSTRAINTS",
+
+	/* I_STMT_TABLES_CONSTRAINTS_NAMED */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", RDB$CONSTRAINT_NAME, " CATALOG_NAME ", " SCHEMA_NAME ", RDB$RELATION_NAME, RDB$CONSTRAINT_TYPE, NULL, CASE WHEN RDB$DEFERRABLE = 'YES' THEN 1 ELSE 0 END, CASE WHEN RDB$INITIALLY_DEFERRED = 'YES' THEN 1 ELSE 0 END FROM RDB$RELATION_CONSTRAINTS WHERE TRIM(RDB$RELATION_NAME) = ##tblname::string AND RDB$CONSTRAINT_NAME = ##constraint_name::string",
+
+	/* I_STMT_REF_CONSTRAINTS */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ",  TRIM(R1.RDB$RELATION_NAME), C.RDB$CONSTRAINT_NAME,  " CATALOG_NAME ", " SCHEMA_NAME ", TRIM(R2.RDB$RELATION_NAME), C.RDB$CONST_NAME_UQ, RDB$MATCH_OPTION, RDB$UPDATE_RULE, RDB$DELETE_RULE FROM RDB$REF_CONSTRAINTS C INNER JOIN RDB$RELATION_CONSTRAINTS R1 ON R1.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME INNER JOIN RDB$RELATION_CONSTRAINTS R2 ON R2.RDB$CONSTRAINT_NAME = C.RDB$CONST_NAME_UQ WHERE TRIM(R1.RDB$RELATION_NAME) = ##tblname::string AND C.RDB$CONSTRAINT_NAME = ##constraint_name::string",
+
+	/* I_STMT_REF_CONSTRAINTS_ALL */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ",  TRIM(R1.RDB$RELATION_NAME), C.RDB$CONSTRAINT_NAME,  " CATALOG_NAME ", " SCHEMA_NAME ", TRIM(R2.RDB$RELATION_NAME), C.RDB$CONST_NAME_UQ, RDB$MATCH_OPTION, RDB$UPDATE_RULE, RDB$DELETE_RULE FROM RDB$REF_CONSTRAINTS C INNER JOIN RDB$RELATION_CONSTRAINTS R1 ON R1.RDB$CONSTRAINT_NAME = C.RDB$CONSTRAINT_NAME INNER JOIN RDB$RELATION_CONSTRAINTS R2 ON R2.RDB$CONSTRAINT_NAME = C.RDB$CONST_NAME_UQ",
+
+	/* I_STMT_KEY_COLUMN_USAGE */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", TRIM(r.RDB$RELATION_NAME), r.rdb$constraint_name, i.rdb$field_name, i.RDB$FIELD_POSITION FROM rdb$relation_constraints r INNER JOIN rdb$index_segments i ON r.rdb$index_name = i.rdb$index_name WHERE (r.rdb$constraint_type='PRIMARY KEY') AND TRIM(r.RDB$RELATION_NAME) = ##tblname::string AND r.rdb$constraint_name = ##constraint_name::string",
+
+	/* I_STMT_KEY_COLUMN_USAGE_ALL */
+	"SELECT " CATALOG_NAME ", " SCHEMA_NAME ", TRIM(r.RDB$RELATION_NAME), r.rdb$constraint_name, i.rdb$field_name, i.RDB$FIELD_POSITION FROM rdb$relation_constraints r INNER JOIN rdb$index_segments i ON r.rdb$index_name = i.rdb$index_name WHERE (r.rdb$constraint_type='PRIMARY KEY') ORDER BY r.rdb$constraint_name, i.rdb$field_position",
+
+	/* I_STMT_TRIGGERS */
+	//"SELECT " CATALOG_NAME " AS trigger_catalog, trigger_schema, trigger_name, event_manipulation, " CATALOG_NAME " AS event_object_catalog, event_object_schema, event_object_table, action_statement, action_orientation, action_timing, NULL, trigger_name, trigger_name FROM INFORMATION_SCHEMA.triggers WHERE trigger_schema =  ##schema::string AND trigger_name = ##name::string",
+
+	/* I_STMT_TRIGGERS_ALL */
+	//"SELECT " CATALOG_NAME " AS trigger_catalog, trigger_schema, trigger_name, event_manipulation, " CATALOG_NAME " AS event_object_catalog, event_object_schema, event_object_table, action_statement, action_orientation, action_timing, NULL, trigger_name, trigger_name FROM INFORMATION_SCHEMA.triggers",
+
+	/* I_STMT_ROUTINES_ALL */
+	//"SELECT " CATALOG_NAME " AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, " CATALOG_NAME " AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines",
+
+	/* I_STMT_ROUTINES */
+	//"SELECT " CATALOG_NAME " AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, " CATALOG_NAME " AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_schema =  ##schema::string",
+
+	/* I_STMT_ROUTINES_ONE */
+	//"SELECT " CATALOG_NAME " AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, " CATALOG_NAME " AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_schema =  ##schema::string AND routine_name = ##name::string",
+
+	/* I_STMT_ROUTINES_PAR_ALL */
+	//"SELECT " CATALOG_NAME " AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, " CATALOG_NAME " AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines",
+
+	/* I_STMT_ROUTINES_PAR */
+	//"SELECT " CATALOG_NAME " AS specific_catalog, routine_schema AS specific_schema, routine_name AS specific_name, " CATALOG_NAME " AS routine_catalog, routine_schema, routine_name, routine_type, dtd_identifier AS return_type, FALSE AS returns_set, 0 AS nb_args, routine_body, routine_definition, external_name, external_language, parameter_style, CASE is_deterministic WHEN 'YES' THEN TRUE ELSE FALSE END AS is_deterministic, sql_data_access, FALSE AS is_null_call, routine_comment, routine_name, routine_name, definer FROM INFORMATION_SCHEMA.routines WHERE routine_schema = ##schema::string AND routine_name = ##name::string",
+
+	/* I_STMT_INDEXES_ALL */
+	"SELECT DISTINCT " CATALOG_NAME ", " SCHEMA_NAME ", INDEX_NAME, " CATALOG_NAME ", TABLE_SCHEMA, TABLE_NAME, NOT NON_UNIQUE, NULL, INDEX_TYPE, NULL, NULL, COMMENT FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME <> 'PRIMARY'",
+
+	/* I_STMT_INDEXES_TABLE */
+	"SELECT DISTINCT " CATALOG_NAME ", " SCHEMA_NAME ", INDEX_NAME, " CATALOG_NAME ", TABLE_SCHEMA, TABLE_NAME, NOT NON_UNIQUE, NULL, INDEX_TYPE, NULL, NULL, COMMENT FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME <> 'PRIMARY' AND TABLE_SCHEMA = ##schema::string AND TABLE_NAME = ##name::string",
+
+	/* I_STMT_INDEXES_ONE */
+	"SELECT DISTINCT " CATALOG_NAME ", INDEX_SCHEMA, INDEX_NAME, " CATALOG_NAME ", TABLE_SCHEMA, TABLE_NAME, NOT NON_UNIQUE, NULL, INDEX_TYPE, NULL, NULL, COMMENT FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME <> 'PRIMARY' AND TABLE_SCHEMA = ##schema::string AND TABLE_NAME = ##name::string AND INDEX_NAME = ##name2::string",
+
+	/* I_STMT_INDEX_COLUMNS_ALL */
+	"SELECT DISTINCT " CATALOG_NAME ", INDEX_SCHEMA, INDEX_NAME, " CATALOG_NAME ", TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_NAME, SEQ_IN_INDEX FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME <> 'PRIMARY' ORDER BY INDEX_SCHEMA, INDEX_NAME, SEQ_IN_INDEX",
+
+	/* I_STMT_INDEX_COLUMNS_NAMED */
+	"SELECT DISTINCT " CATALOG_NAME ", INDEX_SCHEMA, INDEX_NAME, " CATALOG_NAME ", TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLUMN_NAME, SEQ_IN_INDEX FROM INFORMATION_SCHEMA.STATISTICS WHERE INDEX_NAME <> 'PRIMARY' AND TABLE_SCHEMA = ##schema::string AND TABLE_NAME = ##name::string AND INDEX_NAME = ##name2::string ORDER BY INDEX_SCHEMA, INDEX_NAME, SEQ_IN_INDEX"
+
 };
 
+
 /*
  * global static values, and
  * predefined statements' GdaStatement, all initialized in _gda_postgres_provider_meta_init()
@@ -69,20 +232,31 @@ _gda_firebird_provider_meta_init (GdaServerProvider *provider)
 
 	g_static_mutex_lock (&init_mutex);
 
-        internal_parser = gda_server_provider_internal_get_parser (provider);
-        internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
-        for (i = I_STMT_1; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
-                internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
-                if (!internal_stmt[i])
-                        g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
-        }
+	internal_parser = gda_server_provider_internal_get_parser (provider);
+	internal_stmt = g_new0 (GdaStatement *, sizeof (internal_sql) / sizeof (gchar*));
+	for (i = I_STMT_CATALOG; i < sizeof (internal_sql) / sizeof (gchar*); i++) {
+			internal_stmt[i] = gda_sql_parser_parse_string (internal_parser, internal_sql[i], NULL, NULL);
+			if (!internal_stmt[i])
+					g_error ("Could not parse internal statement: %s\n", internal_sql[i]);
+	}
 
 	/* initialize static values here */
-	i_set = gda_set_new_inline (4, "cat", G_TYPE_STRING, "", 
-				    "name", G_TYPE_STRING, "",
+	
+	i_set = gda_set_new_inline (5, "tblname", G_TYPE_STRING, "", 
+				    "schema", G_TYPE_STRING, "",
+				    "constraint_name", G_TYPE_STRING, "",
+				    "field_name", G_TYPE_STRING, ""
+				    , "char_set_name", G_TYPE_STRING, "");
+	g_static_mutex_unlock (&init_mutex);
+	
+	/* initialize static values here */
+	/*
+	i_set = gda_set_new_inline (3, "name", G_TYPE_STRING, "",
 				    "schema", G_TYPE_STRING, "",
-				    "name2", G_TYPE_STRING, "");
+                                    "name2", G_TYPE_STRING, "");
+	
 	g_static_mutex_unlock (&init_mutex);
+	*/
 }
 
 gboolean
@@ -91,17 +265,21 @@ _gda_firebird_meta__info (GdaServerProvider *prov, GdaConnection *cnc,
 {
 	GdaDataModel *model;
 	gboolean retval;
-
-	TO_IMPLEMENT;
-	/* fill in @model, with something like:
-	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_1], NULL, 
-	 *                                                  error);
-	 */
+	//WHERE_AM_I;
+	model = gda_connection_statement_execute_select_full (cnc
+								, internal_stmt[I_STMT_CATALOG]
+								, NULL
+								, GDA_DATA_MODEL_ACCESS_RANDOM
+								, _col_types_information_schema_catalog_name
+								, error);
 	if (!model)
 		return FALSE;
+	
+	gda_meta_store_set_identifiers_style (store, GDA_SQL_IDENTIFIERS_UPPER_CASE);
 	retval = gda_meta_store_modify_with_context (store, context, model, error);
 	g_object_unref (model);
-		
+	if (!retval){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
 	return retval;
 }
 
@@ -109,15 +287,141 @@ gboolean
 _gda_firebird_meta__btypes (GdaServerProvider *prov, GdaConnection *cnc, 
 			GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	//WHERE_AM_I;
+	typedef struct
+	{
+		gchar  *tname;
+		gchar  *gtype;
+		gchar  *comments;
+		gchar  *synonyms;
+	} BuiltinDataType;
+
+	BuiltinDataType data_types[] = {
+		{ "CHAR"
+			, "gchararray"
+			, "A fixed-length string that is always right-padded with spaces to the specified length when stored. M represents the column length in characters. The range of M is 0 to 255. If M is omitted, the length is 1."
+			, "" }
+		, { "VARCHAR"
+			, "gchararray"
+			, "A variable-length string. M represents the maximum column length in characters. In MySQL 5.0, the range of M is 0 to 255 before MySQL 5.0.3, and 0 to 65,535 in MySQL 5.0.3 and later. The effective maximum length of a VARCHAR in MySQL 5.0.3 and later is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used. For example, utf8 characters can require up to three bytes per character, so a VARCHAR column that uses the utf8 character set can be declared to be a maximum of 21,844 characters."
+			, "" }
+
+		, { "DATE"
+			, "GDate"
+			, "A date. The supported range is '1000-01-01' to '9999-12-31'. MySQL displays DATE values in 'YYYY-MM-DD' format, but allows assignment of values to DATE columns using either strings or numbers."
+			, "" }
+		, { "TIME"
+			, "GdaTime"
+			, "A time. The range is '-838:59:59' to '838:59:59'. MySQL displays TIME values in 'HH:MM:SS' format, but allows assignment of values to TIME columns using either strings or numbers."
+			, "" }
+			
+		, { "TIMESTAMP"
+			, "GdaTimestamp"
+			, "A timestamp. The range is '1970-01-01 00:00:01' UTC to partway through the year 2038. TIMESTAMP values are stored as the number of seconds since the epoch ('1970-01-01 00:00:00' UTC). A TIMESTAMP cannot represent the value '1970-01-01 00:00:00' because that is equivalent to 0 seconds from the epoch and the value 0 is reserved for representing '0000-00-00 00:00:00', the \"zero\" TIMESTAMP value."
+			, "" }
+
+		, { "SMALLINT"
+			, "gint"
+			, "A small integer. The signed range is -32768 to 32767. The unsigned range is 0 to 65535."
+			, "" }	
+		, { "INTEGER"
+			, "gint"
+			, "A normal-size integer. The signed range is -2147483648 to 2147483647. The unsigned range is 0 to 4294967295."
+			, "INTEGER" }
+		, { "DECIMAL"
+			, "GdaNumeric"
+			, "A packed \"exact\" fixed-point number. M is the total number of digits (the precision) and D is the number of digits after the decimal point (the scale). The decimal point and (for negative numbers) the \"-\" sign are not counted in M. If D is 0, values have no decimal point or fractional part. The maximum number of digits (M) for DECIMAL is 65 (64 from 5.0.3 to 5.0.5). The maximum number of supported decimals (D) is 30. If D is omitted, the default is 0. If M is omitted, the default is 10."
+			, "DEC" }
+		, { "DOUBLE"
+			, "gdouble"
+			, "A normal-size (double-precision) floating-point number. Allowable values are -1.7976931348623157E+308 to -2.2250738585072014E-308, 0, and 2.2250738585072014E-308 to 1.7976931348623157E+308. These are the theoretical limits, based on the IEEE standard. The actual range might be slightly smaller depending on your hardware or operating system."
+			, "DOUBLE PRECISION" }
+
+		, { "FLOAT"
+			, "gfloat"
+			, "A small (single-precision) floating-point number. Allowable values are -3.402823466E+38 to -1.175494351E-38, 0, and 1.175494351E-38 to 3.402823466E+38. These are the theoretical limits, based on the IEEE standard. The actual range might be slightly smaller depending on your hardware or operating system."
+			, "" }
+		, { "NUMERIC"
+			, "GdaNumeric"
+			, "A BLOB column with a maximum length of 4,294,967,295 or 4GB (232 - 1) bytes. The effective maximum length of LONGBLOB columns depends on the configured maximum packet size in the client/server protocol and available memory. Each LONGBLOB value is stored using a four-byte length prefix that indicates the number of bytes in the value."
+			, "" }
+		, { "INT64"
+			, "gint64"
+			, "A large integer. The signed range is -9223372036854775808 to 9223372036854775807. The unsigned range is 0 to 18446744073709551615."
+			, "" }
+		, { "BIGINT"
+			, "gint64"
+			, "A large integer. The signed range is -9223372036854775808 to 9223372036854775807. The unsigned range is 0 to 18446744073709551615."
+			, "" }
+
+		, { "BLOB"
+			, "GdaBinary"
+			, "A BLOB column with a maximum length of 65,535 (216 - 1) bytes. Each BLOB value is stored using a two-byte length prefix that indicates the number of bytes in the value."
+			, "" }
+
+	};
+
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	model = gda_meta_store_create_modify_data_model (store, context->table_name);
+	if (model == NULL)
+			retval = FALSE;
+	else {
+		gsize i;
+		for (i = 0; i < sizeof(data_types) / sizeof(BuiltinDataType); ++i) {
+			BuiltinDataType *data_type = &(data_types[i]);
+			GList *values = NULL;
+			GValue *tmp_value = NULL;
+
+			g_value_set_string (tmp_value = gda_value_new (G_TYPE_STRING), data_type->tname);
+			values = g_list_append (values, tmp_value); 
+
+			g_value_set_string (tmp_value = gda_value_new (G_TYPE_STRING), data_type->tname);
+			values = g_list_append (values, tmp_value); 
+
+			g_value_set_string (tmp_value = gda_value_new (G_TYPE_STRING), data_type->gtype);
+			values = g_list_append (values, tmp_value); 
+
+			g_value_set_string (tmp_value = gda_value_new (G_TYPE_STRING), data_type->comments);
+			values = g_list_append (values, tmp_value); 
+
+			if (data_type->synonyms && *(data_type->synonyms))
+				g_value_set_string (tmp_value = gda_value_new (G_TYPE_STRING), data_type->synonyms);
+			else
+				tmp_value = gda_value_new_null ();
+			values = g_list_append (values, tmp_value); 
+
+			g_value_set_boolean (tmp_value = gda_value_new (G_TYPE_BOOLEAN), FALSE);
+			values = g_list_append (values, tmp_value); 
+
+			if (gda_data_model_append_values (model, values, NULL) < 0) {
+				retval = FALSE;
+				break;
+			}
+
+			g_list_foreach (values, (GFunc) gda_value_free, NULL);
+			g_list_free (values);
+		}
+
+		if (retval) {
+			//retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+			retval = gda_meta_store_modify_with_context (store, context, model, error);
+		}
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__udt (GdaServerProvider *prov, GdaConnection *cnc, 
 		     GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -126,22 +430,24 @@ _gda_firebird_meta_udt (GdaServerProvider *prov, GdaConnection *cnc,
 		    GdaMetaStore *store, GdaMetaContext *context, GError **error,
 		    const GValue *udt_catalog, const GValue *udt_schema)
 {
-	GdaDataModel *model;
+	//GdaDataModel *model;
 	gboolean retval = TRUE;
 
+	//WHERE_AM_I;
+
 	/* set internal holder's values from the arguments */
 	gda_holder_set_value (gda_set_get_holder (i_set, "cat"), udt_catalog, error);
 	gda_holder_set_value (gda_set_get_holder (i_set, "schema"), udt_schema, error);
 
-	TO_IMPLEMENT;
+	//TO_IMPLEMENT;
 	/* fill in @model, with something like:
 	 * model = gda_connection_statement_execute_select (cnc, internal_stmt[I_STMT_UDT], i_set, error);
-	 */
+	 *
 	if (!model)
 		return FALSE;
 	retval = gda_meta_store_modify_with_context (store, context, model, error);
 	g_object_unref (model);
-
+	*/
 	return retval;
 }
 
@@ -150,8 +456,10 @@ gboolean
 _gda_firebird_meta__udt_cols (GdaServerProvider *prov, GdaConnection *cnc, 
 			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;	
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
+	return TRUE;
 }
 
 gboolean
@@ -159,16 +467,20 @@ _gda_firebird_meta_udt_cols (GdaServerProvider *prov, GdaConnection *cnc,
 			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
 			 const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;	
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
+	return TRUE;
 }
 
 gboolean
 _gda_firebird_meta__enums (GdaServerProvider *prov, GdaConnection *cnc, 
 		       GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;	
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
+	return TRUE;
 }
 
 gboolean
@@ -176,7 +488,9 @@ _gda_firebird_meta_enums (GdaServerProvider *prov, GdaConnection *cnc,
 		      GdaMetaStore *store, GdaMetaContext *context, GError **error,
 		      const GValue *udt_catalog, const GValue *udt_schema, const GValue *udt_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -185,7 +499,9 @@ gboolean
 _gda_firebird_meta__domains (GdaServerProvider *prov, GdaConnection *cnc, 
 			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -194,7 +510,9 @@ _gda_firebird_meta_domains (GdaServerProvider *prov, GdaConnection *cnc,
 			GdaMetaStore *store, GdaMetaContext *context, GError **error,
 			const GValue *domain_catalog, const GValue *domain_schema)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -202,7 +520,9 @@ gboolean
 _gda_firebird_meta__constraints_dom (GdaServerProvider *prov, GdaConnection *cnc, 
 				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -212,7 +532,9 @@ _gda_firebird_meta_constraints_dom (GdaServerProvider *prov, GdaConnection *cnc,
 				const GValue *domain_catalog, const GValue *domain_schema, 
 				const GValue *domain_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -220,7 +542,9 @@ gboolean
 _gda_firebird_meta__el_types (GdaServerProvider *prov, GdaConnection *cnc, 
 			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -229,7 +553,9 @@ _gda_firebird_meta_el_types (GdaServerProvider *prov, GdaConnection *cnc,
 			 GdaMetaStore *store, GdaMetaContext *context, GError **error,
 			 const GValue *specific_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -237,7 +563,9 @@ gboolean
 _gda_firebird_meta__collations (GdaServerProvider *prov, GdaConnection *cnc, 
 			    GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -247,7 +575,9 @@ _gda_firebird_meta_collations (GdaServerProvider *prov, GdaConnection *cnc,
 			   const GValue *collation_catalog, const GValue *collation_schema, 
 			   const GValue *collation_name_n)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -255,8 +585,24 @@ gboolean
 _gda_firebird_meta__character_sets (GdaServerProvider *prov, GdaConnection *cnc, 
 				GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+	//WHERE_AM_I;
+	model = gda_connection_statement_execute_select_full (cnc,
+									internal_stmt[I_STMT_CHARACTER_SETS_ALL],
+									NULL, 
+									GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									_col_types_character_sets,
+									error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
@@ -265,16 +611,52 @@ _gda_firebird_meta_character_sets (GdaServerProvider *prov, GdaConnection *cnc,
 			       const GValue *chset_catalog, const GValue *chset_schema, 
 			       const GValue *chset_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+	//WHERE_AM_I;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "char_set_name"), chset_name_n, error))
+		return FALSE;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+						internal_stmt[I_STMT_CHARACTER_SETS],
+						i_set,
+						GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+						_col_types_character_sets,
+						error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
+
 }
 
 gboolean
 _gda_firebird_meta__schemata (GdaServerProvider *prov, GdaConnection *cnc, 
 			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+	//WHERE_AM_I;
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_SCHEMAS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_schemata, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
@@ -282,16 +664,81 @@ _gda_firebird_meta_schemata (GdaServerProvider *prov, GdaConnection *cnc,
 			 GdaMetaStore *store, GdaMetaContext *context, GError **error, 
 			 const GValue *catalog_name, const GValue *schema_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+	//WHERE_AM_I;
+	if (!schema_name_n) {
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_SCHEMAS],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_schemata,
+								      error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model, NULL, error, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	} else {
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_SCHEMA_NAMED],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_schemata,
+								      error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model,
+							"schema_name=##name::string",
+							error,
+							"schema", schema_name_n, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__tables_views (GdaServerProvider *prov, GdaConnection *cnc, 
 			      GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model_tables, *model_views;
+	gboolean retval;
+	//WHERE_AM_I;
+	/* Copy contents, just because we need to modify @context->table_name */
+	GdaMetaContext copy = *context;
+
+	model_tables = gda_connection_statement_execute_select_full (cnc,
+								     internal_stmt[I_STMT_TABLES_ALL],
+								     NULL,
+								     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								     _col_types_tables, error);
+	if (model_tables == NULL)
+		retval = FALSE;
+	else {
+		copy.table_name = "_tables";
+		retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
+		g_object_unref (G_OBJECT(model_tables));
+		if (retval == FALSE){g_print("\n\n***ERROR (_tables): \n\n");}
+	}
+
+	model_views = gda_connection_statement_execute_select_full (cnc,
+								    internal_stmt[I_STMT_VIEWS_ALL],
+								    NULL, 
+								    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								    _col_types_views, error);
+	if (model_views == NULL)
+		retval = FALSE;
+	else {
+		copy.table_name = "_views";
+		retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
+		g_object_unref (G_OBJECT(model_views));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR (_views): \n\n");}
+	return retval;
 }
 
 gboolean
@@ -300,16 +747,216 @@ _gda_firebird_meta_tables_views (GdaServerProvider *prov, GdaConnection *cnc,
 			     const GValue *table_catalog, const GValue *table_schema, 
 			     const GValue *table_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model_tables, *model_views;
+	gboolean retval;
+	//WHERE_AM_I;
+	
+	FirebirdConnectionData *cdata;
+	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
+	if (!cdata)
+		return FALSE;
+
+	/* Copy contents, just because we need to modify @context->table_name */
+	GdaMetaContext copy = *context;
+
+	if (!table_name_n) {
+		model_tables = gda_connection_statement_execute_select_full (cnc,
+									     internal_stmt[I_STMT_TABLES],
+									     NULL, 
+									     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									     _col_types_tables,
+									     error);
+		if (model_tables == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_tables";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
+			g_object_unref (G_OBJECT (model_tables));
+		}
+
+		if (!retval)
+			return FALSE;
+
+		model_views = gda_connection_statement_execute_select_full (cnc,
+									    internal_stmt[I_STMT_VIEWS],
+									    NULL, 
+									    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									    _col_types_views,
+									    error);
+		if (model_views == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_views";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
+			g_object_unref (G_OBJECT (model_views));
+		}
+
+	} 
+	else {
+		g_print("got to the named portion\n");
+		if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), table_name_n, error))
+			return FALSE;
+		
+		model_tables = gda_connection_statement_execute_select_full (cnc,
+									     internal_stmt[I_STMT_TABLE_NAMED],
+									     i_set, 
+									     GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									     _col_types_tables,
+									     error);
+		if (model_tables == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_tables";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_tables, error);
+			g_object_unref (G_OBJECT(model_tables));
+		}
+
+		if (!retval)
+			return FALSE;
+
+		model_views = gda_connection_statement_execute_select_full (cnc,
+									    internal_stmt[I_STMT_VIEW_NAMED],
+									    i_set, 
+									    GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+									    _col_types_views,
+									    error);
+		if (model_views == NULL)
+			retval = FALSE;
+		else {
+			copy.table_name = "_views";
+			retval = gda_meta_store_modify_with_context (store, &copy, model_views, error);
+			g_object_unref (G_OBJECT(model_views));
+		}
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
+}
+
+/*
+ * map_mysql_type_to_gda:
+ * @value: a #GValue string.
+ *
+ * It maps a mysql type to a gda type.  This means that when a
+ * mysql type is given, it will return its mapped gda type.
+ *
+ * Returns a newly created GValue string.
+ */
+static inline GValue *
+map_firebird_type_to_gda (const GValue  *value)
+{
+	const gchar *string = g_value_get_string (value);
+	GValue *newvalue;
+	const gchar *newstring;
+
+	if (strcmp (string, "blob") == 0)
+		newstring = "GdaBinary";
+	else
+	if (strcmp (string, "int64") == 0)
+		newstring = "gint64";
+	else
+	if (strcmp (string, "char") == 0)
+		newstring = "gchar";
+	else
+	if (strcmp (string, "date") == 0)
+		newstring = "GDate";
+	else
+	if (strcmp (string, "decimal") == 0)
+		newstring = "GdaNumeric";
+	else
+	if (strcmp (string, "numeric") == 0)
+		newstring = "GdaNumeric";
+	else
+	if (strcmp (string, "double") == 0)
+		newstring = "gdouble";
+	else
+	if (strcmp (string, "float") == 0)
+		newstring = "gfloat";
+	else
+	if (strcmp (string, "int") == 0)
+		newstring = "gint";
+	else
+	if (strcmp (string, "long") == 0)
+		newstring = "glong";
+	else
+	if (strcmp (string, "short") == 0)
+		newstring = "gint";
+	else
+	if (strcmp (string, "text") == 0)
+		newstring = "gchararray";
+	else
+	if (strcmp (string, "smallint") == 0)
+		newstring = "gint";
+	else
+	if (strcmp (string, "time") == 0)
+		newstring = "GdaTime";
+	else
+	if (strcmp (string, "timestamp") == 0)
+		newstring = "GdaTimestamp";
+	else
+	if (strcmp (string, "varchar") == 0)
+		newstring = "gchararray";
+	else
+	if (strcmp (string, "varying") == 0)
+		newstring = "gchararray";
+	else
+	{	
+		g_print("Please report this bug. The following data-type is not supported in the library. %s\n", string);
+		newstring = "";
+	}
+	g_value_set_string (newvalue = gda_value_new (G_TYPE_STRING), newstring);
+
+	return newvalue;
 }
 
 gboolean
 _gda_firebird_meta__columns (GdaServerProvider *prov, GdaConnection *cnc, 
 			 GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model, *proxy;
+	gboolean retval = TRUE;
+
+	//WHERE_AM_I;
+
+	/* Use a prepared statement for the "base" model. */
+	model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_COLUMNS_ALL], NULL,
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_columns, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		proxy = (GdaDataModel *) gda_data_proxy_new (model);
+		gda_data_proxy_set_sample_size ((GdaDataProxy *) proxy, 0);
+		gint n_rows = gda_data_model_get_n_rows (model);
+		gint i;
+		for (i = 0; i < n_rows; ++i) {
+			const GValue *value = gda_data_model_get_value_at (model, 7, i, error);
+			if (!value) {
+				retval = FALSE;
+				break;
+			}
+
+			GValue *newvalue = map_firebird_type_to_gda (value);
+
+			retval = gda_data_model_set_value_at (GDA_DATA_MODEL(proxy), 9, i, newvalue, error);
+			gda_value_free (newvalue);
+			if (!retval)
+				break;
+		}
+
+		if (retval) {
+			retval = gda_meta_store_modify_with_context (store, context, proxy, error);
+			if (!retval)
+				g_print("ERROR MESSAGE: \n\n%s\n\n", (*error)->message);
+		}
+
+		g_object_unref (G_OBJECT(proxy));
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
@@ -318,16 +965,87 @@ _gda_firebird_meta_columns (GdaServerProvider *prov, GdaConnection *cnc,
 			const GValue *table_catalog, const GValue *table_schema, 
 			const GValue *table_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model, *proxy;
+	gboolean retval = TRUE;
+	//WHERE_AM_I;
+	/* Use a prepared statement for the "base" model. */
+	const gchar *str;
+	str = g_value_get_string (table_name);
+	g_print("get columns for: %s\n", str);
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), table_name, error))
+		return FALSE;
+	
+	model = gda_connection_statement_execute_select_full (cnc,
+						internal_stmt[I_STMT_COLUMNS_OF_TABLE],
+						i_set,
+						GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+						_col_types_columns, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		proxy = (GdaDataModel *) gda_data_proxy_new (model);
+		gda_data_proxy_set_sample_size ((GdaDataProxy *) proxy, 0);
+		gint n_rows = gda_data_model_get_n_rows (model);
+		gint i;
+		for (i = 0; i < n_rows; ++i) {
+			const GValue *value = gda_data_model_get_value_at (model, 7, i, error);
+			if (!value) {
+				retval = FALSE;
+				break;
+			}
+
+			GValue *newvalue = map_firebird_type_to_gda (value);
+
+			retval = gda_data_model_set_value_at (GDA_DATA_MODEL(proxy), 9, i, newvalue, error);
+			gda_value_free (newvalue);
+			if (!retval)
+				break;
+		}
+
+		if (retval) {
+			retval = gda_meta_store_modify (store, context->table_name, proxy,
+							NULL,
+							error,
+							NULL);
+
+			/*
+			retval = gda_meta_store_modify (store, context->table_name, proxy,
+							"RF.RDB$RELATION_NAME = ##tblname::string",
+							error,
+							"tblname", table_name, NULL);
+			*/
+		}
+		g_object_unref (G_OBJECT(proxy));
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR (%s): %s\n\n", __FUNCTION__, (*error)->message);}
+
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__view_cols (GdaServerProvider *prov, GdaConnection *cnc, 
 			   GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	//WHERE_AM_I;
+
+	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_VIEWS_COLUMNS_ALL],
+							NULL, 
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_view_column_usage, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
@@ -336,16 +1054,51 @@ _gda_firebird_meta_view_cols (GdaServerProvider *prov, GdaConnection *cnc,
 			  const GValue *view_catalog, const GValue *view_schema, 
 			  const GValue *view_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+//WHERE_AM_I;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), view_name, error))
+		return FALSE;
+	model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_VIEWS_COLUMNS],
+							i_set, 
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_view_column_usage, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__constraints_tab (GdaServerProvider *prov, GdaConnection *cnc, 
 				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I;
+	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+						internal_stmt[I_STMT_TABLES_CONSTRAINTS_ALL],
+						NULL,
+						GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+						_col_types_table_constraints, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
+
 }
 
 gboolean
@@ -354,16 +1107,71 @@ _gda_firebird_meta_constraints_tab (GdaServerProvider *prov, GdaConnection *cnc,
 				const GValue *table_catalog, const GValue *table_schema, 
 				const GValue *table_name, const GValue *constraint_name_n)
 {
-	TO_IMPLEMENT;
+//WHERE_AM_I;
 	return TRUE;
+	GdaDataModel *model;
+	gboolean retval;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), table_name, error))
+		return FALSE;
+	if (!constraint_name_n) {
+		model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_TABLES_CONSTRAINTS],
+							i_set,
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_table_constraints, error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model,
+							"TRIM(RDB$RELATION_NAME) = ##tblname::string",
+							error,
+							"tblname", table_name, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	} else {
+		if (!gda_holder_set_value (gda_set_get_holder (i_set, "constraint_name"), constraint_name_n, error))
+			return FALSE;
+		model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_TABLES_CONSTRAINTS_NAMED],
+							i_set,
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_table_constraints, error);
+		if (model == NULL)
+			retval = FALSE;
+		else {
+			retval = gda_meta_store_modify (store, context->table_name, model,
+							"TRIM(RDB$RELATION_NAME) = ##tblname::string AND RDB$CONSTRAINT_NAME = ##constraint_name::string",
+							error,
+							"tblname", table_name, "constraint_name", constraint_name_n, NULL);
+			g_object_unref (G_OBJECT(model));
+		}
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__constraints_ref (GdaServerProvider *prov, GdaConnection *cnc, 
 				 GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I;
+	GdaDataModel *model;
+	gboolean retval;
+	model = gda_connection_statement_execute_select_full (cnc,
+						internal_stmt[I_STMT_REF_CONSTRAINTS_ALL],
+						NULL,
+						GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+						_col_types_referential_constraints, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+	return retval;
 }
 
 gboolean
@@ -372,16 +1180,57 @@ _gda_firebird_meta_constraints_ref (GdaServerProvider *prov, GdaConnection *cnc,
 				const GValue *table_catalog, const GValue *table_schema, const GValue *table_name, 
 				const GValue *constraint_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I;
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+	
+	/* Use a prepared statement for the "base" model. */
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), table_name, error))
+		return FALSE;
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "constraint_name"), constraint_name, error))
+		return FALSE;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_REF_CONSTRAINTS],
+							i_set,
+							GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_referential_constraints, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify (store, context->table_name, model,
+						"TRIM(R1.RDB$RELATION_NAME) = ##tblname::string AND C.RDB$CONSTRAINT_NAME = ##constraint_name::string",
+						error,
+						"tblname", table_name, "constraint_name", constraint_name, NULL);
+		g_object_unref (G_OBJECT(model));
+		
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__key_columns (GdaServerProvider *prov, GdaConnection *cnc, 
 			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I;
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+						internal_stmt[I_STMT_KEY_COLUMN_USAGE_ALL],
+						NULL,
+						GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+						_col_types_key_column_usage, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+	return retval;
 }
 
 gboolean
@@ -390,15 +1239,42 @@ _gda_firebird_meta_key_columns (GdaServerProvider *prov, GdaConnection *cnc,
 			    const GValue *table_catalog, const GValue *table_schema, 
 			    const GValue *table_name, const GValue *constraint_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I;
+	GdaDataModel *model;
+	gboolean retval = TRUE;
+
+	/* Use a prepared statement for the "base" model. */
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "tblname"), table_name, error))
+		return FALSE;
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "constraint_name"), constraint_name, error))
+		return FALSE;
+	model = gda_connection_statement_execute_select_full (cnc,
+							internal_stmt[I_STMT_KEY_COLUMN_USAGE],
+							i_set, GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							_col_types_key_column_usage,
+							error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify (store, context->table_name, model,
+						"TRIM(r.RDB$RELATION_NAME) = ##tblname::string AND r.rdb$constraint_name = ##constraint_name::string",
+						error,
+						"tblname", table_name, "constraint_name", constraint_name, NULL);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	if (retval == FALSE){g_print("\n\n***ERROR: %s\n\n", (*error)->message);}
+	return retval;
 }
 
 gboolean
 _gda_firebird_meta__check_columns (GdaServerProvider *prov, GdaConnection *cnc, 
 			       GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -408,7 +1284,8 @@ _gda_firebird_meta_check_columns (GdaServerProvider *prov, GdaConnection *cnc,
 			      const GValue *table_catalog, const GValue *table_schema, 
 			      const GValue *table_name, const GValue *constraint_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -416,8 +1293,25 @@ gboolean
 _gda_firebird_meta__triggers (GdaServerProvider *prov, GdaConnection *cnc, 
 			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+//WHERE_AM_I;
 	return TRUE;
+/*	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_TRIGGERS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_triggers, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
+*/
 }
 
 gboolean
@@ -426,16 +1320,55 @@ _gda_firebird_meta_triggers (GdaServerProvider *prov, GdaConnection *cnc,
 			 const GValue *table_catalog, const GValue *table_schema, 
 			 const GValue *table_name)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I; return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema, error))
+		return FALSE;
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
+		return FALSE;
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_TRIGGERS],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_triggers, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
+*/
 }
 
 gboolean
 _gda_firebird_meta__routines (GdaServerProvider *prov, GdaConnection *cnc, 
 			  GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I; return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_ROUTINES_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_routines, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
+*/
 }
 
 gboolean
@@ -444,15 +1377,46 @@ _gda_firebird_meta_routines (GdaServerProvider *prov, GdaConnection *cnc,
 			 const GValue *routine_catalog, const GValue *routine_schema, 
 			 const GValue *routine_name_n)
 {
-	TO_IMPLEMENT;
-	return TRUE;
+//WHERE_AM_I; return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "schema"), routine_schema, error))
+		return FALSE;
+	if (routine_name_n != NULL) {
+ 		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), routine_name_n, error))
+			return FALSE;
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_ROUTINES_ONE],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_routines, error);
+	}
+	else
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_ROUTINES],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_routines, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
+*/
 }
 
 gboolean
 _gda_firebird_meta__routine_col (GdaServerProvider *prov, GdaConnection *cnc, 
 			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -462,7 +1426,8 @@ _gda_firebird_meta_routine_col (GdaServerProvider *prov, GdaConnection *cnc,
 			    const GValue *rout_catalog, const GValue *rout_schema, 
 			    const GValue *rout_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -470,7 +1435,8 @@ gboolean
 _gda_firebird_meta__routine_par (GdaServerProvider *prov, GdaConnection *cnc, 
 			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+	//TO_IMPLEMENT;
 	return TRUE;
 }
 
@@ -480,6 +1446,138 @@ _gda_firebird_meta_routine_par (GdaServerProvider *prov, GdaConnection *cnc,
 			    const GValue *rout_catalog, const GValue *rout_schema, 
 			    const GValue *rout_name)
 {
-	TO_IMPLEMENT;
+	//WHERE_AM_I;
+	//TO_IMPLEMENT;
 	return TRUE;
 }
+
+gboolean
+_gda_firebird_meta__indexes_tab (G_GNUC_UNUSED GdaServerProvider *prov, GdaConnection *cnc,
+			      GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+//WHERE_AM_I;
+	return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_INDEXES_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_table_indexes, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
+*/
+}
+
+gboolean
+_gda_firebird_meta_indexes_tab (G_GNUC_UNUSED GdaServerProvider *prov, GdaConnection *cnc,
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			     G_GNUC_UNUSED const GValue *table_catalog, const GValue *table_schema,
+			     const GValue *table_name, const GValue *index_name_n)
+{
+//WHERE_AM_I;
+	return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "schema"), table_schema, error))
+		return FALSE;
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
+		return FALSE;
+	if (index_name_n) {
+		if (!gda_holder_set_value (gda_set_get_holder (i_set, "name2"), index_name_n, error))
+			return FALSE;
+		model = gda_connection_statement_execute_select_full (cnc,
+								      internal_stmt[I_STMT_INDEXES_ONE],
+								      i_set,
+								      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+								      _col_types_table_indexes, error);
+	}
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_INDEXES_TABLE],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_table_indexes, error);
+
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		gda_meta_store_set_reserved_keywords_func (store,
+							   _gda_mysql_reuseable_get_reserved_keywords_func
+							   ((GdaProviderReuseable*) rdata));
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
+*/
+}
+
+gboolean
+_gda_firebird_meta__index_cols (G_GNUC_UNUSED GdaServerProvider *prov, GdaConnection *cnc,
+			     GdaMetaStore *store, GdaMetaContext *context, GError **error)
+{
+//WHERE_AM_I; return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_INDEX_COLUMNS_ALL],
+							      NULL,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_index_column_usage, error);
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+	}
+
+	return retval;
+*/
+}
+
+gboolean
+_gda_firebird_meta_index_cols (G_GNUC_UNUSED GdaServerProvider *prov, GdaConnection *cnc,
+			    GdaMetaStore *store, GdaMetaContext *context, GError **error,
+			    G_GNUC_UNUSED const GValue *table_catalog, const GValue *table_schema,
+			    const GValue *table_name, const GValue *index_name)
+{
+//WHERE_AM_I; return TRUE;
+/*
+	GdaDataModel *model;
+	gboolean retval;
+
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name"), table_name, error))
+		return FALSE;
+	if (!gda_holder_set_value (gda_set_get_holder (i_set, "name2"), index_name, error))
+		return FALSE;
+	model = gda_connection_statement_execute_select_full (cnc,
+							      internal_stmt[I_STMT_INDEX_COLUMNS_NAMED],
+							      i_set,
+							      GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+							      _col_types_index_column_usage, error);
+
+	if (model == NULL)
+		retval = FALSE;
+	else {
+		retval = gda_meta_store_modify_with_context (store, context, model, error);
+		g_object_unref (G_OBJECT(model));
+
+	}
+
+	return retval;
+*/
+}
+
diff --git a/providers/firebird/gda-firebird-meta.h b/providers/firebird/gda-firebird-meta.h
index dd44cf2..d7dbdca 100644
--- a/providers/firebird/gda-firebird-meta.h
+++ b/providers/firebird/gda-firebird-meta.h
@@ -188,7 +188,21 @@ gboolean _gda_firebird_meta_routine_par      (GdaServerProvider *prov, GdaConnec
 					  const GValue *rout_catalog, const GValue *rout_schema, 
 					  const GValue *rout_name);
 
-
+/* _table_indexes */
+gboolean _gda_firebird_meta__indexes_tab     (GdaServerProvider *prov, GdaConnection *cnc, 
+					   GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_indexes_tab      (GdaServerProvider *prov, GdaConnection *cnc, 
+					   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					   const GValue *table_catalog, const GValue *table_schema, const GValue *table_name,
+					   const GValue *index_name_n);
+
+/* _index_column_usage */
+gboolean _gda_firebird_meta__index_cols      (GdaServerProvider *prov, GdaConnection *cnc, 
+					   GdaMetaStore *store, GdaMetaContext *context, GError **error);
+gboolean _gda_firebird_meta_index_cols       (GdaServerProvider *prov, GdaConnection *cnc, 
+					   GdaMetaStore *store, GdaMetaContext *context, GError **error,
+					   const GValue *table_catalog, const GValue *table_schema,
+					   const GValue *table_name, const GValue *index_name);
 G_END_DECLS
 
 #endif
diff --git a/providers/firebird/gda-firebird-provider.c b/providers/firebird/gda-firebird-provider.c
index 33f13b3..3397f26 100644
--- a/providers/firebird/gda-firebird-provider.c
+++ b/providers/firebird/gda-firebird-provider.c
@@ -44,6 +44,8 @@
 #include "gda-firebird-util.h"
 #define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
+#define FILE_EXTENSION ".fdb"
+
 /*
  * GObject methods
  */
@@ -127,7 +129,7 @@ static GObject             *gda_firebird_provider_statement_execute (GdaServerPr
 								     GType *col_types,
 								     GdaSet **last_inserted_row,
 								     guint *task_id,
-								     GdaServerProviderAsyncCallback async_cb,
+								     GdaServerProviderExecCallback async_cb,
 								     gpointer cb_data, GError **error);
 
 /* distributed transactions */
@@ -162,6 +164,16 @@ static void gda_firebird_free_cnc_data (FirebirdConnectionData *cdata);
 
 static gchar	*fb_server_get_version (FirebirdConnectionData *fcnc);
 
+
+static gchar * firebird_render_operation (GdaSqlOperation *op, GdaSqlRenderingContext *context, GError **error);
+
+static gchar * firebird_render_compound (GdaSqlStatementCompound *stmt, GdaSqlRenderingContext *context, GError **error);
+
+static gchar * firebird_render_expr (GdaSqlExpr *expr, GdaSqlRenderingContext *context, gboolean *is_default, gboolean *is_null, GError **error);
+
+
+
+
 /*
  * Prepared internal statements
  * TO_ADD: any prepared statement to be used internally by the provider should be
@@ -174,7 +186,7 @@ typedef enum {
 } InternalStatementItem;
 
 gchar *internal_sql[] = {
-	"SQL for INTERNAL_STMT1"
+	"SQL 'firebird' FROM RDB$DATABASE"
 };
 
 /*
@@ -263,17 +275,21 @@ gda_firebird_provider_class_init (GdaFirebirdProviderClass *klass)
 	provider_class->meta_funcs.routine_col = _gda_firebird_meta_routine_col;
 	provider_class->meta_funcs._routine_par = _gda_firebird_meta__routine_par;
 	provider_class->meta_funcs.routine_par = _gda_firebird_meta_routine_par;
+	provider_class->meta_funcs._indexes_tab = _gda_firebird_meta__indexes_tab;
+	provider_class->meta_funcs.indexes_tab = _gda_firebird_meta_indexes_tab;
+	provider_class->meta_funcs._index_cols = _gda_firebird_meta__index_cols;
+	provider_class->meta_funcs.index_cols = _gda_firebird_meta_index_cols;
 
 	/* distributed transactions: if not supported, then provider_class->xa_funcs should be set to NULL */
 	provider_class->xa_funcs = NULL;
 	/*
-	provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
-	provider_class->xa_funcs->xa_start = gda_firebird_provider_xa_start;
-	provider_class->xa_funcs->xa_end = gda_firebird_provider_xa_end;
-	provider_class->xa_funcs->xa_prepare = gda_firebird_provider_xa_prepare;
-	provider_class->xa_funcs->xa_commit = gda_firebird_provider_xa_commit;
-	provider_class->xa_funcs->xa_rollback = gda_firebird_provider_xa_rollback;
-	provider_class->xa_funcs->xa_recover = gda_firebird_provider_xa_recover;
+	  provider_class->xa_funcs = g_new0 (GdaServerProviderXa, 1);
+	  provider_class->xa_funcs->xa_start = gda_firebird_provider_xa_start;
+	  provider_class->xa_funcs->xa_end = gda_firebird_provider_xa_end;
+	  provider_class->xa_funcs->xa_prepare = gda_firebird_provider_xa_prepare;
+	  provider_class->xa_funcs->xa_commit = gda_firebird_provider_xa_commit;
+	  provider_class->xa_funcs->xa_rollback = gda_firebird_provider_xa_rollback;
+	  provider_class->xa_funcs->xa_recover = gda_firebird_provider_xa_recover;
 	*/
 }
 
@@ -315,9 +331,9 @@ gda_firebird_provider_get_type (void)
 		g_static_mutex_lock (&registering);
 		if (type == 0) {
 #ifdef FIREBIRD_EMBED
-		type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaFirebirdProviderEmbed", &info, 0);
+			type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaFirebirdProviderEmbed", &info, 0);
 #else
-		type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaFirebirdProvider", &info, 0);
+			type = g_type_register_static (GDA_TYPE_SERVER_PROVIDER, "GdaFirebirdProvider", &info, 0);
 #endif
 		}
 		g_static_mutex_unlock (&registering);
@@ -361,82 +377,116 @@ gda_firebird_provider_open_connection (GdaServerProvider *provider, GdaConnectio
 				       GdaQuarkList *params, GdaQuarkList *auth,
 				       guint *task_id, GdaServerProviderAsyncCallback async_cb, gpointer cb_data)
 {
-	g_print("Attempting to open Firebird DB connection\n");
 	g_return_val_if_fail (GDA_IS_FIREBIRD_PROVIDER (provider), FALSE);
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 
 	/* If asynchronous connection opening is not supported, then exit now */
 	if (async_cb) {
 		gda_connection_add_event_string (cnc, _("Provider does not support asynchronous connection open"));
-                return FALSE;
+		return FALSE;
 	}
 
 	/* Check for connection parameters */
-	const gchar *fb_db, *fb_user, *fb_password, *fb_charset;
+	const gchar *fb_db, *fb_dir, *fb_user, *fb_password, *fb_host;
+	gchar *fb_conn;
+	
 	fb_db = (gchar *) gda_quark_list_find (params, "DB_NAME");
-        if (!fb_db) {
-                gda_connection_add_event_string (cnc,
-						 _("The connection string must contain the DB_NAME values"));
-                return FALSE;
-        }
-        fb_charset = (gchar *) gda_quark_list_find (params, "CHARACTER_SET");
-
-	fb_user = (gchar *) gda_quark_list_find (auth, "USERNAME");
+	fb_dir = (gchar *) gda_quark_list_find (params, "DB_DIR");
+	fb_host	= (gchar *) gda_quark_list_find (params, "HOST");
+	fb_user	= (gchar *) gda_quark_list_find (auth, "USERNAME");
 	fb_password = (gchar *) gda_quark_list_find (auth, "PASSWORD");
 	
-	/* Create a new instance of the provider specific data associated to a connection (FirebirdConnectionData),
-	 * and set its contents, and open the real connection to the database */
-	FirebirdConnectionData *cdata;
-        gchar *dpb;
-
-	cdata = g_new0 (FirebirdConnectionData, 1);
-
-	/* Initialize dpb_buffer */
-        dpb = cdata->dpb_buffer;
-        *dpb++ = isc_dpb_version1;
+	if (!fb_db) {
+		gda_connection_add_event_string (cnc, "%s", _("The connection string must contain the DB_NAME values"));
+		return FALSE;
+	}
+	if (!fb_dir)
+		fb_dir = ".";
+			
+	/* prepare DPB */
+	GString *dpb_string;
+	dpb_string = g_string_new ("");
+	g_string_append_c (dpb_string, isc_dpb_version1);
+
+	/* Set user name */
+	if (fb_user) {
+		size_t len;
+		len = strlen (fb_user);
+		if (len > 256) {
+			gda_connection_add_event_string (cnc, _("The parameter '%s' is too long"), "USERNAME");
+			g_string_free (dpb_string, TRUE);
+			return FALSE;
+		}
+		g_string_append_c (dpb_string, isc_dpb_user_name);
+		g_string_append_c (dpb_string, len);
+		g_string_append (dpb_string, fb_user);
+	}
 
-        /* Set user name */
-        if (fb_user) {
-                *dpb++ = isc_dpb_user_name;
-                *dpb++ = strlen (fb_user);
-                strcpy (dpb, fb_user);
-                dpb += strlen (fb_user);
-        }
+	/* Set password */
+	if (fb_password) {
+		size_t len;
+		len = strlen (fb_password);
+		if (len > 256) {
+			gda_connection_add_event_string (cnc, _("The parameter '%s' is too long"), "PASSWORD");
+			g_string_free (dpb_string, TRUE);
+			return FALSE;
+		}
+		g_string_append_c (dpb_string, isc_dpb_password);
+		g_string_append_c (dpb_string, len);
+		g_string_append (dpb_string, fb_password);
+		
+	}
 
-        /* Set password */
-        if (fb_password) {
-                *dpb++ = isc_dpb_password;
-                *dpb++ = strlen (fb_password);
-                strcpy (dpb, fb_password);
-                dpb += strlen (fb_password);
-        }
+	/* Set character set */
+	g_string_append_c (dpb_string, isc_dpb_lc_ctype);
+	g_string_append_c (dpb_string, strlen ("UTF8"));
+	g_string_append (dpb_string, "UTF8");
 
-        /* Set character set */
-        if (fb_charset) {
-                *dpb++ = isc_dpb_lc_ctype;
-                *dpb++ = strlen (fb_charset);
-                strcpy (dpb, fb_charset);
-                dpb += strlen (fb_charset);
-        }
-
-        /* Save dpb length */
-        cdata->dpb_length = dpb - cdata->dpb_buffer;
+	if (fb_host)
+		fb_conn = g_strconcat (fb_host, ":", fb_db, NULL);
+	else {
+		gchar *tmp;
+		tmp = g_strdup_printf ("%s%s", fb_db, FILE_EXTENSION);
+		fb_conn = g_build_filename (fb_dir, tmp, NULL);
+		g_free (tmp);
+
+		if (! g_file_test (fb_conn, G_FILE_TEST_EXISTS)) {
+			g_free (fb_conn);
+			fb_conn = g_build_filename (fb_dir, fb_db, NULL);
+		}
+	}
 
-	if (isc_attach_database (cdata->status, strlen (fb_db), fb_db, &(cdata->handle), cdata->dpb_length,
-                                 cdata->dpb_buffer)) {
-		gda_firebird_free_cnc_data (cdata);
-		gda_connection_add_event_string (cnc, 
-						 _("Failed to connect to the database"));
-		//g_print("Failed to connect to the database\n");
+	ISC_STATUS_ARRAY status_vector;
+	isc_db_handle handle = 0L;
+	if (isc_attach_database (status_vector, strlen (fb_conn), fb_conn, &handle,
+				 dpb_string->len, dpb_string->str)) {
+		ISC_SCHAR *msg;
+		const ISC_STATUS *p = status_vector;
+		GdaConnectionEvent *ev;
+
+		msg = g_new0 (ISC_SCHAR, 512);
+		fb_interpret (msg, 511, &p);
+		ev = gda_connection_add_event_string (cnc, "%s", msg);
+		g_free (msg);
+		gda_connection_event_set_code (ev, isc_sqlcode (status_vector));
+
+		g_free (fb_conn);
+		g_string_free (dpb_string, TRUE);
 		return FALSE;
 	}
 
-	/* connection is now opened */
-	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_firebird_free_cnc_data);
-	 
-	cdata->dbname = g_strdup (fb_db);
+	/* connection is now opened:
+	 * Create a new instance of the provider specific data associated to a connection (FirebirdConnectionData),
+	 * and set its contents, and open the real connection to the database */
+	FirebirdConnectionData *cdata;
+	cdata = g_new0 (FirebirdConnectionData, 1);
+	cdata->handle = handle;
+	cdata->dpb = g_string_free (dpb_string, FALSE);
+	cdata->dbname = fb_conn;
 	cdata->server_version = fb_server_get_version (cdata);
 
+	gda_connection_internal_set_provider_data (cnc, cdata, (GDestroyNotify) gda_firebird_free_cnc_data);
+	
 	return TRUE;
 }
 
@@ -464,6 +514,7 @@ gda_firebird_provider_close_connection (GdaServerProvider *provider, GdaConnecti
 
 	/* detach from database */
 	isc_detach_database (cdata->status, &(cdata->handle));
+	cdata->handle = 0L;
 
 	/* Free the FirebirdConnectionData structure and its contents*/
 	gda_firebird_free_cnc_data (cdata);
@@ -727,7 +778,7 @@ gda_firebird_provider_begin_transaction (GdaServerProvider *provider,
 	/* start the transaction */
 	cdata->ftr = g_new0 (isc_tr_handle, 1);
 	if (isc_start_transaction (cdata->status, (cdata->ftr), 1, &(cdata->handle),
-				(unsigned short) sizeof (tpb), &tpb)) {
+				   (unsigned short) sizeof (tpb), &tpb)) {
 		_gda_firebird_make_error (cnc, 0);
 		g_free (cdata->ftr);
 		cdata->ftr = NULL;
@@ -757,24 +808,24 @@ gda_firebird_provider_commit_transaction (GdaServerProvider *provider, GdaConnec
 	if (!cdata) 
 		return FALSE;
 
-        if (!cdata->ftr) {
-                gda_connection_add_event_string (cnc, _("Invalid transaction handle"));
-                return FALSE;
-        }
+	if (!cdata->ftr) {
+		gda_connection_add_event_string (cnc, _("Invalid transaction handle"));
+		return FALSE;
+	}
 
-        if (isc_commit_transaction (cdata->status, cdata->ftr)) {
+	if (isc_commit_transaction (cdata->status, cdata->ftr)) {
 		_gda_firebird_make_error (cnc, 0);
-                result = FALSE;
-        }
-        else {
-                gda_connection_internal_transaction_committed (cnc, name);
-                result = TRUE;
-        }
+		result = FALSE;
+	}
+	else {
+		gda_connection_internal_transaction_committed (cnc, name);
+		result = TRUE;
+	}
 
-        g_free (cdata->ftr);
+	g_free (cdata->ftr);
 	cdata->ftr = NULL;
 
-        return result;
+	return result;
 }
 
 /*
@@ -786,7 +837,7 @@ gda_firebird_provider_rollback_transaction (GdaServerProvider *provider, GdaConn
 {
 	FirebirdConnectionData *cdata;
 	gboolean result = FALSE;
-
+	//WHERE_AM_I;
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, FALSE);
 
@@ -973,7 +1024,7 @@ gda_firebird_provider_get_default_dbms_type (GdaServerProvider *provider, GdaCon
 		return "blob";
 
 	if (type == G_TYPE_BOOLEAN)
-		return "boolean";
+		return "smallint";
 	
 	if ((type == G_TYPE_DATE) || 
 	    (type == GDA_TYPE_GEOMETRIC_POINT) ||
@@ -986,7 +1037,7 @@ gda_firebird_provider_get_default_dbms_type (GdaServerProvider *provider, GdaCon
 	if ((type == G_TYPE_DOUBLE) ||
 	    (type == GDA_TYPE_NUMERIC) ||
 	    (type == G_TYPE_FLOAT))
-		return "real";
+		return "double";
 	
 	if (type == GDA_TYPE_TIME)
 		return "time";
@@ -1029,6 +1080,9 @@ gda_firebird_provider_statement_to_sql (GdaServerProvider *provider, GdaConnecti
 					GdaStatement *stmt, GdaSet *params, GdaStatementSqlFlag flags,
 					GSList **params_used, GError **error)
 {
+	//gchar *str;
+	//GdaSqlRenderingContext context;
+	
 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), NULL);
 	if (cnc) {
 		g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
@@ -1038,6 +1092,13 @@ gda_firebird_provider_statement_to_sql (GdaServerProvider *provider, GdaConnecti
 	return gda_statement_to_sql_extended (stmt, cnc, params, flags, params_used, error);
 }
 
+
+/*
+ * Statement prepare request
+ */
+static GdaFirebirdPStmt *real_prepare (GdaServerProvider *provider, GdaConnection *cnc, GdaStatement *stmt, GError **error);
+
+
 /*
  * Statement prepare request
  *
@@ -1049,9 +1110,9 @@ static gboolean
 gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnection *cnc,
 					 GdaStatement *stmt, GError **error)
 {
-	GdaFirebirdPStmt 		*ps;
+	GdaFirebirdPStmt *ps;
 	FirebirdConnectionData	*cdata;
-	gboolean				result = FALSE;
+	gboolean result = FALSE;
 
 	int            buffer[2048];
 
@@ -1068,25 +1129,24 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 	g_return_val_if_fail (GDA_IS_STATEMENT (stmt), FALSE);
 
 	/* fetch prepares stmt if already done */
-	ps = (GdaFirebirdPStmt *)gda_connection_get_prepared_statement (cnc, stmt);
+	ps = (GdaFirebirdPStmt *) gda_connection_get_prepared_statement (cnc, stmt);
 	if (ps)
 		return TRUE;
 
 	/* render as SQL understood by Firebird */
-	GdaSet *params		= NULL;
-	gchar *sql			= NULL;
-	GSList *used_params	= NULL;
-	g_print("gda_statement_get_parameters\n\n");
+	GdaSet *params = NULL;
+	gchar *sql = NULL;
+	GSList *used_params = NULL;
+	gboolean trans_started = FALSE;
+
 	if (!gda_statement_get_parameters (stmt, &params, error))
 		goto out_err;
 
-	g_print("gda_firebird_provider_statement_to_sql\n");
-	sql = gda_firebird_provider_statement_to_sql (provider, NULL, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_COLON,
-						&used_params, error);
+	sql = gda_firebird_provider_statement_to_sql (provider, NULL, stmt, params, GDA_STATEMENT_SQL_PARAMS_AS_UQMARK,
+						      &used_params, error);
 	if (!sql)
 		goto out_err;
 
-	g_print("Now get the internal FB-connection\n");
 	/* get private connection data */
 	cdata = (FirebirdConnectionData *) gda_connection_internal_get_provider_data (cnc);
 	if (!cdata)
@@ -1094,44 +1154,32 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 
 	/* create the stmt object */
 	ps = (GdaFirebirdPStmt *) g_object_new (GDA_TYPE_FIREBIRD_PSTMT, NULL);
-	ps->stmt_h = 0;
+	ps->stmt_h = 0L;
 
-	g_print("isc_dsql_allocate_statement\n\n");
 	/* actually prepare statement */
-	if (isc_dsql_allocate_statement(cdata->status, &(cdata->handle), &(ps->stmt_h)))
+	if (isc_dsql_allocate_statement (cdata->status, &(cdata->handle), &(ps->stmt_h)))
 		goto out_err;
 
-
-	g_print("Check if we have a transaction.\n\n");
-	if (NULL == cdata->ftr) {
-		g_print("Begin a transaction.\n");
-
-		if (!gda_firebird_provider_begin_transaction (provider
-					, cnc
-					, "prepare_tr"
-					, GDA_TRANSACTION_ISOLATION_UNKNOWN
-					, error)){
-			g_print("Could not start a transaction.\n");
-			isc_print_status(cdata->status);
-			g_print("\n");
+	if (! cdata->ftr) {
+		if (!gda_firebird_provider_begin_transaction (provider, cnc, "prepare_tr",
+							      GDA_TRANSACTION_ISOLATION_UNKNOWN, error))
 			goto out_err;
-		}
+		trans_started = TRUE;
 	}
-	if (NULL == ps->sqlda){
+
+	if (! ps->sqlda){
 		/* 
 		 * Allocate enough space for 20 fields.  
 		 * If more fields get selected, re-allocate SQLDA later.
 		 */
-		ps->sqlda			= g_new0(XSQLDA, 1);
-		ps->sqlda->sqln		= 1;
-		ps->sqlda->version	= 1;
+		ps->sqlda = (XSQLDA *) g_malloc (XSQLDA_LENGTH(20)); //g_new0(XSQLDA, 20);
+		ps->sqlda->sqln	= 20;
+		ps->sqlda->version = SQLDA_VERSION1;
 	}
-	g_print("isc_dsql_prepare\n");
 
 	/* now prepare the fb statement */
-	if (isc_dsql_prepare(cdata->status, (cdata->ftr), &(ps->stmt_h), 0, sql, SQL_DIALECT_V6, ps->sqlda)){
-		//gda_connection_add_event_string (cnc, _("Could not prepare the FB statement"));
-		g_print("Failed to prepare the statement.\n");
+	if (isc_dsql_prepare (cdata->status, cdata->ftr, &(ps->stmt_h), 0, sql, SQL_DIALECT_CURRENT, ps->sqlda)) {
+		_gda_firebird_make_error (cnc, 0);
 		goto out_err;
 	}
 
@@ -1143,10 +1191,10 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 	 * two bytes of length, and a statement_type token.
 	 */
 
-	if (!isc_dsql_sql_info(cdata->status, &(ps->stmt_h), sizeof (stmt_info), stmt_info,
-			       sizeof (info_buffer), info_buffer)) {
-		l = (short) isc_vax_integer((char *) info_buffer + 1, 2);
-		ps->statement_type = isc_vax_integer((char *) info_buffer + 3, l);
+	if (!isc_dsql_sql_info (cdata->status, &(ps->stmt_h), sizeof (stmt_info), stmt_info,
+				sizeof (info_buffer), info_buffer)) {
+		l = (short) isc_vax_integer ((char *) info_buffer + 1, 2);
+		ps->statement_type = isc_vax_integer ((char *) info_buffer + 3, l);
 	}
 
 	ps->is_non_select = !ps->sqlda->sqld;
@@ -1159,26 +1207,23 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 		num_cols = ps->sqlda->sqld;
 
 		/* Need more room. */
-		if (ps->sqlda->sqln < num_cols)
-		{
-			g_free(ps->sqlda);
-			ps->sqlda			= g_new0(XSQLDA, num_cols);
-			ps->sqlda->sqln		= num_cols;
-			ps->sqlda->version	= 1;
-
-			if (isc_dsql_describe(cdata->status, &(ps->stmt_h), SQL_DIALECT_V6, ps->sqlda))
-			{
+		if (ps->sqlda->sqln < num_cols)	{
+			//g_print("Only have space for %d columns, need to re-allocate more space for %d columns\n", ps->sqlda->sqln, ps->sqlda->sqld );
+			g_free (ps->sqlda);
+			ps->sqlda = (XSQLDA *) g_malloc(XSQLDA_LENGTH(num_cols)); //g_new0(XSQLDA, num_cols);
+			ps->sqlda->sqln	= num_cols;
+			ps->sqlda->version = SQLDA_VERSION1;
+
+			if (isc_dsql_describe (cdata->status, &(ps->stmt_h), SQL_DIALECT_V6, ps->sqlda))
 				goto out_err;
-			}
-
 			num_cols = ps->sqlda->sqld;
 		}
 
 		/*
 		 * Set up SQLDA.
 		 */
-		for (var = ps->sqlda->sqlvar, offset = 0, i = 0; i < num_cols; var++, i++)
-		{
+		//g_print("set up SQLDA\n");
+		for (var = ps->sqlda->sqlvar, offset = 0, i = 0; i < num_cols; var++, i++) {
 			length = alignment = var->sqllen;
 			type = var->sqltype & ~1;
 			var->sqlname[var->sqlname_length + 1] = '\0';
@@ -1188,72 +1233,110 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 
 			if (type == SQL_TEXT)
 				alignment = 1;
-			else if (type == SQL_VARYING)
-			{
+			else if (type == SQL_VARYING) {
 				length += sizeof (short) + 1;
 				alignment = sizeof (short);
 			}
+
 			/*  RISC machines are finicky about word alignment
 			 *  So the output buffer values must be placed on
 			 *  word boundaries where appropriate
 			 */
-			offset			= FB_ALIGN(offset, alignment);
-			var->sqldata	= (char *) buffer + offset;
-			offset			+= length;
-			offset			= FB_ALIGN(offset, sizeof (short));
-			var->sqlind		= (short*) ((char *) buffer + offset);
-			offset			+= sizeof  (short);
+			gchar *buff = g_new0(gchar, 2048);
+
+			offset = FB_ALIGN(offset, alignment);
+			var->sqldata = (char *) buff + offset;
+			offset += length;
+			offset = FB_ALIGN(offset, sizeof (short));
+			var->sqlind = (short*) ((char *) buff + offset);
+			offset += sizeof (short);
 		}
 	}
 
-	/* prepare @stmt using the C API, creates @ps */
+	//SETUP INPUT-SQLDA
+	//NOW ALLOCATE SPACE FOR THE INPUT PARAMETERS
+	if (ps->input_sqlda)
+		g_free(ps->input_sqlda);
+
+	ps->input_sqlda	= (XSQLDA *) g_new0(XSQLDA, 1);
+	ps->input_sqlda->version = SQLDA_VERSION1;
+	ps->input_sqlda->sqln = 1;
+	
+	isc_dsql_describe_bind(cdata->status, &(ps->stmt_h), 1, ps->input_sqlda);
+
+	if ((cdata->status[0] == 1) && cdata->status[1]){
+		// Process error
+		isc_print_status (cdata->status);
+		goto out_err;
+	}
+
+	if (ps->input_sqlda->sqld > ps->input_sqlda->sqln){
+		gint n = ps->input_sqlda->sqld;
+		g_free(ps->input_sqlda);
+		ps->input_sqlda	= (XSQLDA *) g_new0(XSQLDA, n);
+		ps->input_sqlda->sqln= n;
+		ps->input_sqlda->version = SQLDA_VERSION1;
+
+		isc_dsql_describe_bind(cdata->status, &(ps->stmt_h), n, ps->input_sqlda);
+	
+		if ((cdata->status[0] == 1) && cdata->status[1]){
+			// Process error
+			isc_print_status(cdata->status);
+			goto out_err;
+		}
+	}
+
+	if (!params){
+		/* no input paramaters so clear the input_sqlda */
+		g_free (ps->input_sqlda);
+		ps->input_sqlda = NULL;
+	}
+
 	/* make a list of the parameter names used in the statement */
 	GSList *param_ids = NULL;
 	if (used_params) {
 		GSList *list;
 		for (list = used_params; list; list = list->next) {
-				const gchar *cid;
-				cid = gda_holder_get_id (GDA_HOLDER (list->data));
-				if (cid) {
-					param_ids = g_slist_append (param_ids, g_strdup (cid));
-					//g_print ("PostgreSQL's PREPARATION: param ID: %s\n", cid);
-				}
-				else {
-					g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
-						"%s", _("Unnamed parameter is not allowed in prepared statements"));
-					g_slist_foreach (param_ids, (GFunc) g_free, NULL);
-					g_slist_free (param_ids);
-					goto out_err;
-				}
+			const gchar *cid;
+			cid = gda_holder_get_id (GDA_HOLDER (list->data));
+			if (cid) {
+				param_ids = g_slist_append (param_ids, g_strdup (cid));
+			}
+			else {
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_PREPARE_STMT_ERROR,
+					     "%s", _("Unnamed parameter is not allowed in prepared statements"));
+				g_slist_foreach (param_ids, (GFunc) g_free, NULL);
+				g_slist_free (param_ids);
+				goto out_err;
+			}
 		}
+
+		g_slist_free (used_params);
 	}
 
-	g_print("Adding the prepared statement to GDA.\n");
+
+	/* create a prepared statement */
+	//g_print("Adding the prepared statement to GDA.\n");
 	//ps = (GdaFirebirdPStmt *) g_object_new (GDA_TYPE_FIREBIRD_PSTMT, NULL);
 	gda_pstmt_set_gda_statement (_GDA_PSTMT (ps), stmt);
 	_GDA_PSTMT (ps)->param_ids = param_ids;
 	_GDA_PSTMT (ps)->sql = sql;
 
 	gda_connection_add_prepared_statement (cnc, stmt, (GdaPStmt *) ps);
-	g_object_unref (ps);
-
-	/* create a prepared statement */
-
+	//g_object_unref (ps);
+	
 	result  = TRUE;
 
  out_err:
- 	if (FALSE == result){
-		g_print("ERROR OCCURED!!!\n");
-		isc_print_status(cdata->status);
-		g_print("\n");
-
-		if (used_params)
-			g_slist_free (used_params);
-		if (params)
-			g_object_unref (params);
-
+ 	if (!result){
+		if (trans_started)
+			gda_firebird_provider_rollback_transaction (provider, cnc, "prepare_tr", NULL);
 		g_free (sql);
 	}
+	
+	if (params)
+		g_object_unref (params);
+	
 	return result;
 }
 
@@ -1273,18 +1356,20 @@ gda_firebird_provider_statement_prepare (GdaServerProvider *provider, GdaConnect
 static GObject *
 gda_firebird_provider_statement_execute (GdaServerProvider *provider,
 					 GdaConnection *cnc,
-					 GdaStatement *stmt, GdaSet *params,
+					 GdaStatement *stmt, 
+					 GdaSet *params,
 					 GdaStatementModelUsage model_usage,
 					 GType *col_types,
 					 GdaSet **last_inserted_row,
 					 guint *task_id,
-					 GdaServerProviderAsyncCallback async_cb,
+					 GdaServerProviderExecCallback async_cb,
 					 gpointer cb_data,
 					 GError **error)
 {
-	GdaFirebirdPStmt *ps;
-	FirebirdConnectionData *cdata;
-	gchar *sql;
+	GdaFirebirdPStmt	*ps;
+	FirebirdConnectionData	*cdata;
+	GSList			*mem_to_free = NULL;
+	XSQLVAR			*fbvar;
 
 	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 	g_return_val_if_fail (gda_connection_get_provider (cnc) == provider, NULL);
@@ -1294,17 +1379,17 @@ gda_firebird_provider_statement_execute (GdaServerProvider *provider,
 	if (async_cb) {
 		g_set_error (error, GDA_SERVER_PROVIDER_ERROR, GDA_SERVER_PROVIDER_METHOD_NON_IMPLEMENTED_ERROR,
 			     "%s", _("Provider does not support asynchronous statement execution"));
-                return FALSE;
+		return FALSE;
 	}
 
 	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data_error (cnc, error);
 	if (!cdata) 
 		return FALSE;
 
-
 	/* get/create new prepared statement */
 	ps = (GdaFirebirdPStmt *)gda_connection_get_prepared_statement (cnc, stmt);
 	if (!ps) {
+		g_print("prepare statement in execute stage\n");
 		if (!gda_firebird_provider_statement_prepare (provider, cnc, stmt, NULL)) {
 			/* this case can appear for example if some variables are used in places
 			 * where the C API cannot allow them (for example if the variable is the table name
@@ -1315,22 +1400,23 @@ gda_firebird_provider_statement_execute (GdaServerProvider *provider,
 			//TO_IMPLEMENT;
 			return NULL;
 		}
-		else
-			ps = (GdaFirebirdPStmt *)gda_connection_get_prepared_statement (cnc, stmt);
+		
+		ps = (GdaFirebirdPStmt *)gda_connection_get_prepared_statement (cnc, stmt);
 	}
+	g_object_ref(ps);
 	g_assert (ps);
 
 	/* optionnally reset the prepared statement if required by the API */
-	//TO_IMPLEMENT;
-	
+
 	/* bind statement's parameters */
 	GSList *list;
 	GdaConnectionEvent *event = NULL;
 	int i;
+
 	for (i = 1, list = _GDA_PSTMT (ps)->param_ids; list; list = list->next, i++) {
 		const gchar *pname = (gchar *) list->data;
 		GdaHolder *h;
-		
+		g_print("binding paramater %s\n", pname);
 		/* find requested parameter */
 		if (!params) {
 			event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
@@ -1361,9 +1447,278 @@ gda_firebird_provider_statement_execute (GdaServerProvider *provider,
 		}
 
 		/* actual binding using the C API, for parameter at position @i */
-		//TODO: Not sure how this should be done right now.
-		//const GValue *value = gda_holder_get_value (h);
-		//TO_IMPLEMENT;
+		if (ps->input_sqlda == NULL) continue;
+		
+		g_print("bind the value to SQLDA\n");
+		const GValue* value = gda_holder_get_value (h);
+		
+		fbvar = &(ps->input_sqlda->sqlvar[i-1]);
+		if (!value || gda_value_is_null (value)) {
+			gint *flag0 = g_new0 (gint, 1);
+			mem_to_free = g_slist_prepend (mem_to_free, flag0);
+			
+			fbvar->sqlind = flag0; //TELLS FIREBIRD THAT THE COLUMN IS NULL
+			flag0 = -1; //TELLS FIREBIRD THAT THE COLUMN IS NULL
+		}
+		else if (G_VALUE_TYPE (value) == GDA_TYPE_TIMESTAMP) {
+			/*
+			  const GdaTimestamp *ts;
+
+			  ts = gda_value_get_timestamp (value);
+			  if (!ts) {
+			  fbvar->sqldata_type = MYSQL_TYPE_NULL;
+			  fbvar.is_null = (my_bool*)1;
+			  }
+			  else {
+			  MYSQL_TIME *mtime;
+			  mtime = g_new0 (MYSQL_TIME, 1);
+			  mem_to_free = g_slist_prepend (mem_to_free, mtime);
+			  mtime->year = ts->year;
+			  mtime->month = ts->month;
+			  mtime->day = ts->day;
+			  mtime->hour = ts->hour;
+			  mtime->minute = ts->minute;
+			  mtime->second = ts->second;
+			  mtime->second_part = ts->fraction;
+
+			  fbvar->sqldata_type= MYSQL_TYPE_TIMESTAMP;
+			  fbvar->sqldata= (char *)mtime;
+			  fbvar->sqllen = sizeof (MYSQL_TIME);
+			  }
+			*/
+		}
+		else if (G_VALUE_TYPE (value) == GDA_TYPE_TIME) {
+			/*
+			  const GdaTime *ts;
+
+			  ts = gda_value_get_time (value);
+			  if (!ts) {
+			  fbvar->sqldata_type = MYSQL_TYPE_NULL;
+			  fbvar.is_null = (my_bool*)1;
+			  }
+			  else {
+			  MYSQL_TIME *mtime;
+			  mtime = g_new0 (MYSQL_TIME, 1);
+			  mem_to_free = g_slist_prepend (mem_to_free, mtime);
+			  mtime->hour = ts->hour;
+			  mtime->minute = ts->minute;
+			  mtime->second = ts->second;
+			  mtime->second_part = ts->fraction;
+
+			  fbvar->sqldata_type= MYSQL_TYPE_TIME;
+			  fbvar->sqldata= (char *)mtime;
+			  fbvar->sqllen = sizeof (MYSQL_TIME);
+			  }
+			*/
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_DATE) {
+			/*
+			  const GDate *ts;
+
+			  ts = (GDate*) g_value_get_boxed (value);
+			  if (!ts) {
+			  fbvar->sqldata_type = MYSQL_TYPE_NULL;
+			  fbvar.is_null = (my_bool*)1;
+			  }
+			  else {
+			  MYSQL_TIME *mtime;
+			  mtime = g_new0 (MYSQL_TIME, 1);
+			  mem_to_free = g_slist_prepend (mem_to_free, mtime);
+			  mtime->year = g_date_get_year (ts);
+			  mtime->month = g_date_get_month (ts);
+			  mtime->day = g_date_get_day (ts);
+
+			  fbvar->sqldata_type= MYSQL_TYPE_DATE;
+			  fbvar->sqldata= (char *)mtime;
+			  fbvar->sqllen = sizeof (MYSQL_TIME);
+			  }
+			*/
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
+			
+			gchar 		*str;// = "CLIENTS";
+			gshort 		*flag0 = g_new0(gshort, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			str		= (g_value_get_string (value));
+			//mem_to_free	= g_slist_prepend (mem_to_free, str);
+			if (!str) {
+				fbvar->sqlind	= flag0;
+				*flag0 = -1;
+			}
+			else {
+				fbvar->sqldata		= g_value_dup_string(value); //str;
+				//g_print("string-len: %d\n", fbvar->sqllen);
+				fbvar->sqllen		= strlen (fbvar->sqldata);
+				fbvar->sqlind		= flag0;
+				*flag0 = 0;
+			}
+			
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE) {
+			gdouble *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv		= g_new (gdouble, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, pv);
+			*pv		= g_value_get_double (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (gdouble);
+			fbvar->sqlind	= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_FLOAT) {
+			gfloat *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv			= g_new (gfloat, 1);
+			mem_to_free		= g_slist_prepend (mem_to_free, pv);
+			*pv			= g_value_get_float (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (gfloat);
+			fbvar->sqlind		= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_CHAR) {
+			gchar *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv			= g_new (gchar, 1);
+			mem_to_free		= g_slist_prepend (mem_to_free, pv);
+			*pv			= g_value_get_char (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (gchar);
+			fbvar->sqlind		= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == GDA_TYPE_SHORT) {
+			gshort *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv				= g_new (gshort, 1);
+			mem_to_free		= g_slist_prepend (mem_to_free, pv);
+			*pv				= gda_value_get_short (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (gshort);
+			fbvar->sqlind		= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_LONG) {
+			glong *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv				= g_new (glong, 1);
+			mem_to_free		= g_slist_prepend (mem_to_free, pv);
+			*pv				= g_value_get_long (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (glong);
+			fbvar->sqlind		= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == G_TYPE_INT64) {
+			gint64 *pv;
+			gint *flag0 = g_new0(gint, 1);
+			mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+			
+			pv				= g_new (gint64, 1);
+			mem_to_free		= g_slist_prepend (mem_to_free, pv);
+			*pv				= g_value_get_long (value);
+			fbvar->sqldata	= pv;
+			fbvar->sqllen	= sizeof (gint64);
+			fbvar->sqlind		= flag0;
+			*flag0 = 0;
+		}
+		else if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB) {
+			/*
+			  const GdaBinary *bin = NULL;
+			  GdaBlob *blob = (GdaBlob*) gda_value_get_blob (value);
+
+			  bin = ((GdaBinary*) blob);
+			  if (!bin) {
+			  fbvar->sqldata_type = MYSQL_TYPE_NULL;
+			  fbvar.is_null = (my_bool*)1;
+			  }
+			  else {
+			  gchar *str = NULL;
+			  glong blob_len;
+			  if (blob->op) {
+			  blob_len = gda_blob_op_get_length (blob->op);
+			  if ((blob_len != bin->binary_length) &&
+			  ! gda_blob_op_read_all (blob->op, blob)) {
+			  // force reading the complete BLOB into memory
+			  str = _("Can't read whole BLOB into memory");
+			  }
+			  }
+			  else
+			  blob_len = bin->binary_length;
+			  if (blob_len < 0)
+			  str = _("Can't get BLOB's length");
+			  else if (blob_len >= G_MAXINT)
+			  str = _("BLOB is too big");
+				
+			  if (str) {
+			  event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
+			  gda_connection_event_set_description (event, str);
+			  g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+			  GDA_SERVER_PROVIDER_DATA_ERROR, "%s", str);
+			  break;
+			  }
+				
+			  else {
+			  fbvar->sqldata_type= MYSQL_TYPE_BLOB;
+			  fbvar->sqldata= (char *) bin->data;
+			  fbvar->sqllen = bin->binary_length;
+			  fbvar.length = NULL;
+			  }
+			  }
+			*/
+		}
+		else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY) {
+			/*
+			  const GdaBinary *bin;
+			  bin = gda_value_get_binary (value);
+			  if (!bin) {
+			  fbvar->sqldata_type = MYSQL_TYPE_NULL;
+			  fbvar.is_null = (my_bool*)1;
+			  }
+			  else {
+			  fbvar->sqldata_type= MYSQL_TYPE_BLOB;
+			  fbvar->sqldata= (char *) bin->data;
+			  fbvar->sqllen = bin->binary_length;
+			  fbvar.length = NULL;
+			  }
+			*/
+		}
+		else {
+			gchar *str;
+			GdaDataHandler *data_handler =
+				gda_server_provider_get_data_handler_g_type (provider, cnc, 
+									     G_VALUE_TYPE (value));
+			if (data_handler == NULL) {
+				/* there is an error here */
+				event = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
+				gda_connection_event_set_description (event, str);
+				g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
+					     GDA_SERVER_PROVIDER_DATA_ERROR, "%s", str);
+				break;
+			}
+			else {
+				gint *flag0 = g_new0(gint, 1);
+				mem_to_free	= g_slist_prepend (mem_to_free, flag0);
+				
+				str		= gda_data_handler_get_str_from_value (data_handler, value);
+				mem_to_free	= g_slist_prepend (mem_to_free, str);
+				fbvar->sqldata	= str;
+				fbvar->sqllen	= strlen (str);
+				fbvar->sqlind		= flag0;
+				*flag0 = 0;
+			}
+		}
 	}
 		
 	if (event) {
@@ -1387,23 +1742,64 @@ gda_firebird_provider_statement_execute (GdaServerProvider *provider,
 		else
 			flags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
 
-		data_model = (GObject *) gda_firebird_recordset_new (cnc, ps, flags, col_types);
+		g_print("get the data model\n");
+
+		data_model = (GObject *) gda_firebird_recordset_new (cnc, ps, params, flags, col_types);
+		
+		g_print("assign the data model\n");
 		gda_connection_internal_statement_executed (cnc, stmt, params, NULL); /* required: help @cnc keep some stats */
+		
+		
+		if (mem_to_free){
+			g_print("free the memory for the input variables\n");
+			g_slist_foreach	(mem_to_free, (GFunc) g_free, NULL);
+			g_slist_free	(mem_to_free);
+		}
+		g_object_unref(ps);
 		return data_model;
         }
 	else {
 		GdaSet *set = NULL;
 		//TODO: What the hell must I do here?
 		//TO_IMPLEMENT;
-		//g_print("SQL: %s\n\n", _GDA_PSTMT (ps)->sql);
+		g_print("SQL: %s\n\n", _GDA_PSTMT (ps)->sql);
 		if (isc_dsql_execute(cdata->status, cdata->ftr, &(ps->stmt_h), SQL_DIALECT_V6, NULL)) {
 			isc_print_status(cdata->status);
 			g_print("\n");
 		}
-
+		/*
+		  gchar		count_item[]	= { isc_info_sql_records };
+		  char		res_buffer[64];
+		  gint		affected = 0;
+		  gint		length = 0;
+
+		  isc_dsql_sql_info (cdata->status
+		  , &(ps->stmt_h)
+		  , sizeof (count_item)
+		  , count_item
+		  , sizeof (res_buffer)
+		  , res_buffer);
+		  if (res_buffer[0] ==  isc_info_sql_records){
+		  unsigned i = 3, result_size = isc_vax_integer(&res_buffer[1],2);
+
+		  while (res_buffer[i] != isc_info_end && i < result_size) {
+		  short len = (short)isc_vax_integer(&res_buffer[i+1],2);
+		  if (res_buffer[i] != isc_info_req_select_count) {
+		  affected += isc_vax_integer(&res_buffer[i+3],len);
+		  }
+		  i += len+3;
+		  }
+		  }
+		*/
+	
 		/* Create a #GdaSet containing "IMPACTED_ROWS" */
 		/* Create GdaConnectionEvent notice with the type of command and impacted rows */
 
+		if (mem_to_free){
+			g_slist_foreach	(mem_to_free, (GFunc) g_free, NULL);
+			g_slist_free	(mem_to_free);
+		}
+
 		gda_connection_internal_statement_executed (cnc, stmt, params, event); /* required: help @cnc keep some stats */
 		return (GObject*) set;
 	}
@@ -1547,7 +1943,12 @@ gda_firebird_free_cnc_data (FirebirdConnectionData *cdata)
 	if (!cdata)
 		return;
 
-	TO_IMPLEMENT;
+	if (cdata->handle)
+		isc_detach_database (cdata->status, &(cdata->handle));
+	g_free (cdata->dpb);
+	g_free (cdata->dbname);
+	g_free (cdata->server_version);
+
 	g_free (cdata);
 }
 
@@ -1569,7 +1970,7 @@ fb_server_get_version (FirebirdConnectionData *fcnc)
 		isc_info_end
 	};
 
-	/* Try to get datbase version */
+	/* Try to get database version */
 	if (! isc_database_info (fcnc->status, &(fcnc->handle), sizeof (fdb_info), fdb_info,
 				 sizeof (buffer), buffer)) {
 		p_buffer = buffer;
diff --git a/providers/firebird/gda-firebird-pstmt.c b/providers/firebird/gda-firebird-pstmt.c
index 103d3f8..264a0ad 100644
--- a/providers/firebird/gda-firebird-pstmt.c
+++ b/providers/firebird/gda-firebird-pstmt.c
@@ -48,7 +48,8 @@ gda_firebird_pstmt_get_type (void)
 			NULL,
 			sizeof (GdaFirebirdPStmt),
 			0,
-			(GInstanceInitFunc) gda_firebird_pstmt_init
+			(GInstanceInitFunc) gda_firebird_pstmt_init,
+			0
 		};
 
 		g_static_mutex_lock (&registering);
@@ -67,6 +68,7 @@ gda_firebird_pstmt_get_type (void)
 static void 
 gda_firebird_pstmt_class_init (GdaFirebirdPStmtClass *klass)
 {
+//WHERE_AM_I;
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	parent_class = g_type_class_peek_parent (klass);
 
@@ -78,27 +80,70 @@ static void
 gda_firebird_pstmt_init (GdaFirebirdPStmt *pstmt, GdaFirebirdPStmtClass *klass)
 {
 	g_return_if_fail (GDA_IS_PSTMT (pstmt));
-	
+//WHERE_AM_I;
 	/* initialize specific parts of @pstmt */
-	pstmt->stmt_h = 0;
-	pstmt->sqlda = NULL;
+	if (pstmt->stmt_h != 0){
+		g_print("\t\tEXISTING PSTMT\n");
+		if (!isc_dsql_free_statement(pstmt->status, &(pstmt->stmt_h), DSQL_close)){
+			isc_print_status(pstmt->status);
+		}
+		
+		pstmt->stmt_h = 0;
+	}
+	//else
+		//g_print("\t\tNO STATEMENT\n");
+	
+	if (pstmt->sqlda != NULL){
+		//g_print("\t\tEXISTING SQLDA\n");
+		
+		g_free(pstmt->sqlda);
+		pstmt->sqlda = NULL;
+	}
+	
+	if (pstmt->input_sqlda != NULL){
+		//g_print("\t\tEXISTING SQLDA\n");
+		g_free(pstmt->input_sqlda);
+		pstmt->input_sqlda = NULL;
+	}
+	//else
+		//g_print("\t\tNO SQLDA\n");
 }
 
 static void
 gda_firebird_pstmt_finalize (GObject *object)
 {
-	GdaFirebirdPStmt *pstmt = (GdaFirebirdPStmt *) object;
+//WHERE_AM_I;
 
+	GdaFirebirdPStmt *pstmt = (GdaFirebirdPStmt *) object;
 	g_return_if_fail (GDA_IS_PSTMT (pstmt));
 
 	/* free memory */
 	//TO_IMPLEMENT; /* free some specific parts of @pstmt */
-	isc_dsql_free_statement(pstmt->status, &(pstmt->stmt_h), DSQL_close);
-
-	g_free(pstmt->sqlda);
-	pstmt->sqlda = NULL;
+	if (pstmt->stmt_h != 0){
+		g_print("\t\tCLOSE STATEMENT\n");
+		if (!isc_dsql_free_statement(pstmt->status, &(pstmt->stmt_h), DSQL_close)){
+			isc_print_status(pstmt->status);
+		}
+	}
+	else{
+		//g_print("\t\tNO STATEMENT TO CLOSE\n");
+	}
+	//g_free(pstmt->sqlda);
+	//pstmt->sqlda = NULL;
 	pstmt->stmt_h = 0;
 
+	if (pstmt->sqlda != NULL){
+		g_print("\t\tEXISTING SQLDA\n");
+		g_free(pstmt->sqlda);
+		pstmt->sqlda = NULL;
+	}
+	
+	if (pstmt->input_sqlda != NULL){
+		g_print("\t\tEXISTING SQLDA\n");
+		g_free(pstmt->input_sqlda);
+		pstmt->input_sqlda = NULL;
+	}
+	
 	/* chain to parent class */
 	parent_class->finalize (object);
 }
diff --git a/providers/firebird/gda-firebird-pstmt.h b/providers/firebird/gda-firebird-pstmt.h
index af50341..062c815 100644
--- a/providers/firebird/gda-firebird-pstmt.h
+++ b/providers/firebird/gda-firebird-pstmt.h
@@ -40,7 +40,7 @@ struct _GdaFirebirdPStmt {
 	isc_stmt_handle	stmt_h;
 	ISC_STATUS	status[20];
 	XSQLDA 	       *sqlda;
-
+	XSQLDA 	       *input_sqlda;
 	gint		statement_type;
 	gboolean	is_non_select;
 };
diff --git a/providers/firebird/gda-firebird-recordset.c b/providers/firebird/gda-firebird-recordset.c
index d7087fa..2ce0aba 100644
--- a/providers/firebird/gda-firebird-recordset.c
+++ b/providers/firebird/gda-firebird-recordset.c
@@ -36,6 +36,20 @@
 
 #define _GDA_PSTMT(x) ((GdaPStmt*)(x))
 
+#ifndef ISC_INT64_FORMAT
+
+/* Define a format string for printf.  Printing of 64-bit integers
+   is not standard between platforms */
+
+#if (defined(_MSC_VER) && defined(WIN32))
+#define	ISC_INT64_FORMAT	"I64"
+#else
+#define	ISC_INT64_FORMAT	"ll"
+#endif
+#endif
+
+typedef PARAMVARY VARY2;
+
 static void gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *klass);
 static void gda_firebird_recordset_init       (GdaFirebirdRecordset *recset,
 					     GdaFirebirdRecordsetClass *klass);
@@ -50,28 +64,11 @@ static gboolean gda_firebird_recordset_fetch_at (GdaDataSelect *model, GdaRow **
 
 
 struct _GdaFirebirdRecordsetPrivate {
-	GdaConnection *cnc;
-	/* TO_ADD: specific information */
-	XSQLDA *xsqlda;
+
 	gint n_columns;
 };
 static GObjectClass *parent_class = NULL;
 
-typedef PARAMVARY VARY2;
-
-
-#ifndef ISC_INT64_FORMAT
-
-/* Define a format string for printf.  Printing of 64-bit integers
-   is not standard between platforms */
-
-#if (defined(_MSC_VER) && defined(WIN32))
-#define	ISC_INT64_FORMAT	"I64"
-#else
-#define	ISC_INT64_FORMAT	"ll"
-#endif
-#endif
-
 
 /*
  * Object init and finalize
@@ -80,18 +77,21 @@ static void
 gda_firebird_recordset_init (GdaFirebirdRecordset *recset,
 			   GdaFirebirdRecordsetClass *klass)
 {
+//WHERE_AM_I;
 	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
+	
 	recset->priv = g_new0 (GdaFirebirdRecordsetPrivate, 1);
-	recset->priv->cnc = NULL;
+
 
 	/* initialize specific information */
 	//TO_IMPLEMENT;
-	recset->priv->xsqlda	= NULL;
+	
 }
 
 static void
 gda_firebird_recordset_class_init (GdaFirebirdRecordsetClass *klass)
 {
+//WHERE_AM_I;
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 	GdaDataSelectClass *pmodel_class = GDA_DATA_SELECT_CLASS (klass);
 
@@ -110,18 +110,16 @@ static void
 gda_firebird_recordset_dispose (GObject *object)
 {
 	GdaFirebirdRecordset *recset = (GdaFirebirdRecordset *) object;
-
+//WHERE_AM_I;
 	g_return_if_fail (GDA_IS_FIREBIRD_RECORDSET (recset));
 
 	if (recset->priv) {
-		if (recset->priv->cnc) 
-			g_object_unref (recset->priv->cnc);
+		//if (recset->priv->cnc) 
+		//	g_object_unref (recset->priv->cnc);
 
 		/* free specific information */
 		//TO_IMPLEMENT;
-		if (NULL != recset->priv->xsqlda)
-			g_free(recset->priv->xsqlda);
-
+		
 		g_free (recset->priv);
 		recset->priv = NULL;
 	}
@@ -149,7 +147,8 @@ gda_firebird_recordset_get_type (void)
 			NULL,
 			sizeof (GdaFirebirdRecordset),
 			0,
-			(GInstanceInitFunc) gda_firebird_recordset_init
+			(GInstanceInitFunc) gda_firebird_recordset_init,
+			0
 		};
 		g_static_mutex_lock (&registering);
 		if (type == 0) {
@@ -225,7 +224,8 @@ _gda_firebird_type_to_gda (XSQLVAR *var){
 /*
  *    Print column's data.
  */
-void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
+void 
+_fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row, GType req_col_type){
 	short       dtype;
 	char        data[2048], *p;
 	char        blob_s[20], date_s[25];
@@ -279,21 +279,26 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 					len = 17;
 					break;
 		}
-		g_value_set_string (value, "NULL");
+		//if (req_col_type != G_TYPE_BOOLEAN)
+		//	g_value_set_string (value, "NULL");
+		//else
+		//	g_value_set_boolean(value, FALSE);
 	}
 	else
 	{
 		switch (dtype)
 		{
 			case SQL_TEXT:
-				sprintf (p, "%.*s ", var->sqllen, var->sqldata);
-				g_value_set_string (value, p);
+				sprintf (p, "%.*s", var->sqllen, var->sqldata);
+				if (req_col_type != G_TYPE_BOOLEAN)
+					g_value_set_string (value, p);
+				else
+					g_value_set_boolean(value, g_ascii_strcasecmp("1", p) == 0 ? TRUE : FALSE);
 				break;
 			case SQL_VARYING:
 				vary2 = (VARY2*) var->sqldata;
-				vary2->vary_string[vary2->vary_length] = '\0';	
-				sprintf(p, "%-*s ", var->sqllen, vary2->vary_string);
-				g_value_set_string (value, p);
+				vary2->vary_string[vary2->vary_length] = '\0';
+				g_value_set_string (value, (char *)vary2->vary_string);
 				break;
 
 			case SQL_SHORT:
@@ -360,19 +365,47 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 						 field_width, 
 						 (ISC_INT64) fb_value);
 				}
-
-				switch (dtype) {
-					case SQL_SHORT:
-						gda_value_set_short (value, atoi (p));
-						break;
-					case SQL_LONG:
-						g_value_set_ulong (value, atoll (p));
-						break;
-					case SQL_INT64:
-					default:
-						g_value_set_int64 (value, atoll (p));
-						break;
+				
+				if (req_col_type != G_TYPE_BOOLEAN){
+					switch (req_col_type) {
+						case G_TYPE_INT:
+							g_value_set_int (value, atoi (p));
+							break;
+						case G_TYPE_UINT:
+							g_value_set_uint (value, atoi (p));
+							break;
+						case G_TYPE_INT64:
+							g_value_set_int64(value, atoll(p));
+							break;
+						case G_TYPE_UINT64:
+							g_value_set_uint64(value, atoll(p));
+							break;
+						case G_TYPE_LONG:
+							g_value_set_long (value, atoll (p));
+							break;
+						case G_TYPE_ULONG:
+							g_value_set_ulong (value, atoll (p));
+							break;
+						default:
+							g_print("Oh flip....did not cater for this\n");
+							g_value_set_int64 (value, atoll (p));
+							break;
+					}
+					/*switch (dtype) {
+						case SQL_SHORT:
+							gda_value_set_short (value, atoi (p));
+							break;
+						case SQL_LONG:
+							g_value_set_ulong (value, atoll (p));
+							break;
+						case SQL_INT64:
+						default:
+							g_value_set_int64 (value, atoll (p));
+							break;
+					}*/
 				}
+				else
+					g_value_set_boolean(value, atoll(p) == 1 ? TRUE : FALSE);
 				}
 				break;
 
@@ -399,7 +432,7 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 						times.tm_hour,
 						times.tm_min,
 						times.tm_sec);
-				sprintf(p, "%*s ", 22, date_s);
+				sprintf(p, "%*s", 22, date_s);
 				//g_value_set_string (value, p);
 
 				GdaTimestamp timestamp;
@@ -426,7 +459,7 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 						times.tm_mday);
 				sprintf(p, "%*s ", 10, date_s);
 				GDate date;
-				if (!gda_parse_iso8601_date (&date, p)) {
+				if (!gda_parse_iso8601_date (&date, date_s)) {
 					//gda_row_invalidate_value (row, value);
 					/*
 					g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
@@ -446,7 +479,7 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 						times.tm_sec);
 				sprintf(p, "%*s ", 11, date_s);
 				GdaTime timegda;
-				if (!gda_parse_iso8601_time (&timegda, p)) {
+				if (!gda_parse_iso8601_time (&timegda, date_s)) {
 					//gda_row_invalidate_value (row, value); 
 					/*
 					g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
@@ -462,7 +495,7 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 			case SQL_ARRAY:
 				/* Print the blob id on blobs or arrays */
 				bid = *(ISC_QUAD *) var->sqldata;
-				sprintf(blob_s, "%08x:%08x", bid.gds_quad_high, bid.gds_quad_low);
+				sprintf(blob_s, "%08x:%08x", (unsigned int)bid.gds_quad_high, (unsigned int)bid.gds_quad_low);
 				sprintf(p, "%17s ", blob_s);
 				g_value_set_string (value, p);
 				break;
@@ -471,40 +504,79 @@ void _fb_set_row_data (XSQLVAR *var, GValue *value, GdaRow *row){
 				g_value_set_string(value, "TYPE NOT FOUND");
 				break;
 		}
+		
+		//g_print("\t\t%s\n", p);
 	}
 }
 
+static GdaRow *
+new_row_from_firebird_stmt (GdaFirebirdRecordset *imodel, G_GNUC_UNUSED gint rownum, GType *col_types, GError **error)
+{
+	gint				i;
+	gint 				fetch_stat;
+	ISC_STATUS			status[20];
+	GdaRow*				row = NULL;	
+	GdaFirebirdPStmt*	ps = (GdaFirebirdPStmt *) ((GdaDataSelect *) imodel)->prep_stmt;
+	//WHERE_AM_I;
+	if ((fetch_stat = isc_dsql_fetch(status, &(ps->stmt_h), SQL_DIALECT_V6, ps->sqlda)) == 0) {
+		row = gda_row_new (ps->sqlda->sqld);
+		for (i = 0; i < ps->sqlda->sqld; i++) {
+			GValue *value = gda_row_get_value (row, i);
+			GType type = _gda_firebird_type_to_gda((XSQLVAR *) &(ps->sqlda->sqlvar[i]));
+
+			//IF COLUMN TYPES IS NOT EXPLICITLY SPECIFIED THEN WE
+			//SET THE COLUMN TYPES TO WHAT FIREBIRD RETURNS
+			if (col_types)
+				type = col_types[i];
+			//g_print("col#: %d\n", i);
+			gda_value_reset_with_type (value, type);
+			_fb_set_row_data ((XSQLVAR *) &(ps->sqlda->sqlvar[i]), value, row, type);
+		}
+		rownum++;
+	}
+	
+	return row;
+}
 
 /*
  * the @ps struct is modified and transferred to the new data model created in
  * this function
  */
 GdaDataModel *
-gda_firebird_recordset_new (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataModelAccessFlags flags, GType *col_types)
+gda_firebird_recordset_new (GdaConnection            *cnc,
+			    GdaFirebirdPStmt            *ps,
+			    GdaSet                   *exec_params,
+			    GdaDataModelAccessFlags   flags,
+			    GType                    *col_types)
+
+//(GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataModelAccessFlags flags, GType *col_types)
 {
 	GdaFirebirdRecordset *model;
 	FirebirdConnectionData *cdata;
 	gint i;
-	gint fetch_stat;
 	GdaDataModelAccessFlags rflags;
-
-        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
-        g_return_val_if_fail (ps, NULL);
+//WHERE_AM_I;
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (ps, NULL);
 
 	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
 	if (!cdata)
 		return NULL;
 
+	//g_print("RST-SQL>> %s\n", _GDA_PSTMT (ps)->sql);
+	
+	if (ps->sqlda == NULL){
+		g_print("ERROR: ps->sqlda seems to be NULL\n");
+	}
 	/* make sure @ps reports the correct number of columns using the API*/
-        if (_GDA_PSTMT (ps)->ncols < 0)
+        //if (_GDA_PSTMT (ps)->ncols < 0)
                 /*_GDA_PSTMT (ps)->ncols = ...;*/
-		TO_IMPLEMENT;
+		//TO_IMPLEMENT;
 
-        /* completing @ps if not yet done */
+	/* completing @ps if not yet done */
 	if (_GDA_PSTMT (ps)->ncols < 0)
-		/*_GDA_PSTMT (ps)->ncols = ...;*/
 		_GDA_PSTMT (ps)->ncols = ps->sqlda->sqld;
-
+	
 	/* completing @ps if not yet done */
 	if (!_GDA_PSTMT (ps)->types && (_GDA_PSTMT (ps)->ncols > 0)) {
 		/* create prepared statement's columns */
@@ -534,75 +606,104 @@ gda_firebird_recordset_new (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataMod
 		}
 
 		/* fill GdaColumn's data */
+		g_print("FB reported %d columns. Gda col-cnt: %d\n", ps->sqlda->sqld, GDA_PSTMT (ps)->ncols);
 		for (i=0, list = _GDA_PSTMT (ps)->tmpl_columns; 
-		     i < GDA_PSTMT (ps)->ncols; 
-		     i++, list = list->next) {
-			GdaColumn       *column;
-			GType           gtype;
-			XSQLVAR         *var;
-
+			i < GDA_PSTMT (ps)->ncols; 
+			i++, list = list->next) {
+			GdaColumn*		column;
+			GType			gtype;
+			XSQLVAR*		var;
+			/*
+			g_print("\t\tField:%d/%d (fb-cnt=d)\n\t\tSQL-NAME:%s\n\t\tREL-NAME: %s\n\t\tOWN-NAME: %s\n\t\tALIAS: %s\n**************************\n\n"
+					, i
+					, GDA_PSTMT (ps)->ncols
+					//, ps->sqlda->sqld
+					, var->sqlname
+					, var->relname
+					, var->ownname
+					, var->aliasname);
+			*/
 			var = (XSQLVAR *) &(ps->sqlda->sqlvar[i]);
 			column = GDA_COLUMN (list->data);
 			/* use C API to set columns' information using gda_column_set_*() */
 			gtype = _gda_firebird_type_to_gda(var);
-
 			_GDA_PSTMT (ps)->types [i] = gtype;
-			gda_column_set_g_type (column, gtype);
+			if (col_types)
+				gda_column_set_g_type (column, col_types[i]);
+			else
+				gda_column_set_g_type (column, gtype);
+				
 			gda_column_set_name (column, var->aliasname);
 			gda_column_set_description (column, var->aliasname);
-
-			//g_print("\t\tSQL-NAME:%s\n\t\tREL-NAME: %s\n\t\tOWN-NAME: %s\n\t\tALIAS: %s\n**************************\n\n"
-			//      , var->sqlname
-			//      , var->relname
-			//      , var->ownname
-			//      , var->aliasname);
 		}
 	}
 
 
-	/* 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_FIREBIRD_RECORDSET, "prepared-stmt", ps, "model-usage", rflags, NULL);
-	model->priv->cnc = cnc;
-	model->priv->n_columns	= ps->sqlda->sqld;
-	g_object_ref (cnc);
-
-	gda_data_select_set_columns (GDA_DATA_SELECT (model), _GDA_PSTMT (ps)->tmpl_columns);
+	if (ps->input_sqlda != NULL){
+		g_print("\n\nPRINTING THE INPUT PARAMETERS\n--------------------------\n");
+		for(i =0; i < ps->input_sqlda->sqld; i++){
+			g_print("input-paramater #%d: %s\n", i, (ps->input_sqlda->sqlvar[i].sqldata));
+			g_print("input-len       #%d: %d\n", i, ps->input_sqlda->sqlvar[i].sqllen);
+		}
+	}
+	
+	//RUN ISC_DSQL_DESCRIBE TO GET OUTPUT FIELDS
+	//isc_dsql_describe(cdata->status, cdata->ftr, &(ps->stmt_h), ps->sqlda);
 
+	
+	g_print("isc_dsql_execute\n");
 	/* post init specific code */
-	if (isc_dsql_execute (cdata->status, cdata->ftr, &(ps->stmt_h), SQL_DIALECT_V6, NULL)) {
+	//if (isc_dsql_execute (cdata->status, cdata->ftr, &(ps->stmt_h), SQL_DIALECT_V6, NULL)) {
+	if (isc_dsql_execute2 (cdata->status, cdata->ftr, &(ps->stmt_h), SQL_DIALECT_V6, ps->input_sqlda, NULL)) {
+		g_print("\nisc error occured: \n");
 		isc_print_status(cdata->status);
 		g_print("\n");
 	}
 
-	gint rownum = 0;
-	while ((fetch_stat = isc_dsql_fetch(cdata->status, &(ps->stmt_h), SQL_DIALECT_V6, ps->sqlda)) == 0) {
-		GdaRow *row = gda_row_new (ps->sqlda->sqld);
-		for (i = 0; i < ps->sqlda->sqld; i++) {
-			GValue *value = gda_row_get_value (row, i);
-			GType type =_gda_firebird_type_to_gda((XSQLVAR *) &(ps->sqlda->sqlvar[i]));
-			//char *data = mysql_row[i];
-
-			//if (!data || (type == GDA_TYPE_NULL))
-			//	continue;
+	isc_dsql_set_cursor_name(cdata->status, &(ps->stmt_h), "dyn_cursor", NULL);
 
-			gda_value_reset_with_type (value, type);
-			//g_value_set_string (value, "faghmie");
-			_fb_set_row_data ((XSQLVAR *) &(ps->sqlda->sqlvar[i]), value, row);
-			//print_column((XSQLVAR *) &sqlda->sqlvar[i]);
-		}
+	/* determine access mode: RANDOM or CURSOR FORWARD are the only supported */
+	if (flags & GDA_DATA_MODEL_ACCESS_RANDOM){
+		rflags = GDA_DATA_MODEL_ACCESS_RANDOM;
+		g_print("\nRANDOM ACCESS\n");
+	}
+	else{
+		rflags = GDA_DATA_MODEL_ACCESS_CURSOR_FORWARD;
+		g_print("CURSOR FORWARD ACCESS\n");
+	}
+	/* create data model */
+	g_print("Creating the data-model\n");
+	model = g_object_new (GDA_TYPE_FIREBIRD_RECORDSET
+			, "connection", cnc
+			, "prepared-stmt", ps
+			, "model-usage", rflags
+			, "exec-params", exec_params
+			, NULL);
+	g_print("point to the connection\n");
+	//model->priv->cnc = cnc;
+	g_print("set the number of columns\n");
+	//model->priv->n_columns	= ps->sqlda->sqld;
+	g_print("add reference to connection\n");
+	//g_object_ref (model->priv->cnc);
+	gda_data_select_set_columns (GDA_DATA_SELECT (model), _GDA_PSTMT (ps)->tmpl_columns);
 
+	gint rownum = 0;
+	g_print("populate the model\n");
+	GdaRow *row = NULL;
+	while ((row = new_row_from_firebird_stmt (model, rownum, col_types, NULL)) != NULL) {
 		gda_data_select_take_row ((GdaDataSelect*) model, row, rownum);
 		rownum++;
 	}
-
+	
+	isc_dsql_free_statement(cdata->status, &(ps->stmt_h), DSQL_close);
+	
+	g_print("SQL-ROWS >> %d\n", rownum);
 	((GdaDataSelect *) model)->advertized_nrows = rownum;
-
+	/*
+	g_print("\n\ncreating a dump of the table\n\n");
+	g_print("%s", gda_data_model_dump_as_string(GDA_DATA_MODEL (model)));
+	g_print("\n\nreturning the data model\n\n");
+	*/
 	return GDA_DATA_MODEL (model);
 }
 
@@ -613,9 +714,9 @@ gda_firebird_recordset_new (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataMod
 static gint
 gda_firebird_recordset_fetch_nb_rows (GdaDataSelect *model)
 {
-	GdaFirebirdRecordset *imodel;
-
-	imodel = GDA_FIREBIRD_RECORDSET (model);
+	//GdaFirebirdRecordset *imodel;
+	//WHERE_AM_I;
+	//imodel = GDA_FIREBIRD_RECORDSET (model);
 	if (model->advertized_nrows >= 0)
 		return model->advertized_nrows;
 
@@ -641,13 +742,17 @@ gda_firebird_recordset_fetch_nb_rows (GdaDataSelect *model)
 static gboolean 
 gda_firebird_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaFirebirdRecordset *imodel;
-
+	gboolean				result = FALSE;
+	GdaFirebirdRecordset*	imodel;
+	//WHERE_AM_I;
 	imodel = GDA_FIREBIRD_RECORDSET (model);
 
-	TO_IMPLEMENT;
+	if ((*prow = new_row_from_firebird_stmt (imodel, rownum, NULL, NULL)) != NULL) {
+		result = TRUE;
+		gda_data_select_take_row (model, *prow, rownum);
+	}
 
-	return TRUE;
+	return result;
 }
 
 /*
@@ -656,10 +761,10 @@ gda_firebird_recordset_fetch_random (GdaDataSelect *model, GdaRow **prow, gint r
 static gboolean
 gda_firebird_recordset_store_all (GdaDataSelect *model, GError **error)
 {
-	GdaFirebirdRecordset *imodel;
+	//GdaFirebirdRecordset *imodel;
 	gint i;
-
-	imodel = GDA_FIREBIRD_RECORDSET (model);
+	//WHERE_AM_I;
+	//imodel = GDA_FIREBIRD_RECORDSET (model);
 
 	/* default implementation */
 	for (i = 0; i < model->advertized_nrows; i++) {
@@ -686,11 +791,17 @@ gda_firebird_recordset_store_all (GdaDataSelect *model, GError **error)
 static gboolean 
 gda_firebird_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
+	gboolean				result = FALSE;
+	GdaFirebirdRecordset*	imodel;
+	//WHERE_AM_I;
+	imodel = GDA_FIREBIRD_RECORDSET (model);
 
-	TO_IMPLEMENT;
+	if ((*prow = new_row_from_firebird_stmt (imodel, rownum, NULL, NULL)) != NULL) {
+		result = TRUE;
+		gda_data_select_take_row (model, *prow, rownum);
+	}
 
-	return TRUE;
+	return result;
 }
 
 /*
@@ -710,11 +821,18 @@ gda_firebird_recordset_fetch_next (GdaDataSelect *model, GdaRow **prow, gint row
 static gboolean 
 gda_firebird_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
+	gboolean				result = FALSE;
+	GdaFirebirdRecordset*	imodel;
+	//WHERE_AM_I;
+	imodel = GDA_FIREBIRD_RECORDSET (model);
 
-	TO_IMPLEMENT;
+	if ((*prow = new_row_from_firebird_stmt (imodel, rownum, NULL, NULL)) != NULL) {
+		result = TRUE;
+		gda_data_select_take_row (model, *prow, rownum);
+	}
+
+	return result;
 
-	return TRUE;
 }
 
 /*
@@ -734,10 +852,17 @@ gda_firebird_recordset_fetch_prev (GdaDataSelect *model, GdaRow **prow, gint row
 static gboolean 
 gda_firebird_recordset_fetch_at (GdaDataSelect *model, GdaRow **prow, gint rownum, GError **error)
 {
-	GdaFirebirdRecordset *imodel = (GdaFirebirdRecordset*) model;
-	
-	TO_IMPLEMENT;
+	gboolean				result = FALSE;
+	GdaFirebirdRecordset*	imodel;
+	//WHERE_AM_I;
+	imodel = GDA_FIREBIRD_RECORDSET (model);
+
+	if ((*prow = new_row_from_firebird_stmt (imodel, rownum, NULL, NULL)) != NULL) {
+		result = TRUE;
+		gda_data_select_take_row (model, *prow, rownum);
+	}
+
+	return result;
 
-	return TRUE;
 }
 
diff --git a/providers/firebird/gda-firebird-recordset.h b/providers/firebird/gda-firebird-recordset.h
index f3e46d4..e3fc899 100644
--- a/providers/firebird/gda-firebird-recordset.h
+++ b/providers/firebird/gda-firebird-recordset.h
@@ -77,8 +77,11 @@ struct _GdaFirebirdRecordsetClass {
 };
 
 GType         gda_firebird_recordset_get_type  (void) G_GNUC_CONST;
-GdaDataModel *gda_firebird_recordset_new       (GdaConnection *cnc, GdaFirebirdPStmt *ps, GdaDataModelAccessFlags flags, 
-					    GType *col_types);
+GdaDataModel *gda_firebird_recordset_new (GdaConnection            *cnc,
+			    GdaFirebirdPStmt            *ps,
+			    GdaSet                   *exec_params,
+			    GdaDataModelAccessFlags   flags,
+			    GType                    *col_types);
 
 G_END_DECLS
 
diff --git a/providers/firebird/gda-firebird-util.c b/providers/firebird/gda-firebird-util.c
index 33b7d8c..7c77bce 100644
--- a/providers/firebird/gda-firebird-util.c
+++ b/providers/firebird/gda-firebird-util.c
@@ -25,21 +25,25 @@ _gda_firebird_make_error (GdaConnection *cnc, const gint statement_type)
 {
 	FirebirdConnectionData *cdata;
 	GdaConnectionEvent *error_ev;
-        gchar *description;
 
-        g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
+	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
 
 	cdata = (FirebirdConnectionData*) gda_connection_internal_get_provider_data (cnc);
 	if (!cdata) 
-		return FALSE;
+		return NULL;
 
-        error_ev = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
-        gda_connection_event_set_code (error_ev, isc_sqlcode (cdata->status));
-        description = fb_sqlerror_get_description (cdata, statement_type);
-        gda_connection_event_set_source (error_ev, "[GDA Firebird]");
-        gda_connection_event_set_description (error_ev, description);
-        gda_connection_add_event (cnc, error_ev);
-        g_free (description);
+	error_ev = gda_connection_point_available_event (cnc, GDA_CONNECTION_EVENT_ERROR);
+	gda_connection_event_set_code (error_ev, isc_sqlcode (cdata->status));
+	ISC_SCHAR *description;
+	const ISC_STATUS *p = cdata->status;
 
-        return error_ev;
+	description = g_new0 (ISC_SCHAR, 512);
+	fb_interpret (description, 511, &p);
+	g_print ("MAKE_ERROR [%s]\n", description);
+	gda_connection_event_set_source (error_ev, "[GDA Firebird]");
+	gda_connection_event_set_description (error_ev, description);
+	gda_connection_add_event (cnc, error_ev);
+	g_free (description);
+
+	return error_ev;
 }
diff --git a/providers/firebird/gda-firebird.h b/providers/firebird/gda-firebird.h
index da58f81..8e41322 100644
--- a/providers/firebird/gda-firebird.h
+++ b/providers/firebird/gda-firebird.h
@@ -52,22 +52,21 @@
 
 #include <libgda/libgda.h>
 #include <ibase.h>
-
+	
 /*
  * Provider's specific connection data
  */
 
 typedef struct
 {
-	//GdaConnection	*cnc;
-	gchar	       *dbname;
-	gchar	       *server_version;
-	isc_db_handle	handle;
-	ISC_STATUS	status[20];
-	gchar		dpb_buffer[128];
-	gshort		dpb_length;
+	gchar           *dpb;
+	isc_db_handle	 handle;
+
+	gchar	        *dbname;
+	gchar	        *server_version;
 
-	isc_tr_handle	*ftr;
+	ISC_STATUS_ARRAY status;
+	isc_tr_handle   *ftr;
 } FirebirdConnectionData;
 
 #endif
diff --git a/providers/firebird/libmain-embed.c b/providers/firebird/libmain-embed.c
index b13cd1d..5304eb9 100644
--- a/providers/firebird/libmain-embed.c
+++ b/providers/firebird/libmain-embed.c
@@ -57,11 +57,22 @@ plugin_get_dsn_spec (void)
 	gchar *ret, *dir;
 
 	dir = gda_gbr_get_file_path (GDA_DATA_DIR, LIBGDA_ABI_NAME, NULL);
-	ret = gda_server_provider_load_file_contents (module_path, dir, "firebird_specs_dsn.xml");
+	ret = gda_server_provider_load_file_contents (module_path, dir, "firebird_specs_dsn_emb.xml");
 	g_free (dir);
 	return ret;
 }
 
+gchar *
+plugin_get_auth_spec (void)
+{
+#define AUTH "<?xml version=\"1.0\"?>" \
+             "<data-set-spec>" \
+             "  <parameters/>" \
+             "</data-set-spec>"
+
+        return g_strdup (AUTH);
+}
+
 GdaServerProvider *
 plugin_create_provider (void)
 {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]