/* * dbMetrix Database Tool v0.1 * Copyright (c) 1998 David E. Storey * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "config.h" #include "global.h" #include #define DBX_PGSQL(conn) (dbx_pgSQL *)conn typedef struct { PGconn *conn; char *host; char *user; char *pass; char *port; } dbx_pgSQL; /* prototypes */ void close_pgSQL(dataSource *dbconn); int create_db_pgSQL(dataSource *conn, char *database); void create_pgSQL_addDialog(GtkWidget *dWindow, GtkWidget *notebook, int *curpage); void create_pgSQL_dsEntry(GtkWidget *widget); int drop_db_pgSQL(dataSource *conn, char *database); void query_pgSQL(dataSource *conn, char *query); void refresh_pgSQL(GtkWidget *treeItem, gpointer data); GtkWidget *result_pgSQL(PGresult *result, int nIdCol, void(*cb)()); void init_pgSQL(void); void close_pgSQL(dataSource *dbconn) { dbx_pgSQL *conn = DBX_PGSQL(dbconn->info); PQfinish(conn->conn); g_free(conn->host); } int create_db_pgSQL(dataSource *conn, char *database) { dbx_pgSQL *dbconn = DBX_PGSQL(conn->info); char query[256]; PGresult *result = NULL; sprintf(query, "create database %s", database); result = PQexec(dbconn->conn, query); if (PQstatus(dbconn->conn) == CONNECTION_BAD) { s_print(PQerrorMessage(dbconn->conn)); return(FALSE); } return(TRUE); } void create_pgSQL_addDialog(GtkWidget *dWindow, GtkWidget *notebook, int *curpage) { dbx_Dialog entries[] = { {"Host:", "pgSQL_Host", FALSE}, {"Username:", "pgSQL_User", FALSE}, {"Password:", "pgSQL_Pass", TRUE}, {"Database:", "pgSQL_Database", FALSE}, {"Port:", "pgSQL_Port", FALSE} }; create_dialogs(dWindow, notebook, curpage, pgSQL, "PostgreSQL", entries, sizeof(entries)/sizeof(entries[0])); } void create_pgSQL_dsEntry(GtkWidget *widget) { dbx_pgSQL *dbconn; char *host, *user, *pass, *database, *port; char name[256]; int i; host = get_entry_text(widget, "pgSQL_Host", FALSE); user = get_entry_text(widget, "pgSQL_User", FALSE); pass = get_entry_text(widget, "pgSQL_Pass", TRUE); port = get_entry_text(widget, "pgSQL_Port", FALSE); database = get_entry_text(widget, "pgSQL_Database", FALSE); if (!database) database = "template1"; g_snprintf(name, 256, "pgsql://%s", host ? host : "localhost"); /* check for another tree entry */ if (fetch_ds_key(name)) return; /* connect to server */ dbconn = DBX_PGSQL(g_malloc(sizeof(dbx_pgSQL))); dbconn->conn = PQsetdbLogin(host, port, NULL, NULL, database, user, pass); if (PQstatus(dbconn->conn) != CONNECTION_BAD) { dbconn->host = g_strdup(host); dbconn->user = g_strdup(user); dbconn->pass = g_strdup(pass); dbconn->port = g_strdup(port); /* create tree Item */ ds_add(name, dbconn, pgSQL, Host); /* save alias */ for (i = 0; i < cntAlias; i++) { if (strcmp(infAlias[i].alias, crntAlias) == 0) break; } if (i < 64) { if (i == cntAlias) cntAlias++; regist_db_alias(i, host, user, pass, database, port); save_db_alias(); } } else { s_print(PQerrorMessage(dbconn->conn)); g_free(dbconn); } } int drop_db_pgSQL(dataSource *conn, char *database) { char query[256]; dbx_pgSQL *dbconn = DBX_PGSQL(conn->info); g_snprintf(query, 256, "DROP DATABASE %s", database); PQexec(dbconn->conn, query); if (PQstatus(dbconn->conn) == CONNECTION_BAD) { s_print(PQerrorMessage(dbconn->conn)); return(FALSE); } return(TRUE); } void query_pgSQL(dataSource *conn, char *query) { dbx_pgSQL *dbconn; PGresult *result = NULL; if (conn && query) dbconn = DBX_PGSQL(conn->info); else return; result = PQexec(dbconn->conn, query); if (PQstatus(dbconn->conn) == CONNECTION_BAD) { s_print(PQerrorMessage(dbconn->conn)); return; } if (result) { query_window(result_pgSQL(result, -1, NULL)); PQclear(result); } else s_print(PQerrorMessage(dbconn->conn)); } void refresh_pgSQL(GtkWidget *treeItem, gpointer data) { node_ds *nodeInfo = (node_ds *)data; dbx_pgSQL *dbconn = DBX_PGSQL(nodeInfo->conn->info); PGresult *result = NULL; switch(nodeInfo->type) { case Host: result = PQexec(dbconn->conn, "SELECT * FROM pg_database ORDER BY datname"); break; case Database: PQfinish(dbconn->conn); dbconn->conn = PQsetdbLogin(dbconn->host, dbconn->port, NULL, NULL, nodeInfo->name, dbconn->user, dbconn->pass); if (PQstatus(dbconn->conn) == CONNECTION_BAD) { char mess[256]; g_snprintf(mess, 256, "Could not change to '%s' (%s)", nodeInfo->name, PQerrorMessage(dbconn->conn)); s_print(mess); break; } result = PQexec(dbconn->conn, "SELECT relname FROM pg_class WHERE relkind = 'r' AND relname !~ 'pg_' AND relname !~ '^xin[vx][0-9]+' ORDER BY relname"); break; case Table: if (!pref_get("dstree.table.show_fields")) break; case Field: break; } if (result) { int i; if (PQntuples(result) > 0) add_subtree(treeItem); for (i = 0; i < PQntuples(result); i++) tree_refresh(treeItem, nodeInfo, i, PQgetvalue(result, i, 0)); PQclear(result); } } GtkWidget * result_pgSQL(PGresult *result, int nIdCol, void(*cb)()) { GtkWidget *clist = NULL; unsigned *maxflengths; int i, total = 0; if (!result || !PQntuples(result)) return(NULL); maxflengths = (unsigned *)calloc(PQntuples(result), sizeof(unsigned)); clist = gtk_clist_new(PQnfields(result)); for (i = 0; i < PQnfields(result); i++) { gtk_clist_set_column_title(GTK_CLIST(clist), i, PQfname(result, i)); maxflengths[i] = PQfname(result, i) ? strlen(PQfname(result, i)) : 0; } for (i = 0; i < PQntuples(result); i++) { int j; if (nIdCol >= 0) gtk_clist_set_row_data(GTK_CLIST(clist), i, (gpointer *)atol(PQgetvalue(result, i, nIdCol))); gtk_clist_append(GTK_CLIST(clist), NULL); for (j = 0; j < PQnfields(result); j++) { char *value = PQgetvalue(result, i, j); int length = value ? strlen(value) : 0; gtk_clist_set_text(GTK_CLIST(clist), i, j, value); if (length > maxflengths[j]) maxflengths[j] = length; } } for (i = 0; i < PQnfields(result); i++) { total += maxflengths[i] * 8; gtk_clist_set_column_width(GTK_CLIST(clist), i, maxflengths[i] * 8); } gtk_object_set_data(GTK_OBJECT(clist), "width", (gpointer)total); gtk_object_set_data(GTK_OBJECT(clist), "height", (gpointer)PQntuples(result)); free(maxflengths); return(clist); } void init_pgSQL(void) { dbxMenuEntry pgsqlMenuHost[] = { {"create database", NULL, DBX_SIGNAL_FUNC(create_dbDialog), (gpointer)pgSQL}, {"disconnect", NULL, DBX_SIGNAL_FUNC(ds_close), (gpointer)TRUE} }; dbxMenuEntry pgsqlMenuDB[] = { {"drop database", NULL, DBX_SIGNAL_FUNC(drop_db), (gpointer)pgSQL} }; dsMenus[pgSQL].host = set_menu(pgsqlMenuHost, sizeof(pgsqlMenuHost)/sizeof(pgsqlMenuHost[0])); dsMenus[pgSQL].database = set_menu(pgsqlMenuDB, sizeof(pgsqlMenuDB)/sizeof(pgsqlMenuDB[0])); dsFuncs[pgSQL].close = close_pgSQL; dsFuncs[pgSQL].create_db = create_db_pgSQL; dsFuncs[pgSQL].create_dsEntry = create_pgSQL_dsEntry; dsFuncs[pgSQL].create_dsDialog = create_pgSQL_addDialog; dsFuncs[pgSQL].drop_db = drop_db_pgSQL; dsFuncs[pgSQL].exec_query = query_pgSQL; dsFuncs[pgSQL].refresh = refresh_pgSQL; }