Work on support for variable sets.
[pspp] / src / data / psql-reader.c
index 6780138b08da038015f0022ef81b59e606a2e2ce..8b83d018de0d9fe8de5a52889f6e896bf4f3b7ba 100644 (file)
@@ -177,7 +177,7 @@ dump (const unsigned char *x, int l)
 #endif
 
 static struct variable *
-create_var (struct psql_reader *r, const struct fmt_spec *fmt,
+create_var (struct psql_reader *r, struct fmt_spec fmt,
            int width, const char *suggested_name, int col)
 {
   unsigned long int vx = 0;
@@ -233,8 +233,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   casenumber n_cases = CASENUMBER_MAX;
   const char *encoding;
 
-  struct psql_reader *r = xzalloc (sizeof *r);
-  struct string query ;
+  struct psql_reader *r = XZALLOC (struct psql_reader);
 
   r->conn = PQconnectdb (info->conninfo);
   if (NULL == r->conn)
@@ -305,21 +304,19 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
   }
 
   const int version = PQserverVersion (r->conn);
-  ds_init_empty (&query);
   /*
     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");
+  char *query = xasprintf (
+    "BEGIN READ ONLY ISOLATION LEVEL %s; "
+    "DECLARE  pspp BINARY CURSOR FOR %s",
+    (version < 90100) ? "SERIALIZABLE" : "REPEATABLE READ",
+    info->sql);
+  qres = PQexec (r->conn, query);
+  free (query);
 
-  ds_put_substring (&query, info->sql.ss);
-
-  qres = PQexec (r->conn, ds_cstr (&query));
-  ds_destroy (&query);
   if (PQresultStatus (qres) != PGRES_COMMAND_OK)
     {
       msg (ME, _("Error from psql source: %s."),
@@ -339,12 +336,11 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
      On the other hand, most PSPP functions don't need to know this.
      The GUI is the notable exception.
   */
-  ds_init_cstr (&query, "SELECT count (*) FROM (");
-  ds_put_substring (&query, info->sql.ss);
-  ds_put_cstr (&query, ") stupid_sql_standard");
+  query = xasprintf ("SELECT count (*) FROM (%s) stupid_sql_standard",
+                     info->sql);
+  qres = PQexec (r->conn, query);
+  free (query);
 
-  qres = PQexec (r->conn, ds_cstr (&query));
-  ds_destroy (&query);
   if (PQresultStatus (qres) != PGRES_TUPLES_OK)
     {
       msg (ME, _("Error from psql source: %s."),
@@ -464,7 +460,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
        fmt.w = width = PSQL_DEFAULT_WIDTH;
 
 
-      var = create_var (r, &fmt, width, PQfname (qres, i), i);
+      var = create_var (r, fmt, width, PQfname (qres, i), i);
       if (type == NUMERICOID && n_tuples > 0)
        {
          const uint8_t *vptr = (const uint8_t *) PQgetvalue (qres, 0, i);
@@ -481,7 +477,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
          fmt.type = FMT_E;
          fmt.w = fmt_max_output_width (fmt.type) ;
          fmt.d =  MIN (dscale, fmt_max_output_decimals (fmt.type, fmt.w));
-         var_set_both_formats (var, &fmt);
+         var_set_both_formats (var, fmt);
        }
 
       /* Timezones need an extra variable */
@@ -496,7 +492,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
            fmt.w = 8;
            fmt.d = 2;
 
-           create_var (r, &fmt, 0, ds_cstr (&name), -1);
+           create_var (r, fmt, 0, ds_cstr (&name), -1);
 
            ds_destroy (&name);
          }
@@ -511,7 +507,7 @@ psql_open_reader (struct psql_read_info *info, struct dictionary **dict)
            fmt.w = 3;
            fmt.d = 0;
 
-           create_var (r, &fmt, 0, ds_cstr (&name), -1);
+           create_var (r, fmt, 0, ds_cstr (&name), -1);
 
            ds_destroy (&name);
          }
@@ -615,7 +611,7 @@ set_value (struct psql_reader *r)
        case INTERVALOID:
        case TIMESTAMPTZOID:
        case TIMETZOID:
-         if (i < r->vmapsize && var_get_dict_index(v) + 1 < dict_get_var_cnt (r->dict))
+         if (i < r->vmapsize && var_get_dict_index(v) + 1 < dict_get_n_vars (r->dict))
            {
              const struct variable *v1 = NULL;
              v1 = dict_get_var (r->dict, var_get_dict_index (v) + 1);