dataset: Before deleting variables, make sure new values are added.
[pspp] / src / data / dataset.c
index 450383fb875df81a71807ae7326de0768214330b..9503521207c0fd78a5bbbc2fc18a9c55a579da53 100644 (file)
@@ -347,6 +347,27 @@ dataset_steal_source (struct dataset *ds)
   return reader;
 }
 
+void
+dataset_delete_vars (struct dataset *ds, struct variable **vars, size_t n)
+{
+  assert (!proc_in_temporary_transformations (ds));
+  assert (!proc_has_transformations (ds));
+  assert (n < dict_get_n_vars (ds->dict));
+
+  caseinit_mark_for_init (ds->caseinit, ds->dict);
+  ds->source = caseinit_translate_casereader_to_init_vars (
+    ds->caseinit, dict_get_proto (ds->dict), ds->source);
+  caseinit_clear (ds->caseinit);
+  caseinit_mark_as_preinited (ds->caseinit, ds->dict);
+
+  dict_delete_vars (ds->dict, vars, n);
+  ds->source = case_map_create_input_translator (
+    case_map_to_compact_dict (ds->dict, 0), ds->source);
+  dict_compact_values (ds->dict);
+  caseinit_clear (ds->caseinit);
+  caseinit_mark_as_preinited (ds->caseinit, ds->dict);
+}
+
 /* Returns a number unique to DS.  It can be used to distinguish one dataset
    from any other within a given program run, even datasets that do not exist
    at the same time. */
@@ -433,6 +454,8 @@ proc_open_filtering (struct dataset *ds, bool filter)
   update_last_proc_invocation (ds);
 
   caseinit_mark_for_init (ds->caseinit, ds->dict);
+  ds->source = caseinit_translate_casereader_to_init_vars (
+    ds->caseinit, dict_get_proto (ds->dict), ds->source);
 
   /* Finish up the collection of transformations. */
   add_case_limit_trns (ds);
@@ -450,12 +473,12 @@ proc_open_filtering (struct dataset *ds, bool filter)
   if (!ds->discard_output)
     {
       struct dictionary *pd = ds->permanent_dict;
-      size_t compacted_n_values = dict_count_values (pd, 1u << DC_SCRATCH);
+      size_t compacted_n_values = dict_count_values (pd, DC_SCRATCH);
       if (compacted_n_values < dict_get_next_value_idx (pd))
         {
           struct caseproto *compacted_proto;
-          compacted_proto = dict_get_compacted_proto (pd, 1u << DC_SCRATCH);
-          ds->compactor = case_map_to_compact_dict (pd, 1u << DC_SCRATCH);
+          compacted_proto = dict_get_compacted_proto (pd, DC_SCRATCH);
+          ds->compactor = case_map_to_compact_dict (pd, DC_SCRATCH);
           ds->sink = autopaging_writer_create (compacted_proto);
           caseproto_unref (compacted_proto);
         }
@@ -534,12 +557,12 @@ proc_casereader_read (struct casereader *reader UNUSED, void *ds_)
       if (c == NULL)
         return NULL;
       c = case_unshare_and_resize (c, dict_get_proto (ds->dict));
-      caseinit_init_vars (ds->caseinit, c);
+      caseinit_restore_left_vars (ds->caseinit, c);
 
       /* Execute permanent transformations.  */
       casenumber case_nr = ds->cases_written + 1;
       retval = trns_chain_execute (&ds->permanent_trns_chain, case_nr, &c);
-      caseinit_update_left_vars (ds->caseinit, c);
+      caseinit_save_left_vars (ds->caseinit, c);
       if (retval != TRNS_CONTINUE)
         continue;
 
@@ -803,6 +826,12 @@ proc_pop_transformations (struct dataset *ds, struct trns_chain *chain)
   *chain = ds->stack[--ds->n_stack];
 }
 
+bool
+proc_has_transformations (const struct dataset *ds)
+{
+  return ds->permanent_trns_chain.n || ds->temporary_trns_chain.n;
+}
+
 static enum trns_result
 store_case_num (void *var_, struct ccase **cc, casenumber case_num)
 {
@@ -1040,8 +1069,8 @@ measure_guesser_create__ (struct dictionary *dict)
       if (var_get_measure (var) != MEASURE_UNKNOWN)
         continue;
 
-      const struct fmt_spec *f = var_get_print_format (var);
-      enum measure m = var_default_measure_for_format (f->type);
+      struct fmt_spec f = var_get_print_format (var);
+      enum measure m = var_default_measure_for_format (f.type);
       if (m != MEASURE_UNKNOWN)
         {
           var_set_measure (var, m);