1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2006, 2007, 2010, 2011, 2013 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 #include "data/casereader.h"
22 #include "data/dataset.h"
23 #include "data/dictionary.h"
24 #include "language/command.h"
25 #include "language/lexer/lexer.h"
26 #include "language/lexer/variable-parser.h"
27 #include "libpspp/message.h"
30 #define _(msgid) gettext (msgid)
32 /* Performs DELETE VARIABLES command. */
34 cmd_delete_variables (struct lexer *lexer, struct dataset *ds)
36 struct variable **vars;
40 if (proc_make_temporary_transformations_permanent (ds))
41 lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
42 _("%s may not be used after %s. "
43 "Temporary transformations will be made permanent."),
44 "DELETE VARIABLES", "TEMPORARY");
46 if (!parse_variables (lexer, dataset_dict (ds), &vars, &n_vars, PV_NONE))
48 if (n_vars == dict_get_n_vars (dataset_dict (ds)))
50 lex_ofs_error (lexer, 0, lex_ofs (lexer) - 1,
51 _("%s may not be used to delete all variables "
52 "from the active dataset dictionary. "
53 "Use %s instead."), "DELETE VARIABLES", "NEW FILE");
57 ok = casereader_destroy (proc_open_filtering (ds, false));
58 ok = proc_commit (ds) && ok;
62 dict_delete_vars (dataset_dict (ds), vars, n_vars);
64 /* XXX A bunch of bugs conspire to make executing transformations again here
65 necessary, even though it shouldn't be.
67 Consider the following (which is included in delete-variables.at):
69 DATA LIST NOTABLE /s1 TO s2 1-2(A).
77 The DATA LIST gives us a caseproto with widths 1,1. DELETE VARIABLES
78 deletes the first variable so we now have -1,1. This already is
79 technically a problem because proc_casereader_read() calls
80 case_unshare_and_resize() from the former to the latter caseproto, and
81 these caseprotos are not conformable (which is a requirement for
82 case_resize()). It doesn't cause an assert by default because
83 case_resize() uses expensive_assert() to check for it though. However, in
84 practice we don't see a problem yet because case_resize() only does work
85 if the number of widths in the source and dest caseproto are different.
87 Executing NUMERIC adds a third variable, though, so we have -1,1,0. This
88 makes caseproto_resize() notice that there are fewer strings in the new
89 caseproto. Therefore it destroys the second one (s2). It should destroy
90 the first one (s1), but if the caseprotos were really conformable then it
91 would have destroyed the right one. This mistake eventually causes a bad
94 Executing transformations a second time after DELETE VARIABLES, like we do
95 below, works around the problem because we can never run into a situation
96 where we've got both new variables (triggering a resize) and deleted
97 variables (triggering the bad free).
99 We should fix this in a better way. Doing it cleanly seems hard. This
100 seems to work for now. */
101 ok = casereader_destroy (proc_open_filtering (ds, false));
102 ok = proc_commit (ds) && ok;
112 return CMD_CASCADING_FAILURE;