Added the postgres reader. Closes patch #6388
authorJohn Darrington <john@darrington.wattle.id.au>
Mon, 4 Feb 2008 01:24:00 +0000 (01:24 +0000)
committerJohn Darrington <john@darrington.wattle.id.au>
Mon, 4 Feb 2008 01:24:00 +0000 (01:24 +0000)
configure.ac
doc/ChangeLog
doc/data-io.texi
doc/files.texi
src/data/ChangeLog
src/data/automake.mk
src/language/data-io/ChangeLog
src/language/data-io/get-data.c
src/ui/gui/automake.mk
src/ui/terminal/automake.mk
tests/automake.mk

index 5b8e1a933c99c0dec9e00149df042cd0e9a36ea8..cbf3d557f792391689927d69d74928e07cfb06b1 100644 (file)
@@ -47,6 +47,20 @@ fi
 AM_CONDITIONAL(WITHGUI, test x"$with_gui" != x"no")
 
 
+dnl Checks needed for psql reader
+AC_CHECK_PROG(psql_support, pg_config, yes, no)
+if test x"$psql_support" = x"yes" ; then 
+   AC_DEFINE([PSQL_SUPPORT], 1,
+   [Define to 1 if building in support for reading from postgres databases.])
+   PG_CFLAGS=-I`pg_config --includedir` 
+   AC_SUBST(PG_CFLAGS)
+   PG_LDFLAGS=-L`pg_config --libdir`
+   AC_SUBST(PG_LDFLAGS)
+   PG_LIBS=-lpq
+   AC_SUBST(PG_LIBS)
+fi
+AM_CONDITIONAL(PSQL_SUPPORT, test x"$psql_support" = x"yes")
+
 dnl Checks needed for gnumeric reader
 gnm_support=yes;
 PKG_CHECK_MODULES(LIBXML2, libxml-2.0,,
index c1fa40eb6c587b759847e7ef36a59b5dbf42a6b1..021e234345832587d5b76ce3bdbe4aa0453d0aae 100644 (file)
@@ -1,3 +1,9 @@
+2008-02-04 John Darrington <john@darrington.wattle.id.au>
+
+       * files.texi data-io.texi: Document the GET DATA TYPE=PSQL
+       option.  Thanks to Ben Pfaff for reviewing this text.
+
+
 2007-11-10  Ben Pfaff  <blp@gnu.org>
 
        * not-implemented.texi: Fix @include command so that it works
index 8ca251085df691f1cd7bef535e0c6f615f4f28b6..b6a3a6d2a4a5754f7962ca8ceb21bbd45cbc7a0f 100644 (file)
@@ -14,6 +14,8 @@ their sex, age, etc.@: and their responses are all data and the data
 pertaining to single respondent is a case.
 This chapter examines
 the PSPP commands for defining variables and reading and writing data.
+There are alternative commands to  read data from predefined sources
+such as system files or databases (@xref{GET, GET DATA}.)
 
 @quotation Note
 These commands tell PSPP how to read data, but the data will not
index a00d113d1fbc8d9c7e81cf15860f5fc88c6bb9fe..df01567eb956efd64df16ca7feff2e4fba3e93e9 100644 (file)
@@ -163,8 +163,7 @@ extension.
 
 @display
 GET DATA
-        /TYPE=@{GNM,TXT@}
-        /FILE=@{'file-name',file_handle@}
+        /TYPE=@{GNM,PSQL,TXT@}
         @dots{}additional subcommands depending on TYPE@dots{}
 @end display
 
@@ -181,19 +180,19 @@ PSPP currently supports the following file types:
 @item GNM
 Spreadsheet files created by Gnumeric (@url{http://gnumeric.org}).
 
+@item PSQL
+Relations from PostgreSQL databases (@url{http://postgresql.org}).
+
 @item TXT
 Textual data files in columnar and delimited formats.
 @end table
 
-The FILE subcommand is mandatory for all implemented file types.
-Specify the file to be read as a string file name or (for textual data
-only) a file handle (@pxref{File Handles}).
-
 Each supported file type has additional subcommands, explained in
 separate sections below.
 
 @menu
 * GET DATA /TYPE=GNM::
+* GET DATA /TYPE=PSQL::
 * GET DATA /TYPE=TXT::
 @end menu
 
@@ -222,6 +221,10 @@ If this cell is of string (text) format, then the width of the variable is
 determined from the length of the string it contains, unless the 
 ASSUMEDVARWIDTH subcommand is given.
 
+
+The FILE subcommand is mandatory. Specify the name of the file
+to be read.
+
 The SHEET subcommand specifies the sheet within the spreadsheet file to read.
 There are two forms of the SHEET subcommand.
 In the first form,
@@ -253,6 +256,61 @@ variables read  from the file.
 If omitted, the default value is determined from the length of the 
 string in the first spreadsheet cell for each variable.
 
+
+@node GET DATA /TYPE=PSQL
+@subsection Postgres Database Queries
+
+@display
+GET DATA /TYPE=PSQL
+         /CONNECT=@{connection info@}
+         /SQL=@{query@}
+         [/ASSUMEDVARWIDTH=n]
+         [/UNENCRYPTED].
+@end display
+
+@cindex postgres
+@cindex databases
+
+The PSQL type is used to import data from a postgres database server.
+The server may be located locally or remotely.
+Variables are automatically created based on the table column names 
+or the names specified in the SQL query.
+Postgres data types of high precision, will loose precision when 
+imported into PSPP.
+Not all the postgres data types are able to be represented in PSPP.
+If a datum cannot be represented a warning will be issued and that 
+datum will be set to SYSMIS.
+
+The CONNECT subcommand is mandatory.
+It is a string specifying the parameters of the database server from
+which the data should be fetched.
+The format of the string is given in the postgres manual
+@url{http://www.postgresql.org/docs/8.0/static/libpq.html#LIBPQ-CONNECT}.
+
+The SQL subcommand is mandatory.
+It must be a valid SQL string to retrieve data from the database.
+
+The ASSUMEDVARWIDTH subcommand specifies the maximum width of string
+variables read  from the database.
+If omitted, the default value is determined from the length of the 
+string in the first value read for each variable.
+
+The UNENCRYPTED subcommand allows data to be retrieved over an insecure
+connection.
+If the connection is not encrypted, and the UNENCRYPTED subcommand is not
+given, then an error will occur.
+Whether or not the connection is
+encrypted depends upon the underlying psql library and the 
+capabilities of the database server.
+
+The following syntax is an example:
+@example
+GET DATA /TYPE=PSQL
+     /CONNECT='host=example.com port=5432 dbname=product user=fred passwd=xxxx'
+     /SQL='select * from manufacturer'.
+@end example
+
+
 @node GET DATA /TYPE=TXT
 @subsection Textual Data Files
 
@@ -268,9 +326,11 @@ GET DATA /TYPE=TXT
 @cindex text files
 @cindex data files
 When TYPE=TXT is specified, GET DATA reads data in a delimited or
-fixed columnar format, much like DATA LIST (@pxref{DATA LIST}).  The
-FILE subcommand must be specified indicate the name or the file handle
-of the file to be read.
+fixed columnar format, much like DATA LIST (@pxref{DATA LIST}).
+
+The FILE subcommand is mandatory.  Specify the file to be read as 
+a string file name or (for textual data
+only) a file handle (@pxref{File Handles}).
 
 The ARRANGEMENT subcommand determines the file's basic format.
 DELIMITED, the default setting, specifies that fields in the input
index c1dd098a7cec668be7a2d43671627fe74ad7d7a4..012ffaf52a9c8e02de42ec0ea71a8c23c6531a95 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-02  John Darrington <john@darrington.wattle.id.au>
+
+       psql-reader.c psql-reader.h: New files.  Thanks to Ben Pfaff
+       for reviewing this code.
+       
 2008-02-02  Ben Pfaff  <blp@gnu.org>
 
        Patch #6347.
index e06798671236214607fabfc9fd5f99302b1e4e50..a432e300ca114049524a3a6839045a153358df4b 100644 (file)
@@ -1,7 +1,7 @@
 
 noinst_LIBRARIES += src/data/libdata.a
 
-src_data_libdata_a_CPPFLAGS = $(LIBXML2_CFLAGS) $(AM_CPPFLAGS)
+src_data_libdata_a_CPPFLAGS = $(LIBXML2_CFLAGS) $(PG_CFLAGS) $(AM_CPPFLAGS) 
 
 
 src_data_libdata_a_SOURCES = \
@@ -69,6 +69,8 @@ src_data_libdata_a_SOURCES = \
        src/data/por-file-reader.h \
        src/data/por-file-writer.c \
        src/data/por-file-writer.h \
+       src/data/psql-reader.c \
+       src/data/psql-reader.h \
        src/data/scratch-handle.c \
        src/data/scratch-handle.h \
        src/data/scratch-reader.c \
index 112efefba10c1030b518c45a712ada0c03cefac2..187d6464bab0e2db6f33ccfc960fe05338e46777 100644 (file)
@@ -1,3 +1,7 @@
+2008-02-02 John Darrington <john@darrington.wattle.id.au>
+
+       * get-data.c (cmd_get_data): Support PSQL type.
+
 2007-12-07  Ben Pfaff  <blp@gnu.org>
 
        Patch #6302.
index 7b38d62233e1d0ff76500c201f773a6141df5625..189054a507058c38b17b1ba027d0f69b5a995613 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 
    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
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 
 #include <data/gnumeric-reader.h>
+#include <data/psql-reader.h>
 
 #include <data/dictionary.h>
 #include <data/format.h>
@@ -38,6 +39,7 @@
 
 static int parse_get_gnm (struct lexer *lexer, struct dataset *);
 static int parse_get_txt (struct lexer *lexer, struct dataset *);
+static int parse_get_psql (struct lexer *lexer, struct dataset *);
 
 int
 cmd_get_data (struct lexer *lexer, struct dataset *ds)
@@ -53,11 +55,78 @@ cmd_get_data (struct lexer *lexer, struct dataset *ds)
     return parse_get_gnm (lexer, ds);
   else if (lex_match_id (lexer, "TXT"))
     return parse_get_txt (lexer, ds);
+  else if (lex_match_id (lexer, "PSQL"))
+    return parse_get_psql (lexer, ds);
 
   msg (SE, _("Unsupported TYPE %s"), lex_tokid (lexer));
   return CMD_FAILURE;
 }
 
+static int
+parse_get_psql (struct lexer *lexer, struct dataset *ds)
+{
+  struct psql_read_info psql;
+  psql.allow_clear = false;
+  psql.conninfo = NULL;
+  psql.str_width = -1;
+  ds_init_empty (&psql.sql);
+
+  lex_force_match (lexer, '/');
+
+  if (!lex_force_match_id (lexer, "CONNECT"))
+    goto error;
+
+  lex_force_match (lexer, '=');
+
+  if (!lex_force_string (lexer))
+    goto error;
+
+  psql.conninfo = strdup (ds_cstr (lex_tokstr (lexer)));
+
+  lex_get (lexer);
+
+  while (lex_match (lexer, '/') )
+    {
+      if ( lex_match_id (lexer, "ASSUMEDSTRWIDTH"))
+       {
+         lex_match (lexer, '=');
+         psql.str_width = lex_integer (lexer);
+         lex_get (lexer);
+       }
+      else if ( lex_match_id (lexer, "UNENCRYPTED"))
+       {
+         psql.allow_clear = true;
+       }
+      else if (lex_match_id (lexer, "SQL"))
+       {
+         lex_match (lexer, '=');
+         if ( ! lex_force_string (lexer) )
+           goto error;
+
+         ds_put_substring (&psql.sql,  lex_tokstr (lexer)->ss);
+         lex_get (lexer);
+       }
+     }
+  {
+    struct dictionary *dict = NULL;
+    struct casereader *reader = psql_open_reader (&psql, &dict);
+
+    if ( reader )
+      proc_set_active_file (ds, reader, dict);
+  }
+
+  ds_destroy (&psql.sql);
+  free (psql.conninfo);
+
+  return CMD_SUCCESS;
+
+ error:
+
+  ds_destroy (&psql.sql);
+  free (psql.conninfo);
+
+  return CMD_FAILURE;
+}
 
 static int
 parse_get_gnm (struct lexer *lexer, struct dataset *ds)
index 70cfefdbb04b1b2a91a0da35536554895361ed31..dfbc578574e1475cc9d69cf18978b21e7a20c6ef 100644 (file)
@@ -41,6 +41,7 @@ src_ui_gui_psppire_LDADD = \
        src/libpspp/libpspp.a \
        $(GTK_LIBS) \
        $(GLADE_LIBS) \
+       $(PG_LIBS) \
        gl/libgl.la \
        @LIBINTL@ @LIBREADLINE@
 
index 65cd23a33818f4b7b9f37e2c71ca33e8efd3e03e..0684e313caa0638369df94207516d0990a3ac97f 100644 (file)
@@ -33,6 +33,7 @@ src_ui_terminal_pspp_LDADD = \
        src/data/libdata.a \
        src/libpspp/libpspp.a \
        $(LIBXML2_LIBS) \
+       $(PG_LIBS) \
        $(LIBICONV) \
        gl/libgl.la \
        @LIBINTL@ @LIBREADLINE@
index aa9a92ffb35b685054f970dbdddb133eb97ba70b..6d0fd670e8142343e0879488648a84d240dac656 100644 (file)
@@ -154,6 +154,10 @@ if GNM_SUPPORT
 dist_TESTS += tests/command/get-data-gnm.sh 
 endif
 
+if PSQL_SUPPORT
+dist_TESTS += tests/command/get-data-psql.sh 
+endif
+
 nodist_TESTS = \
        tests/libpspp/abt-test \
        tests/libpspp/bt-test \