Get rid of uses of MAX_SHORT_STRING in Gnumeric and PostgreSQL readers.
[pspp-builds.git] / src / data / psql-reader.c
index f2d5ff282272f48e821c4826d9d60f5158f6bfca..68ea7e5672cea1c483fb356e75b5834852642c1d 100644 (file)
@@ -20,6 +20,7 @@
 #include <libpspp/message.h>
 #include <gl/xalloc.h>
 #include <data/dictionary.h>
+#include <math.h>
 #include <stdlib.h>
 
 #include "psql-reader.h"
 #include "calendar.h"
 
 #include <inttypes.h>
+#include <libpspp/misc.h>
 #include <libpspp/str.h>
 
+#include "minmax.h"
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) (msgid)
@@ -50,6 +54,9 @@ psql_open_reader (struct psql_read_info *info UNUSED, struct dictionary **dict U
 #include <libpq-fe.h>
 
 
+/* Default width of string variables. */
+#define PSQL_DEFAULT_WIDTH 8
+
 /* These macros  must be the same as in catalog/pg_types.h from the postgres source */
 #define BOOLOID            16
 #define BYTEAOID           17
@@ -95,7 +102,7 @@ struct psql_reader
 
   double postgres_epoch;
 
-  size_t value_cnt;
+  struct caseproto *proto;
   struct dictionary *dict;
 
   /* An array of ints, which maps psql column numbers into
@@ -175,8 +182,6 @@ create_var (struct psql_reader *r, const struct fmt_spec *fmt,
   struct variable *var;
   char name[VAR_NAME_LEN + 1];
 
-  r->value_cnt += value_cnt_from_width (width);
-
   if ( ! dict_make_unique_var_name (r->dict, suggested_name, &vx, name))
     {
       msg (ME, _("Cannot create variable name from %s"), suggested_name);
@@ -357,7 +362,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   n_tuples = PQntuples (qres);
   n_fields = PQnfields (qres);
 
-  r->value_cnt = 0;
+  r->proto = NULL;
   r->vmap = NULL;
   r->vmapsize = 0;
 
@@ -374,7 +379,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
       if ( n_tuples > 0 )
        length = PQgetlength (qres, 0, i);
       else 
-       length = MAX_SHORT_STRING;
+       length = PSQL_DEFAULT_WIDTH;
 
       switch (type)
        {
@@ -401,13 +406,13 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
        case BPCHAROID:
          fmt.type = FMT_A;
          width = (info->str_width == -1) ?
-           ROUND_UP (length, MAX_SHORT_STRING) : info->str_width;
+           ROUND_UP (length, PSQL_DEFAULT_WIDTH) : info->str_width;
          fmt.w = width;
          fmt.d = 0;
           break;
        case BYTEAOID:
          fmt.type = FMT_AHEX;
-         width = length > 0 ? length : MAX_SHORT_STRING;
+         width = length > 0 ? length : PSQL_DEFAULT_WIDTH;
          fmt.w = width * 2;
          fmt.d = 0;
          break;
@@ -446,12 +451,16 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
        default:
           msg (MW, _("Unsupported OID %d.  SYSMIS values will be inserted."), type);
          fmt.type = FMT_A;
-         width = length > 0 ? length : MAX_SHORT_STRING;
+         width = length > 0 ? length : PSQL_DEFAULT_WIDTH;
          fmt.w = width ;
          fmt.d = 0;
          break;
        }
 
+      if ( width == 0 && fmt_is_string (fmt.type))
+       fmt.w = width = PSQL_DEFAULT_WIDTH;
+
+
       var = create_var (r, &fmt, width, PQfname (qres, i), i);
       if ( type == NUMERICOID && n_tuples > 0)
        {
@@ -524,10 +533,11 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   ds_put_format (&r->fetch_cmd,  "FETCH FORWARD %d FROM pspp", r->cache_size);
 
   reload_cache (r);
+  r->proto = caseproto_ref (dict_get_proto (*dict));
 
   return casereader_create_sequential
     (NULL,
-     r->value_cnt,
+     r->proto,
      n_cases,
      &psql_casereader_class, r);
 
@@ -550,6 +560,7 @@ psql_casereader_destroy (struct casereader *reader UNUSED, void *r_)
   free (r->vmap);
   if (r->res) PQclear (r->res);
   PQfinish (r->conn);
+  caseproto_unref (r->proto);
 
   free (r);
 }
@@ -584,8 +595,8 @@ set_value (struct psql_reader *r)
   if ( r->tuple >= PQntuples (r->res))
     return NULL;
 
-  c = case_create (r->value_cnt);
-  memset (case_data_rw_idx (c, 0)->s, ' ', MAX_SHORT_STRING * r->value_cnt);
+  c = case_create (r->proto);
+  case_set_missing (c);
 
 
   for (i = 0 ; i < n_vars ; ++i )
@@ -827,7 +838,8 @@ set_value (struct psql_reader *r)
            case VARCHAROID:
            case BPCHAROID:
            case BYTEAOID:
-             memcpy (val->s, (char *) vptr, MIN (length, var_width));
+             memcpy (value_str_rw (val, var_width), (char *) vptr,
+                      MIN (length, var_width));
              break;
 
            case NUMERICOID: