1 /*
2 * Copyright (C) 2008 - 2010 Murray Cumming <murrayc@murrayc.com>
3 * Copyright (C) 2008 - 2011 Vivien Malerba <malerba@gnome-db.org>
4 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
5 * Copyright (C) 2010 David King <davidk@openismus.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #include <libgda/gda-debug-macros.h>
24 #include <libgda/sql-parser/gda-statement-struct.h>
25 #include <libgda/sql-parser/gda-statement-struct-update.h>
26 #include <libgda/sql-parser/gda-statement-struct-util.h>
27 #include <libgda/sql-parser/gda-statement-struct-pspec.h>
28 #include <string.h>
29 #include <glib/gi18n-lib.h>
30
31 static gpointer gda_sql_statement_update_new (void);
32 static void gda_sql_statement_update_free (gpointer stmt);
33 static gpointer gda_sql_statement_update_copy (gpointer src);
34 static gchar *gda_sql_statement_update_serialize (gpointer stmt);
35 static gboolean gda_sql_statement_update_check_structure (GdaSqlAnyPart *stmt, gpointer data, GError **error);
36
37 GdaSqlStatementContentsInfo update_infos = {
38 GDA_SQL_STATEMENT_UPDATE,
39 "UPDATE",
40 gda_sql_statement_update_new,
41 gda_sql_statement_update_free,
42 gda_sql_statement_update_copy,
43 gda_sql_statement_update_serialize,
44
45 gda_sql_statement_update_check_structure,
46 NULL,
47 NULL,
48 NULL,
49 NULL,
50 NULL
51 };
52
53 GdaSqlStatementContentsInfo *
_gda_sql_statement_update_get_infos(void)54 _gda_sql_statement_update_get_infos (void)
55 {
56 return &update_infos;
57 }
58
59 static gpointer
gda_sql_statement_update_new(void)60 gda_sql_statement_update_new (void)
61 {
62 GdaSqlStatementUpdate *stmt;
63 stmt = g_new0 (GdaSqlStatementUpdate, 1);
64 GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_UPDATE;
65 return (gpointer) stmt;
66 }
67
68 static void
gda_sql_statement_update_free(gpointer stmt)69 gda_sql_statement_update_free (gpointer stmt)
70 {
71 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt;
72 GSList *list;
73
74 if (update->table)
75 gda_sql_table_free (update->table);
76 for (list = update->fields_list; list; list = list->next) {
77 if (list->data)
78 gda_sql_field_free ((GdaSqlField *) list->data);
79 }
80 if (update->fields_list)
81 g_slist_free (update->fields_list);
82
83 for (list = update->expr_list; list; list = list->next) {
84 if (list->data)
85 gda_sql_expr_free ((GdaSqlExpr *) list->data);
86 }
87 if (update->expr_list)
88 g_slist_free (update->expr_list);
89
90 if (update->cond)
91 gda_sql_expr_free (update->cond);
92 g_free (update);
93 }
94
95 static gpointer
gda_sql_statement_update_copy(gpointer src)96 gda_sql_statement_update_copy (gpointer src)
97 {
98 GdaSqlStatementUpdate *dest;
99 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) src;
100 GSList *list;
101
102 dest = gda_sql_statement_update_new ();
103 if (update->on_conflict)
104 dest->on_conflict = g_strdup (update->on_conflict);
105
106 dest->table = gda_sql_table_copy (update->table);
107 gda_sql_any_part_set_parent (dest->table, dest);
108
109 for (list = update->fields_list; list; list = list->next) {
110 dest->fields_list = g_slist_prepend (dest->fields_list,
111 gda_sql_field_copy ((GdaSqlField *) list->data));
112 gda_sql_any_part_set_parent (dest->fields_list->data, dest);
113 }
114 dest->fields_list = g_slist_reverse (dest->fields_list);
115
116 for (list = update->expr_list; list; list = list->next) {
117 dest->expr_list = g_slist_prepend (dest->expr_list,
118 gda_sql_expr_copy ((GdaSqlExpr *) list->data));
119 gda_sql_any_part_set_parent (dest->expr_list->data, dest);
120 }
121 dest->expr_list = g_slist_reverse (dest->expr_list);
122
123 dest->cond = gda_sql_expr_copy (update->cond);
124 gda_sql_any_part_set_parent (dest->cond, dest);
125
126 return dest;
127 }
128
129 static gchar *
gda_sql_statement_update_serialize(gpointer stmt)130 gda_sql_statement_update_serialize (gpointer stmt)
131 {
132 GString *string;
133 gchar *str;
134 GSList *list;
135 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt;
136
137 g_return_val_if_fail (stmt, NULL);
138
139 string = g_string_new ("\"contents\":{");
140
141 /* table name */
142 g_string_append (string, "\"table\":");
143 str = gda_sql_table_serialize (update->table);
144 g_string_append (string, str);
145 g_free (str);
146
147 /* fields */
148 g_string_append (string, ",\"fields\":");
149 if (update->fields_list) {
150 g_string_append_c (string, '[');
151 for (list = update->fields_list; list; list = list->next) {
152 if (list != update->fields_list)
153 g_string_append_c (string, ',');
154 str = gda_sql_field_serialize ((GdaSqlField *) list->data);
155 g_string_append (string, str);
156 g_free (str);
157 }
158 g_string_append_c (string, ']');
159 }
160 else
161 g_string_append (string, "null");
162
163 /* expressions */
164 g_string_append (string, ",\"expressions\":");
165 if (update->expr_list) {
166 g_string_append_c (string, '[');
167 for (list = update->expr_list; list; list = list->next) {
168 if (list != update->expr_list)
169 g_string_append_c (string, ',');
170 str = gda_sql_expr_serialize ((GdaSqlExpr *) list->data);
171 g_string_append (string, str);
172 g_free (str);
173 }
174 g_string_append_c (string, ']');
175 }
176 else
177 g_string_append (string, "null");
178
179 /* condition */
180 if (update->cond) {
181 g_string_append (string, ",\"condition\":");
182 str = gda_sql_expr_serialize (update->cond);
183 g_string_append (string, str);
184 g_free (str);
185 }
186
187 /* conflict clause */
188 if (update->on_conflict) {
189 g_string_append (string, ",\"on_conflict\":");
190 str = _json_quote_string (update->on_conflict);
191 g_string_append (string, str);
192 g_free (str);
193 }
194 g_string_append_c (string, '}');
195 str = string->str;
196 g_string_free (string, FALSE);
197 return str;
198 }
199
200 /**
201 * gda_sql_statement_update_take_table_name
202 * @stmt: a #GdaSqlStatement pointer
203 * @value: a table name, as a G_TYPE_STRING #GValue
204 *
205 * Sets the name of the table to delete from in @stmt.
206 *
207 * @value's ownership is transferred to
208 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
209 */
210 void
gda_sql_statement_update_take_table_name(GdaSqlStatement * stmt,GValue * value)211 gda_sql_statement_update_take_table_name (GdaSqlStatement *stmt, GValue *value)
212 {
213 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt->contents;
214 if (value) {
215 update->table = gda_sql_table_new (GDA_SQL_ANY_PART (update));
216 gda_sql_table_take_name (update->table, value);
217 }
218 }
219
220 /**
221 * gda_sql_statement_update_take_on_conflict
222 * @stmt: a #GdaSqlStatement pointer
223 * @value: name of the resolution conflict algorithm, as a G_TYPE_STRING #GValue
224 *
225 * Sets the name of the resolution conflict algorithm used by @stmt. @value's ownership is transferred to
226 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
227 */
228 void
gda_sql_statement_update_take_on_conflict(GdaSqlStatement * stmt,GValue * value)229 gda_sql_statement_update_take_on_conflict (GdaSqlStatement *stmt, GValue *value)
230 {
231 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt->contents;
232 if (value) {
233 update->on_conflict = g_value_dup_string (value);
234 g_value_reset (value);
235 g_free (value);
236 }
237 }
238
239 /**
240 * gda_sql_statement_update_take_condition
241 * @stmt: a #GdaSqlStatement pointer
242 * @cond: a #GdaSqlExpr pointer
243 *
244 * Sets the WHERE clause of @stmt
245 *
246 * @expr's ownership is transferred to
247 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
248 */
249 void
gda_sql_statement_update_take_condition(GdaSqlStatement * stmt,GdaSqlExpr * cond)250 gda_sql_statement_update_take_condition (GdaSqlStatement *stmt, GdaSqlExpr *cond)
251 {
252 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt->contents;
253 update->cond = cond;
254 gda_sql_any_part_set_parent (cond, update);
255 }
256
257
258 /**
259 * gda_sql_statement_update_take_set_value
260 * @stmt: a #GdaSqlStatement pointer
261 * @fname: a field name, as a G_TYPE_STRING #GValue
262 * @expr: a #GdaSqlExpr pointer
263 *
264 * Specifies that the field named @fname will be updated with the expression @expr.
265 *
266 * @fname and @expr's responsibility are transferred to
267 * @stmt (which means @stmt is then responsible for freeing them when no longer needed).
268 */
269 void
gda_sql_statement_update_take_set_value(GdaSqlStatement * stmt,GValue * fname,GdaSqlExpr * expr)270 gda_sql_statement_update_take_set_value (GdaSqlStatement *stmt, GValue *fname, GdaSqlExpr *expr)
271 {
272 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt->contents;
273 GdaSqlField *sf;
274
275 sf = gda_sql_field_new (GDA_SQL_ANY_PART (update));
276 gda_sql_field_take_name (sf, fname);
277 update->fields_list = g_slist_append (update->fields_list, sf);
278
279 update->expr_list = g_slist_append (update->expr_list, expr);
280 gda_sql_any_part_set_parent (expr, update);
281 }
282
283 static gboolean
gda_sql_statement_update_check_structure(GdaSqlAnyPart * stmt,G_GNUC_UNUSED gpointer data,GError ** error)284 gda_sql_statement_update_check_structure (GdaSqlAnyPart *stmt, G_GNUC_UNUSED gpointer data, GError **error)
285 {
286 GdaSqlStatementUpdate *update = (GdaSqlStatementUpdate *) stmt;
287
288 if (!update->table) {
289 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
290 "%s", _("UPDATE statement needs a table to update data"));
291 return FALSE;
292 }
293
294 if (g_slist_length (update->fields_list) != g_slist_length (update->expr_list)) {
295 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
296 "%s", _("UPDATE statement does not have the same number of target columns and expressions"));
297 return FALSE;
298 }
299
300 if (!update->fields_list) {
301 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
302 "%s", _("UPDATE statement does not have any target columns to update"));
303 return FALSE;
304 }
305
306 return TRUE;
307 }
308