Re: [Planner Dev] First patch to database backend -> New version



Hi!

El mié, 28-07-2004 a las 20:56, Richard Hult escribió:
> On ons, 2004-07-28 at 19:52 +0200, Alvaro del Castillo wrote:
> > Hi guys!
> 
> Hi! 
> 
> > > Looks good... but why did you change the gpl header? :)
> 
> > Reverted!
> 
> :)
> 
> > > There are missing spaces etc coding style wise that would be nice to get
> > > fixed before committing. Other than that:
> 
> > I have review all the code another time trying to find style issues and
> > can't find them :(
> 
> Some of them:
> 
> +       g_strfreev(versionv_new);
> 
> missing space
> 
> +static gboolean
> +check_database_tables (GdaConnection *conn)
> +{
> +       GdaDataModel   *res;
> 
> too many spaces before the variables
> 

Ok, corrected these issues ;-)

> +               gchar  *sql_file = g_build_path (G_DIR_SEPARATOR_S,
> +                                                SQL_DIR,
> +                                                name,
> +                                                NULL);
> 
> I think you are looking for g_build_filename () here.
> 

devhelp is my friend .... sure! better g_build_filename (SQL_DIR, name,
NULL).

> +       else if (upgradable && !create_tables) {
> +               gchar        *contents;
> 
> too many spaces
> 
> +       if (!GDA_IS_CONNECTION (conn)) {
> 
> shouldn't that just be a NULL check?
> 
> > >   _("Database %s need to be upgraded to version: %s."
> > >   " Please backup the database before upgrading."
> > >   " Have you done the backup and want to continue?")
> > > 
> > > The last sentence should probably be removed (likewise for one more
> > > dialog).
> > 
> > Hmmm, I think the user need to answer a clear question in the dialog.
> > Without this last sentence, no question is shown to the user. I have
> > left it as: "Do you want to continue?"
> 
> Well, the dialog should inform about the problem and then the buttons
> should show the choices, instead of yes/no. Perhaps something like:
> 
>  The database %s needs to be upgraded from version %s to %s.
> 
>                                    [ Cancel ]  [ Upgrade ]


Hmmm, looking to the message, it has pointed me that we haven't now a
way to know in which version the database is currently. We check the
VERSION using the planner binary version, so if you upgrade planner,
you'll have a newer version, not the version used to store the data in
the database.

We need someplace in database to store the version. I will bet for a
version for all the data in database, not having a different version for
each project in database, because it will be too complex.

What do you think?

About the dialog, yes, I think richard proposal is more elegant and user
oriented. I will try to implement it in such way. The yes/no was the
quick way because we use this dialog in other places ;-)

> 
> 
> > > _("Can't create tables in database %s. File %s could be corrupted."
> > >  "\n\nDatabase error: \n%s"),
> > > 
> > > I think a corrupt file would be the least probable error here, no reason
> > > to make a guess like that, IMO.
> > 
> > Yes, I have changed that to:
> > 
> > _("Can't create tables in database %s. File %s is not correct, maybe a
> > install problem."
> > 								   "\n\nDatabase error: \n%s"),
> 
> Should probably be "Could not...". I still think we are trying to make
> an impossible guess. We should check if the upgrade file exists and if
> not we should say that the database is out of date but can't be upgraded
> automatically from version foo to version bar.
> 

Ok, a more general message. I was trying to show the user a way in order
to find some support ...

> If the file exists and the upgrade doesn't work, it's probably not an
> installation problem, but more likely a bug in the upgrade file or the C
> code or the way that the database is set up. Since we have no idea which
> it is, we should just say that the upgrade failed and show the error
> message, something like:
> 
>  The database upgrade failed:\n\n%s
> 

Ok, I have modified the message to:

_("Could not create tables in database %s. File %s is not correct."
								   "\n\nDatabase error: \n%s"),

I think it is important to show the filename in order the user could get
some support from its distribution or from us in the planner user list.

>  
> > > Should set the main window as parent window for those dialogs (also
> > > something we need to go through and fix in older code).
> > 
> > Done! I will look to all planner code to solve other places with this
> > problem.
> 
> We could add a bug for that, sounds like a perfect way to get started on
> planner ;)
> 

Yes, good point!

> > > 
> > >        _("Tables in database %s doesn't exist. "
> > >       "Do you want to create them?"),
> > > 
> > > Should be "do not exist"... (or a more friendly wording like "The
> > > database is not setup for Planner. Do you want to do that?".)
> > > 
> > 
> > Changed it two places to:
> > 
> > _("The database is not setup for Planner. "
> > 						   "Do you want to do that?")
> 
> Hm, a question: Couldn't we just go ahead and add create the tables? If
> the user wants to use the database in the first place, why ask again?
> 

I think that it is good that the user knows that something is happening
first time. If everything is ok, only the first time she will see such
dialogs. But if something goes wrong, she will receive more information
and could get more support with the details.

We can let the code as it is now and see what other people think and
also, we can test it a bit more to find the best solution.

I will let it be as it is for now, as I have talked with richard.

So before commiting this patch:

1. We need to create a place in database to store the version for all
the database data. A single data with one record seems to be a terrific
waste of resources, but the direct solution. Maybe we can create a
special property to store it ...

2. I need to implement the new dialog with Cancel, Upgrade buttons.

I attach the new patch with corrected strings and style ;-)

Cheers

-- Alvaro

> /Richard
Index: Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/Makefile.am,v
retrieving revision 1.12
diff -u -b -B -p -r1.12 Makefile.am
--- Makefile.am	4 Jul 2004 12:51:24 -0000	1.12
+++ Makefile.am	28 Jul 2004 21:26:14 -0000
@@ -13,7 +13,6 @@ SUBDIRS = \
 	src				\
 	data				\
 	docs				\
-	examples			\
 	$(python_DIR)			\
 	$(dotnet_DIR)
 
Index: configure.in
===================================================================
RCS file: /cvs/gnome/planner/configure.in,v
retrieving revision 1.37
diff -u -b -B -p -r1.37 configure.in
--- configure.in	19 Jul 2004 18:46:08 -0000	1.37
+++ configure.in	28 Jul 2004 21:26:15 -0000
@@ -270,7 +270,6 @@ docs/libplanner/Makefile
 docs/user-guide/Makefile
 docs/user-guide/C/Makefile
 docs/sql/Makefile
-examples/Makefile
 po/Makefile.in
 data/Makefile
 data/images/Makefile
Index: libplanner/Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/libplanner/Makefile.am,v
retrieving revision 1.7
diff -u -b -B -p -r1.7 Makefile.am
--- libplanner/Makefile.am	2 May 2004 13:30:16 -0000	1.7
+++ libplanner/Makefile.am	28 Jul 2004 21:26:16 -0000
@@ -2,7 +2,8 @@ INCLUDES = \
 	-I. -I$(top_srcdir) \
 	$(LIBPLANNER_CFLAGS) $(WARN_CFLAGS) \
 	-DMRP_STORAGEMODULEDIR=\""$(libdir)/planner/storage-modules"\" \
-	-DMRP_FILE_MODULES_DIR=\""$(libdir)/planner/file-modules"\"
+	-DMRP_FILE_MODULES_DIR=\""$(libdir)/planner/file-modules"\" \
+	-DDATADIR=\""$(datadir)"\"
 
 lib_LTLIBRARIES = libplanner-1.la
 
Index: libplanner/mrp-project.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-project.c,v
retrieving revision 1.10
diff -u -b -B -p -r1.10 mrp-project.c
Index: libplanner/mrp-sql.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-sql.c,v
retrieving revision 1.8
diff -u -b -B -p -r1.8 mrp-sql.c
--- libplanner/mrp-sql.c	25 Jun 2004 09:59:35 -0000	1.8
+++ libplanner/mrp-sql.c	28 Jul 2004 21:26:27 -0000
@@ -37,7 +37,7 @@
 #define REVISION "sql-storage-revision"
 
 /* Struct to keep calendar data before we can build the tree, create the
- * calendars and insert the in the project.
+ * calendars and insert them in the project.
  */
 typedef struct {
 	gint    id;
@@ -206,7 +206,7 @@ sql_get_last_error (GdaConnection *conne
 
 	error = (GdaError *) g_list_last (list)->data;
       
-	/* Poor user, she won't get localized messages */
+	/* FIXME: Poor user, she won't get localized messages */
 	error_txt = gda_error_get_description (error);
 
 	return error_txt;
@@ -430,7 +430,7 @@ sql_read_project (SQLData *data, gint pr
 	g_free (query);
 	
 	if (res == NULL) {
-		g_warning ("Couldn't get cursor for project %s.", 
+		g_warning ("DECLARE CURSOR command failed (project) %s.", 
 				sql_get_last_error (data->con));
 		goto out;
 	}
@@ -604,7 +604,7 @@ sql_read_property_specs (SQLData *data)
 	
 
 	if (res == NULL) {
-		g_warning ("DECLARE CURSOR command failed (propecty_specs) %s.",
+		g_warning ("DECLARE CURSOR command failed (propecty_type) %s.",
 				sql_get_last_error (data->con));
 		goto out;
 	}
@@ -612,7 +612,7 @@ sql_read_property_specs (SQLData *data)
 
 	res = sql_execute_query (data->con, "FETCH ALL in mycursor");
 	if (res == NULL) {
-		g_warning ("FETCH ALL failed for property_specs %s.", 
+		g_warning ("FETCH ALL failed for property_type %s.", 
 				sql_get_last_error (data->con));
 		goto out;
 	}
@@ -695,9 +695,10 @@ sql_read_property_specs (SQLData *data)
 						  TRUE /* FIXME: user_defined, should 
 							  be read from the file */);
 					
-			g_hash_table_insert (data->property_type_id_hash, GINT_TO_POINTER (property_type_id), property);
+			g_hash_table_insert (data->property_type_id_hash, 
+					     GINT_TO_POINTER (property_type_id), property);
 		} else {
-			/* Properties that are already added (e.g. cost). */
+			/* FIXME: Properties that are already added (e.g. cost). */
 			property = mrp_project_get_property (data->project, name, owner);
 			g_hash_table_insert (data->property_type_id_hash, GINT_TO_POINTER (property_type_id), property);
 		}
@@ -2146,6 +2147,7 @@ mrp_sql_load_project (MrpStorageSQL *sto
 	data = g_new0 (SQLData, 1);
 
 	data->project_id = -1;
+	/* data->project_id = project_id; */
 	data->day_id_hash = g_hash_table_new (NULL, NULL);
 	data->calendar_id_hash = g_hash_table_new (NULL, NULL);
 	data->group_id_hash = g_hash_table_new (NULL, NULL);
Index: libplanner/mrp-storage-sql.c
===================================================================
RCS file: /cvs/gnome/planner/libplanner/mrp-storage-sql.c,v
retrieving revision 1.2
diff -u -b -B -p -r1.2 mrp-storage-sql.c
Index: src/Makefile.am
===================================================================
RCS file: /cvs/gnome/planner/src/Makefile.am,v
retrieving revision 1.16
diff -u -b -B -p -r1.16 Makefile.am
--- src/Makefile.am	21 Jun 2004 20:57:05 -0000	1.16
+++ src/Makefile.am	28 Jul 2004 21:26:29 -0000
@@ -12,6 +12,8 @@ INCLUDES = \
 	-DGLADEDIR=\""$(datadir)/planner/glade"\"		\
 	-DMRP_VIEWDIR=\""$(libdir)/planner/views"\"		\
 	-DMRP_PLUGINDIR=\""$(libdir)/planner/plugins"\"		\
+	-DSQL_DIR=\""$(datadir)/planner/sql"\"			\
+	-DVERSION=\""$(VERSION)"\" 				\
 	$(GNOMEUI_UNSTABLE)
 
 if HAVE_PYTHON_PLUGIN
Index: src/planner-sql-plugin.c
===================================================================
RCS file: /cvs/gnome/planner/src/planner-sql-plugin.c,v
retrieving revision 1.12
diff -u -b -B -p -r1.12 planner-sql-plugin.c
--- src/planner-sql-plugin.c	25 Jun 2004 09:59:35 -0000	1.12
+++ src/planner-sql-plugin.c	28 Jul 2004 21:26:32 -0000
@@ -77,6 +77,10 @@ static void     sql_plugin_save         
 static GdaDataModel * 
                 sql_execute_query              (GdaConnection      *con, 
 					        gchar              *query);
+
+/* FIXME: The same in mrp-sql.c. Create a SQL API in libplanner? */ 
+static const gchar * sql_get_last_error        (GdaConnection      *connection);
+
 void            plugin_init                    (PlannerPlugin      *plugin,
 						PlannerWindow      *main_window);
 void            plugin_exit                    (void);
@@ -112,6 +116,23 @@ sql_execute_query (GdaConnection *con, g
 	return res;
 }
 
+static const gchar *
+sql_get_last_error (GdaConnection *connection)
+{
+	GList       *list;
+	GdaError    *error;
+	const gchar *error_txt;
+
+	list = (GList *) gda_connection_get_errors (connection);
+
+	error = (GdaError *) g_list_last (list)->data;
+      
+	/* FIXME: Poor user, she won't get localized messages */
+	error_txt = gda_error_get_description (error);
+
+	return error_txt;
+}
+
 
 /**
  * Helper to get an int.
@@ -291,6 +312,347 @@ row_activated_cb (GtkWidget         *tre
 	gtk_widget_activate (ok_button);
 }
 
+/* Planner versions:
+   1.x is always lower than 2.x.
+   0.6 is lower than 0.11 
+   If 0.11.90 we don't look ".90".
+*/
+static gboolean
+is_newer_version (const gchar *version_new_txt, 
+		  const gchar *version_old_txt)
+{
+	guint   subversion_old, subversion_new;
+	guint   version_old, version_new;
+	gchar **versionv_new, **versionv_old;
+
+	g_return_val_if_fail (version_new_txt != NULL && 
+			      version_old_txt != NULL, FALSE);
+	
+	version_old = g_ascii_strtod (version_old_txt, NULL);
+	version_new = g_ascii_strtod (version_new_txt, NULL);
+
+	if (version_new > version_old) {
+		return TRUE;
+	}
+	else if (version_old > version_new) {
+		return FALSE;
+	}
+	
+	/* Need to check subversion */
+	versionv_old = g_strsplit (version_old_txt,".",-1);
+	versionv_new = g_strsplit (version_new_txt,".",-1);
+
+	subversion_old = g_ascii_strtod (versionv_old[1], NULL);
+	subversion_new = g_ascii_strtod (versionv_new[1], NULL);
+
+	g_strfreev (versionv_new);
+	g_strfreev (versionv_old);
+
+	if (subversion_new > subversion_old) {
+		return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+check_database_tables (GdaConnection *conn,
+		       PlannerPlugin *plugin)
+{
+	GtkWindow    *window;
+	GdaDataModel *res;
+	GtkWidget    *dialog;
+	gint          result;
+	GDir*         dir;
+	const gchar  *name;
+	gboolean      upgradable = FALSE;
+	gboolean      create_tables;
+	gboolean      can_create_tables = FALSE;
+	gchar        *max_version_database;
+	gchar        *max_version_upgrade;
+	gchar        *upgrade_file = NULL;
+	gchar        *database_file = NULL;
+	const gchar  *database_name;
+	gboolean      retval = FALSE;
+
+	max_version_database = g_strdup ("0.0");
+	max_version_upgrade = g_strdup ("0.0");
+	database_name = gda_connection_get_database (conn);
+
+	window = GTK_WINDOW (plugin->main_window);
+
+	/* Check if tables exist */
+	res = sql_execute_query (conn, "SELECT proj_id FROM project");		
+	if (res == NULL) {
+		create_tables = TRUE;
+	} else {
+		create_tables = FALSE;
+		g_free (res);
+	}
+
+	/* Check for tables */
+	dir = g_dir_open (SQL_DIR, 0, NULL);
+	while ((name = g_dir_read_name (dir)) != NULL) {
+		gchar **namev = NULL, **versionv = NULL;
+		gchar  *version;
+		gchar  *sql_file = g_build_filename (SQL_DIR, name, NULL);
+
+		if (strncmp (name + strlen (name) - 4, ".sql", 4) != 0) {
+			g_warning ("Strange file in SQL data Planner directory: %s%s", 
+				   SQL_DIR, name);
+			continue;
+		}
+
+		/* Find version between "-" and ".sql" */
+		namev = g_strsplit (sql_file,"-",-1);
+		/* Upgrade: 2 versions in file */
+		if (namev[1] && namev[2]) {
+			versionv = g_strsplit (namev[2],".sql",-1);
+			if (is_newer_version (versionv[0], namev[1])) {
+				if (!strcmp (namev[1], VERSION)) {
+					upgradable = TRUE;
+					if (is_newer_version (versionv[0], 
+							      max_version_upgrade)) {
+						if (upgrade_file) {
+							g_free (upgrade_file);
+						}
+						upgrade_file = g_strdup (sql_file);
+						g_free (max_version_upgrade);
+						max_version_upgrade = g_strdup (versionv[0]);
+					}
+				}
+			} else {
+				g_warning ("Incorrect upgrade file name: %s", sql_file);
+			}
+		}
+		/* Create tables */
+		else if (namev[1]) {
+			versionv = g_strsplit (namev[1],".sql",-1);
+			if (is_newer_version (versionv[0], max_version_database)) {
+				if (database_file) {
+					g_free (database_file);
+				}
+				database_file = g_strdup (sql_file);
+				g_free (max_version_database);
+				max_version_database = g_strdup (versionv[0]);
+			}
+			
+			can_create_tables = TRUE;
+			version = g_strdup (versionv[0]);
+			g_free (version);
+			
+		} else {
+			if (!database_file) {
+				database_file = g_strdup (sql_file);
+			}
+			g_warning ("File with no version: %s", sql_file);
+			can_create_tables = TRUE;
+		}
+		if (versionv) {
+			g_strfreev (versionv);
+		}
+		if (namev) {
+			g_strfreev (namev);
+		}
+		g_free (sql_file);
+	}
+
+	if (!upgradable && !create_tables) {
+		retval = TRUE;
+	}
+	else if (upgradable && !create_tables) {
+		gchar        *contents;
+
+		dialog = gtk_message_dialog_new (window,
+						 GTK_DIALOG_DESTROY_WITH_PARENT,
+						 GTK_MESSAGE_QUESTION,
+						 GTK_BUTTONS_YES_NO,
+						 _("Database %s need to be upgraded to version: %s."
+						   " Please backup the database before upgrading."
+						   " Do you want to continue?"),
+						 database_name, max_version_upgrade);
+		
+		result = gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		if (result == GTK_RESPONSE_YES) {
+			g_file_get_contents (upgrade_file, &contents, NULL, NULL);
+			res = sql_execute_query (conn, contents);
+			g_free (contents);
+			if (res == NULL) {
+				dialog = gtk_message_dialog_new (window,
+								 GTK_DIALOG_DESTROY_WITH_PARENT,
+								 GTK_MESSAGE_WARNING,
+								 GTK_BUTTONS_CLOSE,
+								 _("Could not create tables in database %s. File %s is not correct."
+								   "\n\nDatabase error: \n%s"),
+								 database_name, upgrade_file,
+								 sql_get_last_error (conn));
+				
+				gtk_dialog_run (GTK_DIALOG (dialog));
+				gtk_widget_destroy (dialog);
+				retval = FALSE;
+			} else {
+				retval = TRUE;
+				g_free (res);
+			}
+		} else {
+			retval = FALSE;
+		}
+		g_free (upgrade_file);
+	}
+
+	else if (create_tables && !can_create_tables) {
+		g_warning ("Need to create tables but no database file");
+		retval = FALSE;
+	}
+
+	else if (create_tables && can_create_tables) {
+		gchar  *contents;
+
+		dialog = gtk_message_dialog_new (window,
+						 GTK_DIALOG_DESTROY_WITH_PARENT,
+						 GTK_MESSAGE_QUESTION,
+						 GTK_BUTTONS_YES_NO,
+						 _("Database %s is not setup for Planner. "
+						   "Do you want to do that?"),
+						 database_name);
+		
+		result = gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		
+		if (result == GTK_RESPONSE_YES) {
+			g_file_get_contents (database_file, &contents, NULL, NULL);
+			res = sql_execute_query (conn, contents);
+			g_free (contents);
+			if (res == NULL) {
+				dialog = gtk_message_dialog_new (window,
+								 GTK_DIALOG_DESTROY_WITH_PARENT,
+								 GTK_MESSAGE_WARNING,
+								 GTK_BUTTONS_CLOSE,
+								 _("Can't create tables in database %s"),
+								 database_name);
+				
+				result = gtk_dialog_run (GTK_DIALOG (dialog));
+				gtk_widget_destroy (dialog);
+				retval = FALSE;
+			} else {
+				g_free (res);
+				retval = TRUE;
+			}
+		}
+		g_free (database_file);
+	}
+	
+	g_free (max_version_upgrade);
+	g_free (max_version_database);
+	return retval;
+}
+
+/* Try to create the database */
+static gboolean
+create_database (const gchar   *dsn_name,
+		 const gchar   *db_name,
+		 PlannerPlugin *plugin)
+{
+	GtkWidget         *dialog;
+	GtkWindow         *window;
+	guint              result;
+	gboolean           retval;
+	GdaConnection     *conn;
+	GdaClient         *client;
+	GdaDataSourceInfo *dsn;
+	gchar             *cnc_string_orig;
+	/* FIXME: In postgresql we use template1 as the connection database */
+	gchar             *init_database = "template1";
+	gchar             *query;
+
+	dsn = gda_config_find_data_source (dsn_name);
+	cnc_string_orig = dsn->cnc_string;
+	retval = FALSE;
+
+	window = GTK_WINDOW (plugin->main_window);
+
+	/* Use same data but changing the database */
+	dsn->cnc_string = g_strdup_printf ("DATABASE=%s", init_database); 
+	gda_config_save_data_source_info (dsn);
+
+	client = gda_client_new ();
+	conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0);
+	if (conn == NULL) {
+		g_warning ("Can't connect to database server in order to check/create the database: %s", cnc_string_orig);
+	} else {
+		dialog = gtk_message_dialog_new (window,
+						 GTK_DIALOG_DESTROY_WITH_PARENT,
+						 GTK_MESSAGE_QUESTION,
+						 GTK_BUTTONS_YES_NO,
+						 _("Database %s is not setup for Planner. "
+						   "Do you want to do that?"),
+						 db_name);
+		
+		result = gtk_dialog_run (GTK_DIALOG (dialog));
+		gtk_widget_destroy (dialog);
+		
+		if (result == GTK_RESPONSE_YES) {
+			query = g_strdup_printf ("CREATE DATABASE %s WITH ENCODING = 'UTF8'", 
+						 db_name); 
+			sql_execute_query (conn, query);
+			g_free (query);
+			/* FIXME: Tables will need the group: dirty relation between 
+			   code and tables definitions in sql file.*/
+			query = g_strdup_printf ("CREATE GROUP planner WITH USER %s", 
+						 gda_connection_get_username (conn));
+			sql_execute_query (conn, query);
+			g_free (query);
+			retval = TRUE;
+		} else {
+			retval = FALSE;
+		}
+		gda_connection_close (conn);
+		g_object_unref (client);
+	}
+	g_free (dsn->cnc_string);
+	dsn->cnc_string = cnc_string_orig;
+	gda_config_save_data_source_info (dsn);
+
+	return retval;
+}
+
+/* Test database status: database exists, correct tables, correct version */
+static GdaConnection *
+sql_get_tested_connection (const gchar   *dsn_name,
+			   const gchar   *db_name,
+			   GdaClient     *client,
+			   PlannerPlugin *plugin) 
+{
+	GdaConnection *conn;
+	gchar         *str;
+
+	conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0);
+
+	if (conn == NULL) {
+		if (!create_database (dsn_name, db_name, plugin)) {
+			str = g_strdup_printf (_("Connection to database '%s' failed."), 
+					       db_name);
+			show_error_dialog (plugin, str);
+			conn = NULL;
+		} else {
+			conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0);
+		}
+	}
+
+	if (conn != NULL) {
+		if (!check_database_tables (conn, plugin)) {		
+			str = g_strdup_printf (_("Test to tables in database '%s' failed."), db_name);
+			show_error_dialog (plugin, str);
+			g_free (str);
+			gda_connection_close (conn);
+			conn = NULL;	
+		}
+	}
+
+	/* g_object_unref (client); */
+	return conn;
+}
+
 /**
  * Display a list with projects and let the user select one. Returns the project
  * id of the selected one.
@@ -306,7 +668,6 @@ sql_plugin_retrieve_project_id (PlannerP
 	GdaConnection     *conn;
 	GdaDataModel      *res;
 	GdaClient         *client;
-	gchar             *str;
 	GladeXML          *gui;
 	GtkWidget         *dialog;
 	GtkWidget         *treeview;
@@ -331,13 +692,9 @@ sql_plugin_retrieve_project_id (PlannerP
 	g_free (db_txt);
 
 	client = gda_client_new ();
+	conn = sql_get_tested_connection (dsn_name, database, client, plugin);
 	
-	conn = gda_client_open_connection (client, dsn_name, NULL, NULL, 0);
-
-	if (!GDA_IS_CONNECTION (conn)) {
-		str = g_strdup_printf (_("Connection to database '%s' failed."), database);
-		show_error_dialog (plugin, str);
-		g_free (str);
+	if (conn == NULL) {
 		return -1;
 	}
 
@@ -347,7 +704,6 @@ sql_plugin_retrieve_project_id (PlannerP
 		return -1;
 	}
 	g_object_unref (res);
-	res = NULL;
 
 	res = sql_execute_query (conn,
 				 "DECLARE mycursor CURSOR FOR SELECT proj_id, name,"
@@ -694,6 +1049,8 @@ sql_plugin_save (BonoboUIComponent *comp
 		 gpointer           user_data,
 		 const gchar       *cname)
 {
+	GdaClient     *client;
+	GdaConnection *conn;
 	PlannerPlugin  *plugin = user_data;
 	MrpProject    *project;
 	GObject       *object;
@@ -703,7 +1060,11 @@ sql_plugin_save (BonoboUIComponent *comp
 	gchar         *login = NULL;
 	gchar         *password = NULL;
 	gchar         *uri = NULL;
+	const gchar   *uri_plan = NULL;
 	GError        *error = NULL;
+	gchar         *db_txt;
+	const gchar   *dsn_name = "planner-auto";
+	const gchar   *provider = "PostgreSQL";
 		
 	project = planner_window_get_project (plugin->main_window);
 
@@ -717,19 +1078,56 @@ sql_plugin_save (BonoboUIComponent *comp
 		return;
 	}
 
+	db_txt = g_strdup_printf ("DATABASE=%s",database);
+	gda_config_save_data_source (dsn_name, 
+                                     provider, 
+                                     db_txt,
+                                     "planner project", login, password);
+	g_free (db_txt);
+	client = gda_client_new ();
+	conn = sql_get_tested_connection (dsn_name, database, client, plugin);
+	if (conn == NULL) {
+		g_object_unref (client);
+		return;
+	}
+	gda_connection_close (conn);
+	g_object_unref (client);
+
 	/* This code is prepared for getting support for selecting a project to
 	 * save over. Needs finishing though. Pass project id -1 for now (always
 	 * create a new project).
 	 */
-	uri = create_sql_uri (server, port, database, login, password, -1);
+	uri_plan = mrp_project_get_uri (project);
 
+	/* First time project */
+	if (uri_plan == NULL) {
+		uri = create_sql_uri (server, port, database, login, password, -1);	
 	if (!mrp_project_save_as (project, uri, FALSE, &error)) {
 		show_error_dialog (plugin, error->message);
 		g_clear_error (&error);
 		goto fail;
 	}
+		g_free (uri);
 	
+	} 
+	/* Project was in database */
+	else if (strncmp (uri_plan, "sql://", 6) == 0) {
+		if (!mrp_project_save (project, FALSE, &error)) { 
+			show_error_dialog (plugin, error->message);
+			g_clear_error (&error);
+			goto fail;
+		}
+	} 
+	/* Project wasn't in database */
+	else {
+		uri = create_sql_uri (server, port, database, login, password, -1);	
+		if (!mrp_project_save_as (project, uri, FALSE, &error)) { 
+			show_error_dialog (plugin, error->message);
+			g_clear_error (&error);
+			goto fail;
+		}
 	g_free (uri);
+	}
 		
 	object = G_OBJECT (plugin->main_window);
 	

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente



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