Reference count struct dictionary.
[pspp] / src / data / psql-reader.c
index 378a56affbb45f66fd04a889fcc8c53d5fc66941..4a49ba0cf92c413c551811b1ce1a87dd9e64c062 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 2008, 2009, 2010, 2011, 2012 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
 
 #include <config.h>
 
-#include <data/casereader-provider.h>
-#include <libpspp/message.h>
-#include <gl/xalloc.h>
-#include <data/dictionary.h>
+#include "data/psql-reader.h"
+
+#include <inttypes.h>
 #include <math.h>
 #include <stdlib.h>
 
-#include "psql-reader.h"
-#include "variable.h"
-#include "format.h"
-#include "calendar.h"
+#include "data/calendar.h"
+#include "data/casereader-provider.h"
+#include "data/dictionary.h"
+#include "data/format.h"
+#include "data/variable.h"
+#include "libpspp/i18n.h"
+#include "libpspp/message.h"
+#include "libpspp/misc.h"
+#include "libpspp/str.h"
 
-#include <inttypes.h>
-#include <libpspp/misc.h>
-#include <libpspp/str.h>
-
-#include "minmax.h"
+#include "gl/c-strcase.h"
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -229,6 +231,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   int n_fields, n_tuples;
   PGresult *qres = NULL;
   casenumber n_cases = CASENUMBER_MAX;
+  const char *encoding;
 
   struct psql_reader *r = xzalloc (sizeof *r);
   struct string query ;
@@ -249,7 +252,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
     }
 
   {
-    int ver_num;
+    int ver_num = 0;
     const char *vers = PQparameterStatus (r->conn, "server_version");
 
     sscanf (vers, "%d", &ver_num);
@@ -268,7 +271,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   {
     const char *dt =  PQparameterStatus (r->conn, "integer_datetimes");
 
-    r->integer_datetimes = ( 0 == strcasecmp (dt, "on"));
+    r->integer_datetimes = ( 0 == c_strcasecmp (dt, "on"));
   }
 
 #if USE_SSL
@@ -285,29 +288,32 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
 
   r->postgres_epoch = calendar_gregorian_to_offset (2000, 1, 1, NULL);
 
-
-  /* Create the dictionary and populate it */
-  *dict = r->dict = dict_create ();
-
   {
     const int enc = PQclientEncoding (r->conn);
 
     /* According to section 22.2 of the Postgresql manual
        a value of zero (SQL_ASCII) indicates
        "a declaration of ignorance about the encoding".
-       Accordingly, we don't set the dictionary's encoding
+       Accordingly, we use the default encoding
        if we find this value.
     */
-    if ( enc != 0 )
-      dict_set_encoding (r->dict, pg_encoding_to_char (enc));
+    encoding = enc ? pg_encoding_to_char (enc) : get_default_encoding ();
+
+    /* Create the dictionary and populate it */
+    *dict = r->dict = dict_create (encoding);
   }
 
+  const int version = PQserverVersion (r->conn);
+  ds_init_empty (&query);
   /*
-    select count (*) from (select * from medium) stupid_sql_standard;
-  */
-  ds_init_cstr (&query,
-               "BEGIN READ ONLY ISOLATION LEVEL SERIALIZABLE; "
-               "DECLARE  pspp BINARY CURSOR FOR ");
+    Versions before 9.1 don't have the REPEATABLE READ isolation level.
+    However according to <a12321aabb@gmail.com> if the server is in the
+    "hot standby" mode then SERIALIZABLE won't work.
+   */
+  ds_put_c_format (&query,
+                  "BEGIN READ ONLY ISOLATION LEVEL %s; "
+                  "DECLARE  pspp BINARY CURSOR FOR ",
+                  (version < 90100) ? "SERIALIZABLE" : "REPEATABLE READ");
 
   ds_put_substring (&query, info->sql.ss);
 
@@ -370,11 +376,11 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
       int width = 0;
       int length ;
 
-      /* If there are no data then make a finger in the air 
+      /* If there are no data then make a finger in the air
         guess at the contents */
       if ( n_tuples > 0 )
        length = PQgetlength (qres, 0, i);
-      else 
+      else
        length = PSQL_DEFAULT_WIDTH;
 
       switch (type)
@@ -538,7 +544,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
      &psql_casereader_class, r);
 
  error:
-  dict_destroy (*dict);
+  dict_unref (*dict);
 
   psql_casereader_destroy (NULL, r);
   return NULL;