Commit reworked version of shp2pgsql-gui to the repository.

As per my email to postgis-devel, this commit contains a major reworking
of the inner core, with many bugfixes. The primary changes are:

- Elimination of FILENODE, since we can just use pointers to
  SHPLOADERCONFIG

- Abstract the configuration structures from the GUI interface

- Restrict entry to either drag/drop or file chooser

- Instead of constantly destroying/creating new dialogs, create
  them once and then just show/hide them (in particular this
  enables the file chooser to open at its previous directory)

- Add separate connection details and progress bar dialogs

- Rework both internals and GUI in preparation for adding dumper
  support

Note that the dumper integration changes are being worked on separately
and will be included in a later commit.

git-svn-id: http://svn.osgeo.org/postgis/trunk@8706 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Mark Cave-Ayland 2012-01-08 23:32:05 +00:00
parent 056116c0fa
commit 4daaecbc8e
13 changed files with 1693 additions and 2563 deletions

View file

@ -104,13 +104,10 @@ $(PGSQL2SHP-CLI): shpopen.o dbfopen.o getopt.o pgsql2shp-core.o shpcommon.o pgsq
$(SHP2PGSQL-CLI): shpopen.o dbfopen.o getopt.o shp2pgsql-core.o shpcommon.o shp2pgsql-cli.o safileio.o $(LIBLWGEOM)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $^ -o $@ $(GETTEXT_LDFLAGS) $(ICONV_LDFLAGS)
structure.o: structure.c structure.h
$(CC) $(CFLAGS) $(GTK_CFLAGS) -o $@ -c structure.c
shp2pgsql-gui.o: shp2pgsql-gui.c structure.h shp2pgsql-core.h shpcommon.h
shp2pgsql-gui.o: shp2pgsql-gui.c shp2pgsql-core.h shpcommon.h
$(CC) $(CFLAGS) $(GTK_CFLAGS) $(PGSQL_FE_CPPFLAGS) -o $@ -c shp2pgsql-gui.c
$(SHP2PGSQL-GUI): shpopen.o dbfopen.o shp2pgsql-core.o shpcommon.o shp2pgsql-gui.o getopt.o structure.o safileio.o $(LIBLWGEOM) $(GTK_WIN32_RES)
$(SHP2PGSQL-GUI): shpopen.o dbfopen.o shp2pgsql-core.o shpcommon.o shp2pgsql-gui.o getopt.o safileio.o pgsql2shp-core.o $(LIBLWGEOM) $(GTK_WIN32_RES)
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(GTK_WIN32_FLAGS) $^ -o $@ $(GTK_LIBS) $(ICONV_LDFLAGS) $(PGSQL_FE_LDFLAGS) $(GETTEXT_LDFLAGS)
installdir:

View file

@ -54,18 +54,6 @@ LOADER_OBJS= \
../pgsql2shp-core.o \
../shp2pgsql-core.o
# We test this variable later to see if we're building the GUI
gtk_build = @GTK_BUILD@
# If we are, define a variable so we can conditionally perform regression
# and also build an extra test file
ifneq ($(gtk_build),)
CFLAGS += -DGTK
OBJS += cu_list.o
LOADER_OBJS += ../structure.o
endif
# If we couldn't find the cunit library then display a helpful message
ifeq ($(CUNIT_LDFLAGS),)
all: requirements_not_met_cunit

View file

@ -1,337 +0,0 @@
/**********************************************************************
* $Id: cu_list.c 5674 2010-06-03 02:04:15Z mleslie $
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
* Copyright 2010 LISAsoft Pty Ltd
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
*
**********************************************************************/
#include "cu_list.h"
#include "cu_tester.h"
#include "../structure.h"
/*
typedef struct _GtkTreeIter GtkTreeIter;
struct _GtkTreeIter
{
gint stamp;
gpointer user_data;
gpointer user_data2;
gpointer user_data3;
}
*/
/* Test functions */
void test_append_file(void);
void test_find_file(void);
void test_traversal(void);
void test_remove_first(void);
void test_remove_middle(void);
void test_remove_last(void);
void test_find_index(void);
/*
** Called from test harness to register the tests in this file.
*/
CU_pSuite register_list_suite(void)
{
CU_pSuite pSuite;
pSuite = CU_add_suite("GUI Shapefile Loader File List Test", init_list_suite, clean_list_suite);
if (NULL == pSuite)
{
CU_cleanup_registry();
return NULL;
}
if (
(NULL == CU_add_test(pSuite, "test_append_file()", test_append_file))
||
(NULL == CU_add_test(pSuite, "test_find_file()", test_find_file))
||
(NULL == CU_add_test(pSuite, "test_traversal()", test_traversal))
||
(NULL == CU_add_test(pSuite, "test_remove_first()", test_remove_first))
||
(NULL == CU_add_test(pSuite, "test_remove_last()", test_remove_first))
||
(NULL == CU_add_test(pSuite, "test_remove_middle()", test_remove_middle))
||
(NULL == CU_add_test(pSuite, "test_find_index()", test_find_index))
)
{
CU_cleanup_registry();
return NULL;
}
return pSuite;
}
/*
** The suite initialization function.
** Create any re-used objects.
*/
int init_list_suite(void)
{
return 0;
}
/*
** The suite cleanup function.
** Frees any global objects.
*/
int clean_list_suite(void)
{
return 0;
}
void test_append_file(void)
{
FILENODE *node;
GtkTreeIter iter;
init_file_list();
node = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
destroy_file_list();
}
void test_find_file(void)
{
FILENODE *node;
FILENODE *keeper_node;
GtkTreeIter iter;
GtkTreeIter keeper_iter;
init_file_list();
node = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
keeper_node = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &keeper_iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file6", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file7", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = append_file("file8", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node);
node = find_file_by_iter(&keeper_iter);
CU_ASSERT_PTR_NOT_NULL(node);
CU_ASSERT_PTR_EQUAL(node, keeper_node);
destroy_file_list();
}
void test_traversal(void)
{
FILENODE *node[5];
FILENODE *current_node;
GtkTreeIter iter;
int i = 0;
init_file_list();
node[0] = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[0]);
node[1] = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[1]);
node[2] = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[2]);
node[3] = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[3]);
node[4] = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[4]);
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
}
void test_remove_first(void)
{
FILENODE *node[5];
FILENODE *current_node;
GtkTreeIter iter;
int i = 0;
init_file_list();
node[0] = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[0]);
node[1] = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[1]);
node[2] = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[2]);
node[3] = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[3]);
node[4] = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[4]);
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
remove_file(node[0]);
i = 1;
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
CU_ASSERT_EQUAL(i, 5);
}
void test_remove_last(void)
{
FILENODE *node[5];
FILENODE *current_node;
GtkTreeIter iter;
int i = 0;
init_file_list();
node[0] = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[0]);
node[1] = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[1]);
node[2] = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[2]);
node[3] = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[3]);
node[4] = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[4]);
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
remove_file(node[4]);
i = 0;
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 4);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
CU_ASSERT_EQUAL(i, 4);
}
void test_remove_middle(void)
{
FILENODE *node[5];
FILENODE *current_node;
GtkTreeIter iter;
int i = 0;
init_file_list();
node[0] = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[0]);
node[1] = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[1]);
node[2] = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[2]);
node[3] = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[3]);
node[4] = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[4]);
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
}
remove_file(node[3]);
i = 0;
current_node = get_next_node(NULL);
CU_ASSERT_PTR_NOT_NULL(current_node);
while (current_node != NULL)
{
CU_ASSERT_NOT_EQUAL(i, 5);
CU_ASSERT_PTR_EQUAL(current_node, node[i]);
current_node = get_next_node(current_node);
i++;
if (i == 3)
i++;
}
CU_ASSERT_EQUAL(i, 5);
destroy_file_list();
}
void test_find_index(void)
{
FILENODE *node[5];
FILENODE *current_node;
GtkTreeIter iter;
int index[11] = {4, 3, 2, 1, 0, 3, 2, 4, 0, 1, 1};
int i = 0;
init_file_list();
node[0] = append_file("file1", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[0]);
node[1] = append_file("file2", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[1]);
node[2] = append_file("file3", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[2]);
node[3] = append_file("file4", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[3]);
node[4] = append_file("file5", "schema", "table", "geom_column", "-1", 'c', &iter);
CU_ASSERT_PTR_NOT_NULL(node[4]);
for (i = 0; i < 11; i++)
{
current_node = find_file_by_index(index[i]);
CU_ASSERT_PTR_EQUAL(node[index[i]], current_node);
}
destroy_file_list();
}

View file

@ -1,29 +0,0 @@
/**********************************************************************
* $Id: cu_list.h 5674 2010-06-03 02:04:15Z mleslie $
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
* Copyright 2010 LISAsoft Pty Ltd
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
*
**********************************************************************/
#ifndef __cu_list_h__
#define __cu_list_h__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "CUnit/Basic.h"
/***********************************************************************
** for Computational Geometry Suite
*/
/* Admin functions */
int init_list_suite(void);
int clean_list_suite(void);
#endif /* __cu_list_h__ */

View file

@ -27,15 +27,6 @@ int main()
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
#ifdef GTK
/* Add the GUI algorithms suite to the registry */
if (NULL == register_list_suite())
{
CU_cleanup_registry();
return CU_get_error();
}
#endif
/* Add the shp2pgsql test suite */
if (NULL == register_shp2pgsql_suite())
{

View file

@ -1264,6 +1264,54 @@ ShpDumperCreate(SHPDUMPERCONFIG *config)
return state;
}
/* Generate the database connection string used by a state */
char *
ShpDumperGetConnectionStringFromConn(SHPCONNECTIONCONFIG *conn)
{
char *connstring;
int connlen;
connlen = 64 +
(conn->host ? strlen(conn->host) : 0) + (conn->port ? strlen(conn->port) : 0) +
(conn->username ? strlen(conn->username) : 0) + (conn->password ? strlen(conn->password) : 0) +
(conn->database ? strlen(conn->database) : 0);
connstring = malloc(connlen);
memset(connstring, 0, connlen);
if (conn->host)
{
strcat(connstring, " host=");
strcat(connstring, conn->host);
}
if (conn->port)
{
strcat(connstring, " port=");
strcat(connstring, conn->port);
}
if (conn->username)
{
strcat(connstring, " user=");
strcat(connstring, conn->username);
}
if (conn->password)
{
strcat(connstring, " password='");
strcat(connstring, conn->password);
strcat(connstring, "'");
}
if (conn->database)
{
strcat(connstring, " dbname=");
strcat(connstring, conn->database);
}
return connstring;
}
/* Connect to the database and identify the version of PostGIS (and any other
capabilities required) */
@ -1273,46 +1321,9 @@ ShpDumperConnectDatabase(SHPDUMPERSTATE *state)
PGresult *res;
char *connstring, *tmpvalue;
int connlen;
/* Generate database connection string */
connlen = 64 +
(state->config->conn->host ? strlen(state->config->conn->host) : 0) + (state->config->conn->port ? strlen(state->config->conn->port) : 0) +
(state->config->conn->username ? strlen(state->config->conn->username) : 0) + (state->config->conn->password ? strlen(state->config->conn->password) : 0) +
(state->config->conn->database ? strlen(state->config->conn->database) : 0);
connstring = malloc(connlen);
memset(connstring, 0, connlen);
if (state->config->conn->host)
{
strcat(connstring, " host=");
strcat(connstring, state->config->conn->host);
}
if (state->config->conn->port)
{
strcat(connstring, " port=");
strcat(connstring, state->config->conn->port);
}
if (state->config->conn->username)
{
strcat(connstring, " user=");
strcat(connstring, state->config->conn->username);
}
if (state->config->conn->password)
{
strcat(connstring, " password=");
strcat(connstring, state->config->conn->password);
}
if (state->config->conn->database)
{
strcat(connstring, " dbname=");
strcat(connstring, state->config->conn->database);
}
/* Generate the PostgreSQL connection string */
connstring = ShpDumperGetConnectionStringFromConn(state->config->conn);
/* Connect to the database */
state->conn = PQconnectdb(connstring);
@ -1457,7 +1468,7 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
query = malloc(250 + strlen(state->schema) + strlen(state->table));
sprintf(query, "SELECT a.attname, a.atttypid, "
"a.atttypmod FROM "
"a.atttypmod, a.attlen FROM "
"pg_attribute a, pg_class c, pg_namespace n WHERE "
"n.nspname = '%s' AND a.attrelid = c.oid AND "
"n.oid = c.relnamespace AND "
@ -1469,7 +1480,7 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
query = malloc(250 + strlen(state->table));
sprintf(query, "SELECT a.attname, a.atttypid, "
"a.atttypmod FROM "
"a.atttypmod, a.attlen FROM "
"pg_attribute a, pg_class c WHERE "
"a.attrelid = c.oid and a.attnum > 0 AND "
"a.atttypid != 0 AND "
@ -1516,6 +1527,8 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
state->dbffieldnames = malloc(sizeof(char *) * PQntuples(res));
state->dbffieldtypes = malloc(sizeof(int) * PQntuples(res));
state->pgfieldnames = malloc(sizeof(char *) * PQntuples(res));
state->pgfieldlens = malloc(sizeof(int) * PQntuples(res));
state->pgfieldtypmods = malloc(sizeof(int) * PQntuples(res));
state->fieldcount = 0;
int tmpint = 1;
@ -1523,7 +1536,7 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
{
char *ptr;
int pgfieldtype, pgtypmod;
int pgfieldtype, pgtypmod, pgfieldlen;
char *pgfieldname;
int dbffieldtype, dbffieldsize, dbffielddecs;
@ -1532,6 +1545,7 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
pgfieldname = PQgetvalue(res, i, 0);
pgfieldtype = atoi(PQgetvalue(res, i, 1));
pgtypmod = atoi(PQgetvalue(res, i, 2));
pgfieldlen = atoi(PQgetvalue(res, i, 3));
dbffieldtype = -1;
dbffieldsize = 0;
dbffielddecs = 0;
@ -1837,7 +1851,9 @@ ShpDumperOpenTable(SHPDUMPERSTATE *state)
state->dbffieldnames[state->fieldcount] = dbffieldname;
state->dbffieldtypes[state->fieldcount] = dbffieldtype;
state->pgfieldnames[state->fieldcount] = pgfieldname;
state->pgfieldlens[state->fieldcount] = pgfieldlen;
state->pgfieldtypmods[state->fieldcount] = pgtypmod;
state->fieldcount++;
}
}

View file

@ -141,6 +141,12 @@ typedef struct shp_dumper_state
/* PostgreSQL column names for all non-spatial fields */
char **pgfieldnames;
/* PostgreSQL column lengths for all non-spatial fields */
int *pgfieldlens;
/* PostgreSQL column typmods for all non-spatial fields */
int *pgfieldtypmods;
/* Number of non-spatial fields in DBF output file */
int fieldcount;
@ -203,6 +209,7 @@ void set_dumper_config_defaults(SHPDUMPERCONFIG *config);
char *shapetypename(int num);
SHPDUMPERSTATE *ShpDumperCreate(SHPDUMPERCONFIG *config);
char *ShpDumperGetConnectionStringFromConn(SHPCONNECTIONCONFIG *config);
int ShpDumperConnectDatabase(SHPDUMPERSTATE *state);
int ShpDumperOpenTable(SHPDUMPERSTATE *state);
int ShpDumperGetRecordCount(SHPDUMPERSTATE *state);

View file

@ -1030,6 +1030,7 @@ ShpLoaderOpenShape(SHPLOADERSTATE *state)
state->types = (DBFFieldType *)malloc(state->num_fields * sizeof(int));
state->widths = malloc(state->num_fields * sizeof(int));
state->precisions = malloc(state->num_fields * sizeof(int));
state->pgfieldtypes = malloc(state->num_fields * sizeof(char *));
state->col_names = malloc((state->num_fields + 2) * sizeof(char) * MAXFIELDNAMELEN);
/* Generate a string of comma separated column names of the form "(col1, col2 ... colN)" for the SQL
@ -1110,6 +1111,62 @@ ShpLoaderOpenShape(SHPLOADERSTATE *state)
state->field_names[j] = malloc(strlen(name) + 1);
strcpy(state->field_names[j], name);
/* Now generate the PostgreSQL type name string and width based upon the shapefile type */
switch (state->types[j])
{
case FTString:
state->pgfieldtypes[j] = malloc(strlen("varchar") + 1);
strcpy(state->pgfieldtypes[j], "varchar");
break;
case FTDate:
state->pgfieldtypes[j] = malloc(strlen("date") + 1);
strcpy(state->pgfieldtypes[j], "date");
break;
case FTInteger:
/* Determine exact type based upon field width */
if (state->config->forceint4 || (state->widths[j] >=5 && state->widths[j] < 10))
{
state->pgfieldtypes[j] = malloc(strlen("int4") + 1);
strcpy(state->pgfieldtypes[j], "int4");
}
else if (state->widths[j] < 5)
{
state->pgfieldtypes[j] = malloc(strlen("int2") + 1);
strcpy(state->pgfieldtypes[j], "int2");
}
else
{
state->pgfieldtypes[j] = malloc(strlen("numeric") + 1);
strcpy(state->pgfieldtypes[j], "numeric");
}
break;
case FTDouble:
/* Determine exact type based upon field width */
if (state->widths[j] > 18)
{
state->pgfieldtypes[j] = malloc(strlen("numeric") + 1);
strcpy(state->pgfieldtypes[j], "numeric");
}
else
{
state->pgfieldtypes[j] = malloc(strlen("float8") + 1);
strcpy(state->pgfieldtypes[j], "float8");
}
break;
case FTLogical:
state->pgfieldtypes[j] = malloc(strlen("boolean") + 1);
strcpy(state->pgfieldtypes[j], "boolean");
break;
default:
snprintf(state->message, SHPLOADERMSGLEN, _("Invalid type %x in DBF file"), state->types[j]);
return SHPLOADERERR;
}
strcat(state->col_names, "\"");
strcat(state->col_names, name);
@ -1147,13 +1204,13 @@ ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
for handling string resizing during append */
sb = stringbuffer_create();
stringbuffer_clear(sb);
/* Set the client encoding if required */
if (state->config->encoding)
{
stringbuffer_aprintf(sb, "SET CLIENT_ENCODING TO UTF8;\n");
}
/* Use SQL-standard string escaping rather than PostgreSQL standard */
stringbuffer_aprintf(sb, "SET STANDARD_CONFORMING_STRINGS TO ON;\n");
@ -1222,57 +1279,18 @@ ShpLoaderGetSQLHeader(SHPLOADERSTATE *state, char **strheader)
{
stringbuffer_aprintf(sb, ",\n\"%s\" ", state->field_names[j]);
switch (state->types[j])
/* First output the raw field type string */
stringbuffer_aprintf(sb, "%s", state->pgfieldtypes[j]);
/* Some types do have typmods though... */
if (!strcmp("varchar", state->pgfieldtypes[j]))
stringbuffer_aprintf(sb, "(%d)", state->widths[j]);
if (!strcmp("numeric", state->pgfieldtypes[j]))
{
case FTString:
/* use DBF attribute size as maximum width */
stringbuffer_aprintf(sb, "varchar(%d)", state->widths[j]);
break;
case FTDate:
stringbuffer_aprintf(sb, "date");
break;
case FTInteger:
/* Determine exact type based upon field width */
if (state->config->forceint4)
{
stringbuffer_aprintf(sb, "int4");
}
else if (state->widths[j] < 5)
{
stringbuffer_aprintf(sb, "int2");
}
else if (state->widths[j] < 10)
{
stringbuffer_aprintf(sb, "int4");
}
else
{
stringbuffer_aprintf(sb, "numeric(%d,0)", state->widths[j]);
}
break;
case FTDouble:
/* Determine exact type based upon field width */
if (state->widths[j] > 18)
{
stringbuffer_aprintf(sb, "numeric");
}
else
{
stringbuffer_aprintf(sb, "float8");
}
break;
case FTLogical:
stringbuffer_aprintf(sb, "boolean");
break;
default:
snprintf(state->message, SHPLOADERMSGLEN, _("Invalid type %x in DBF file"), state->types[j]);
stringbuffer_destroy(sb);
return SHPLOADERERR;
/* Doubles we just allow PostgreSQL to auto-detect the size */
if (state->types[j] != FTDouble)
stringbuffer_aprintf(sb, "(%d,0)", state->widths[j]);
}
}
@ -1758,7 +1776,8 @@ void
ShpLoaderDestroy(SHPLOADERSTATE *state)
{
/* Destroy a state object created with ShpLoaderOpenShape */
int i;
if (state != NULL)
{
if (state->hSHPHandle)
@ -1767,12 +1786,18 @@ ShpLoaderDestroy(SHPLOADERSTATE *state)
DBFClose(state->hDBFHandle);
if (state->field_names)
{
int i;
for (i = 0; i < state->num_fields; i++)
free(state->field_names[i]);
free(state->field_names);
}
if (state->pgfieldtypes)
{
for (i = 0; i < state->num_fields; i++)
free(state->pgfieldtypes[i]);
free(state->pgfieldtypes);
}
if (state->types)
free(state->types);
if (state->widths)
@ -1786,6 +1811,3 @@ ShpLoaderDestroy(SHPLOADERSTATE *state)
free(state);
}
}

View file

@ -187,6 +187,9 @@ typedef struct shp_loader_state
int *widths;
int *precisions;
/* Pointer to an array of PostgreSQL field types */
char **pgfieldtypes;
/* String containing colume name list in the form "(col1, col2, col3 ... , colN)" */
char *col_names;

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,9 @@
*
**********************************************************************/
#ifndef SHPCOMMON_H
#define SHPCOMMON_H
typedef struct shp_connection_state
{
/* PgSQL username to log in with */
@ -31,3 +34,5 @@ typedef struct shp_connection_state
/* External shared functions */
char *escape_connection_string(char *str);
#endif

View file

@ -1,252 +0,0 @@
/**********************************************************************
* $Id$
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
* Copyright 2010 LISAsoft Pty Ltd <mark.leslie@lisasoft.com>
*
* This is free softwark; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
*
* This file contains functions used to manage the basic elements
* stored withing the shp2pgsql-gui.c list item. These were separated
* out for ease of testing.
*
*********************************************************************/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "structure.h"
FILENODE *file_list_head = NULL;
FILENODE *file_list_tail = NULL;
void
init_file_list(void)
{
file_list_head = malloc(sizeof(FILENODE));
file_list_tail = malloc(sizeof(FILENODE));
file_list_head->filename = NULL;
file_list_head->schema = NULL;
file_list_head->table = NULL;
file_list_head->geom_column = NULL;
file_list_head->srid = NULL;
file_list_head->mode = '\0';
file_list_head->prev = NULL;
file_list_head->next = file_list_tail;
file_list_tail->filename = NULL;
file_list_tail->schema = NULL;
file_list_tail->table = NULL;
file_list_tail->geom_column = NULL;
file_list_tail->srid = NULL;
file_list_tail->mode = '\0';
file_list_tail->prev = file_list_head;
file_list_tail->next = NULL;
}
void
destroy_file_list(void)
{
FILENODE *node = get_next_node(NULL);
while (node != NULL)
{
remove_file(node);
node = get_next_node(NULL);
}
if (file_list_head != NULL)
{
file_list_head->next = NULL;
file_list_head->prev = NULL;
free(file_list_head);
}
if (file_list_tail != NULL)
{
file_list_tail->next = NULL;
file_list_tail->prev = NULL;
free(file_list_tail);
}
}
FILENODE*
append_file_node(void)
{
if (file_list_head == NULL || file_list_tail == NULL)
{
init_file_list();
}
FILENODE *new_node = malloc(sizeof(FILENODE));
new_node->filename = NULL;
new_node->schema = NULL;
new_node->table = NULL;
new_node->geom_column = NULL;
new_node->srid = NULL;
new_node->mode = '\0';
new_node->tree_iterator = NULL;
new_node->next = file_list_tail;
new_node->prev = file_list_tail->prev;
file_list_tail->prev->next = new_node;
file_list_tail->prev = new_node;
return new_node;
}
FILENODE*
append_file(char *filename, char *schema, char *table,
char *geom_column, char *srid, char mode,
GtkTreeIter *tree_iterator)
{
FILENODE *new_file = append_file_node();
/*
* I have no reason to believe that freeing char*'s in the struct will
* not harm the ui and vice versa, so I'm avoiding the problem by dup'ing.
*/
new_file->filename = strdup(filename);
new_file->schema = strdup(schema);
new_file->table = strdup(table);
new_file->geom_column = strdup(geom_column);
new_file->srid = strdup(srid);
new_file->mode = mode;
new_file->tree_iterator = tree_iterator;
return new_file;
}
FILENODE*
find_file_by_iter(GtkTreeIter *tree_iterator)
{
FILENODE *current_node;
if (file_list_head == NULL)
{
return NULL;
}
current_node = file_list_head->next;
while (current_node != NULL && current_node != file_list_tail)
{
if (current_node->tree_iterator == tree_iterator)
{
return current_node;
}
current_node = current_node->next;
}
return NULL;
}
FILENODE*
find_file_by_index(int index)
{
FILENODE *current_node;
int i = 0;
if (file_list_head == NULL)
{
return NULL;
}
current_node = file_list_head->next;
while (current_node != NULL && current_node != file_list_tail)
{
if (i == index)
{
return current_node;
}
current_node = current_node->next;
i++;
}
return NULL;
}
void
remove_file(FILENODE *remove_node)
{
if (remove_node == NULL
|| remove_node->next == NULL
|| remove_node->prev == NULL)
{
return;
}
remove_node->next->prev = remove_node->prev;
remove_node->prev->next = remove_node->next;
remove_node->next = NULL;
remove_node->prev = NULL;
if (remove_node->filename == NULL)
{
free(remove_node->filename);
remove_node->filename = NULL;
}
if (remove_node->schema == NULL)
{
free(remove_node->schema);
remove_node->schema = NULL;
}
if (remove_node->table == NULL)
{
free(remove_node->table);
remove_node->table = NULL;
}
if (remove_node->geom_column == NULL)
{
free(remove_node->geom_column);
remove_node->geom_column = NULL;
}
if (remove_node->srid == NULL)
{
free(remove_node->srid);
remove_node->srid = NULL;
}
free(remove_node);
}
FILENODE*
get_next_node(FILENODE *current)
{
if (file_list_head == NULL)
return NULL;
if (current == NULL)
current = file_list_head;
return (current->next != file_list_tail) ? current->next : NULL;
}
void
print_file_list_delegate(void (*printer)(const char *fmta, va_list apa), const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
(*printer)(fmt, ap);
va_end(ap);
return;
}
void
print_file_list(void (*printer)(const char *fmt, va_list ap))
{
FILENODE *current_node;
int i = 0;
print_file_list_delegate(printer, "File List:\n");
print_file_list_delegate(printer, "Head %p <-- %p --> %p\n", file_list_head->prev, file_list_head, file_list_head->next);
current_node = get_next_node(NULL);
while (current_node != NULL)
{
print_file_list_delegate(printer, " Node %d: %s\n", i++, current_node->filename);
print_file_list_delegate(printer, " %p <-- %p --> %p\n", current_node->prev, current_node, current_node->next);
current_node = get_next_node(current_node);
}
print_file_list_delegate(printer, "Tail %p <-- %p --> %p\n", file_list_tail->prev, file_list_tail, file_list_tail->next);
}

View file

@ -1,61 +0,0 @@
/**********************************************************************
* $Id$
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
* Copyright 2010 LISAsoft Pty Ltd <mark.leslie@lisasoft.com>
*
* This is free softwark; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
*
* This file contains struct and method definitions used to manage the
* basic elements stored withing the shp2pgsql-gui.c list item. These
* were separated out for ease of testing.
*
*********************************************************************/
#ifndef __PGIS_STRUCTURE_H__
#define __PGIS_STRUCTURE_H__
#include <gtk/gtktreemodel.h>
typedef struct file_node
{
char *filename;
char *schema;
char *table;
char *geom_column;
char *srid;
char mode;
GtkTreeIter *tree_iterator;
struct file_node *next;
struct file_node *prev;
} FILENODE;
void init_file_list(void);
void destroy_file_list(void);
FILENODE *append_file_node(void);
FILENODE *append_file(char *filename, char *schema, char *table,
char *geom_column, char *srid, char mode,
GtkTreeIter *tree_iterator);
FILENODE *find_file_by_iter(GtkTreeIter *tree_iterator);
FILENODE *find_file_by_index(int index);
void remove_file(FILENODE *remove_node);
void print_file_list_delegate(void (*printer)(const char *fmta, va_list apa), const char *fmt, ...);
/*
* This is a debugging function, it shouldn't really be used for
* general status output. It takes a function pointer of the same
* signature as vprintf (hint).
*/
void print_file_list(void (*printer)(const char *fmt, va_list ap));
/*
* This will return the next node after the current node.
* If the current is null, it will return the first node. Returns NULL
* if the list is uninitialised, empty or if the current node is the last node.
*/
FILENODE *get_next_node(FILENODE *current);
#endif /* __PGIS_STRUCTURE_H__ */