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-insert.h>
26 #include <libgda/sql-parser/gda-statement-struct-compound.h>
27 #include <libgda/sql-parser/gda-statement-struct-util.h>
28 #include <libgda/sql-parser/gda-statement-struct-pspec.h>
29 #include <string.h>
30 #include <glib/gi18n-lib.h>
31
32 static gpointer gda_sql_statement_insert_new (void);
33 static void gda_sql_statement_insert_free (gpointer stmt);
34 static gpointer gda_sql_statement_insert_copy (gpointer src);
35 static gchar *gda_sql_statement_insert_serialize (gpointer stmt);
36 static gboolean gda_sql_statement_insert_check_structure (GdaSqlAnyPart *stmt, gpointer data, GError **error);
37
38 GdaSqlStatementContentsInfo insert_infos = {
39 GDA_SQL_STATEMENT_INSERT,
40 "INSERT",
41 gda_sql_statement_insert_new,
42 gda_sql_statement_insert_free,
43 gda_sql_statement_insert_copy,
44 gda_sql_statement_insert_serialize,
45
46 gda_sql_statement_insert_check_structure,
47 NULL,
48 NULL,
49 NULL,
50 NULL,
51 NULL
52 };
53
54 GdaSqlStatementContentsInfo *
_gda_sql_statement_insert_get_infos(void)55 _gda_sql_statement_insert_get_infos (void)
56 {
57 return &insert_infos;
58 }
59
60 static gpointer
gda_sql_statement_insert_new(void)61 gda_sql_statement_insert_new (void)
62 {
63 GdaSqlStatementInsert *stmt;
64 stmt = g_new0 (GdaSqlStatementInsert, 1);
65 GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_INSERT;
66 return (gpointer) stmt;
67 }
68
69 static void
gda_sql_statement_insert_free(gpointer stmt)70 gda_sql_statement_insert_free (gpointer stmt)
71 {
72 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt;
73 GSList *list;
74 g_free (insert->on_conflict);
75 gda_sql_table_free (insert->table);
76 for (list = insert->values_list; list; list = list->next) {
77 if (list->data) {
78 g_slist_foreach ((GSList *) list->data, (GFunc) gda_sql_expr_free, NULL);
79 g_slist_free ((GSList *) list->data);
80 }
81 }
82 g_slist_free (insert->values_list);
83
84 g_slist_foreach (insert->fields_list, (GFunc) gda_sql_field_free, NULL);
85 g_slist_free (insert->fields_list);
86 if (insert->select) {
87 if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT)
88 _gda_sql_statement_select_free (insert->select);
89 else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
90 _gda_sql_statement_compound_free (insert->select);
91 else
92 g_assert_not_reached ();
93 }
94
95 g_free (insert);
96 }
97
98 static gpointer
gda_sql_statement_insert_copy(gpointer src)99 gda_sql_statement_insert_copy (gpointer src)
100 {
101 GdaSqlStatementInsert *dest;
102 GSList *list;
103 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) src;
104
105 dest = gda_sql_statement_insert_new ();
106 if (insert->on_conflict)
107 dest->on_conflict = g_strdup (insert->on_conflict);
108
109 dest->table = gda_sql_table_copy (insert->table);
110 gda_sql_any_part_set_parent (dest->table, dest);
111
112 for (list = insert->fields_list; list; list = list->next) {
113 dest->fields_list = g_slist_prepend (dest->fields_list,
114 gda_sql_field_copy ((GdaSqlField*) list->data));
115 gda_sql_any_part_set_parent (dest->fields_list->data, dest);
116 }
117 dest->fields_list = g_slist_reverse (dest->fields_list);
118
119 for (list = insert->values_list; list; list = list->next) {
120 GSList *vlist, *clist = NULL;
121 for (vlist = (GSList *) list->data; vlist; vlist = vlist->next) {
122 clist = g_slist_prepend (clist,
123 gda_sql_expr_copy ((GdaSqlExpr*) vlist->data));
124 gda_sql_any_part_set_parent (clist->data, dest);
125 }
126 dest->values_list = g_slist_append (dest->values_list, g_slist_reverse (clist));
127 }
128 if (insert->select) {
129 if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT)
130 dest->select = _gda_sql_statement_select_copy (insert->select);
131 else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
132 dest->select = _gda_sql_statement_compound_copy (insert->select);
133 else
134 g_assert_not_reached ();
135 gda_sql_any_part_set_parent (dest->select, dest);
136 }
137
138 return dest;
139 }
140
141 static gchar *
gda_sql_statement_insert_serialize(gpointer stmt)142 gda_sql_statement_insert_serialize (gpointer stmt)
143 {
144 GString *string;
145 gchar *str;
146 GSList *list;
147 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt;
148
149 g_return_val_if_fail (stmt, NULL);
150
151 string = g_string_new ("\"contents\":{");
152
153 /* table name */
154 g_string_append (string, "\"table\":");
155 str = gda_sql_table_serialize (insert->table);
156 g_string_append (string, str);
157 g_free (str);
158
159 /* fields */
160 g_string_append (string, ",\"fields\":");
161 if (insert->fields_list) {
162 g_string_append_c (string, '[');
163 for (list = insert->fields_list; list; list = list->next) {
164 if (list != insert->fields_list)
165 g_string_append_c (string, ',');
166 str = gda_sql_field_serialize ((GdaSqlField*) list->data);
167 g_string_append (string, str);
168 g_free (str);
169 }
170 g_string_append_c (string, ']');
171 }
172 else
173 g_string_append (string, "null");
174
175 /* values */
176 if (insert->values_list) {
177 g_string_append (string, ",\"values\":[");
178 for (list = insert->values_list; list; list = list->next) {
179 if (list != insert->values_list)
180 g_string_append_c (string, ',');
181 if (list->data) {
182 GSList *vlist;
183 g_string_append_c (string, '[');
184 for (vlist = (GSList *) list->data; vlist; vlist = vlist->next) {
185 if (vlist != (GSList *) list->data)
186 g_string_append_c (string, ',');
187 str = gda_sql_expr_serialize ((GdaSqlExpr*) vlist->data);
188 g_string_append (string, str);
189 g_free (str);
190 }
191 g_string_append_c (string, ']');
192 }
193 else
194 g_string_append (string, "null");
195 }
196 g_string_append_c (string, ']');
197 }
198
199 /* select statement */
200 if (insert->select) {
201 g_string_append (string, ",\"select\":{");
202 if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT)
203 str = _gda_sql_statement_select_serialize (insert->select);
204 else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND)
205 str = _gda_sql_statement_compound_serialize (insert->select);
206 else
207 g_assert_not_reached ();
208
209 g_string_append (string, str);
210 g_free (str);
211 g_string_append_c (string, '}');
212 }
213
214 /* conflict clause */
215 if (insert->on_conflict) {
216 g_string_append (string, ",\"on_conflict\":");
217 str = _json_quote_string (insert->on_conflict);
218 g_string_append (string, str);
219 g_free (str);
220 }
221 g_string_append_c (string, '}');
222 str = string->str;
223 g_string_free (string, FALSE);
224 return str;
225 }
226
227 /**
228 * gda_sql_statement_insert_take_table_name
229 * @stmt: a #GdaSqlStatement pointer
230 * @value: name of the table to insert into, as a G_TYPE_STRING #GValue
231 *
232 * Sets the name of the table to insert into in @stmt. @value's ownership is transferred to
233 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
234 */
235 void
gda_sql_statement_insert_take_table_name(GdaSqlStatement * stmt,GValue * value)236 gda_sql_statement_insert_take_table_name (GdaSqlStatement *stmt, GValue *value)
237 {
238 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
239 if (value) {
240 insert->table = gda_sql_table_new (GDA_SQL_ANY_PART (insert));
241 gda_sql_table_take_name (insert->table, value);
242 }
243 }
244
245 /**
246 * gda_sql_statement_insert_take_on_conflict
247 * @stmt: a #GdaSqlStatement pointer
248 * @value: name of the resolution conflict algorithm, as a G_TYPE_STRING #GValue
249 *
250 * Sets the name of the resolution conflict algorithm used by @stmt. @value's ownership is transferred to
251 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
252 */
253 void
gda_sql_statement_insert_take_on_conflict(GdaSqlStatement * stmt,GValue * value)254 gda_sql_statement_insert_take_on_conflict (GdaSqlStatement *stmt, GValue *value)
255 {
256 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
257 if (value) {
258 insert->on_conflict = g_value_dup_string (value);
259 g_value_reset (value);
260 g_free (value);
261 }
262 }
263
264 /**
265 * gda_sql_statement_insert_take_fields_list
266 * @stmt: a #GdaSqlStatement pointer
267 * @list: a list of #GdaSqlField pointers
268 *
269 * Sets the list of fields for which values will be specified in @stmt. @list's
270 * ownership is transferred to
271 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
272 */
273 void
gda_sql_statement_insert_take_fields_list(GdaSqlStatement * stmt,GSList * list)274 gda_sql_statement_insert_take_fields_list (GdaSqlStatement *stmt, GSList *list)
275 {
276 GSList *l;
277 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
278 insert->fields_list = list;
279
280 for (l = list; l; l = l->next)
281 gda_sql_any_part_set_parent (l->data, insert);
282 }
283
284 /**
285 * gda_sql_statement_insert_take_1_values_list
286 * @stmt: a #GdaSqlStatement pointer
287 * @list: a list of #GdaSqlExpr pointers
288 *
289 * Sets a list of values to be inserted by @stmt. @list's
290 * ownership is transferred to
291 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
292 */
293 void
gda_sql_statement_insert_take_1_values_list(GdaSqlStatement * stmt,GSList * list)294 gda_sql_statement_insert_take_1_values_list (GdaSqlStatement *stmt, GSList *list)
295 {
296 GSList *l;
297 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
298
299 for (l = list; l; l = l->next)
300 gda_sql_any_part_set_parent (l->data, insert);
301 insert->values_list = g_slist_prepend (insert->values_list, list);
302 }
303
304 /**
305 * gda_sql_statement_insert_take_1_values_list
306 * @stmt: a #GdaSqlStatement pointer
307 * @list: a list of #GSList of #GdaSqlExpr pointers
308 *
309 * Sets a list of list of values to be inserted by @stmt. @list's
310 * ownership is transferred to
311 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
312 */
313 void
gda_sql_statement_insert_take_extra_values_list(GdaSqlStatement * stmt,GSList * list)314 gda_sql_statement_insert_take_extra_values_list (GdaSqlStatement *stmt, GSList *list)
315 {
316 GSList *l1, *l2;
317 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
318 for (l1 = list; l1; l1 = l1->next) {
319 for (l2 = (GSList *) l1->data; l2; l2 = l2->next)
320 gda_sql_any_part_set_parent (l2->data, insert);
321 }
322 insert->values_list = g_slist_concat (insert->values_list, list);
323 }
324
325
326 /**
327 * gda_sql_statement_insert_take_select
328 * @stmt: a #GdaSqlStatement pointer
329 * @select: a SELECT or COMPOUND #GdaSqlStatement pointer
330 *
331 * Specifies a SELECT statement, the values inserted will be the result set of @select. @select's
332 * ownership is transferred to
333 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
334 */
335 void
gda_sql_statement_insert_take_select(GdaSqlStatement * stmt,GdaSqlStatement * select)336 gda_sql_statement_insert_take_select (GdaSqlStatement *stmt, GdaSqlStatement *select)
337 {
338 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt->contents;
339 GdaSqlAnyPart *part;
340 part = GDA_SQL_ANY_PART (select->contents);
341 select->contents = NULL;
342 gda_sql_statement_free (select);
343 insert->select = _gda_sql_statement_compound_reduce (part);
344 gda_sql_any_part_set_parent (insert->select, insert);
345 }
346
347 static gboolean
gda_sql_statement_insert_check_structure(GdaSqlAnyPart * stmt,G_GNUC_UNUSED gpointer data,GError ** error)348 gda_sql_statement_insert_check_structure (GdaSqlAnyPart *stmt, G_GNUC_UNUSED gpointer data, GError **error)
349 {
350 GdaSqlStatementInsert *insert = (GdaSqlStatementInsert *) stmt;
351 guint nb_values;
352 GSList *list;
353 if (!stmt) return TRUE;
354
355 nb_values = g_slist_length (insert->fields_list); /* may be 0 */
356 if (!insert->table) {
357 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
358 "%s", _("INSERT statement needs a table to insert into"));
359 return FALSE;
360 }
361 if (insert->select) {
362 if (insert->values_list) {
363 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
364 "%s", _("Can't specify values to insert and SELECT statement in INSERT statement"));
365 return FALSE;
366 }
367 if (nb_values > 0) {
368 guint len;
369 if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_SELECT) {
370 GdaSqlStatementSelect *select = (GdaSqlStatementSelect*) insert->select;
371 len = g_slist_length (select->expr_list);
372 }
373 else if (GDA_SQL_ANY_PART (insert->select)->type == GDA_SQL_ANY_STMT_COMPOUND) {
374 gint compound_len;
375 GdaSqlStatementCompound *compound = (GdaSqlStatementCompound*) insert->select;
376 compound_len = _gda_sql_statement_compound_get_n_cols (compound, error);
377 len = compound_len;
378 if (compound_len < 0)
379 return FALSE;
380 }
381 else
382 g_assert_not_reached ();
383 if (len != nb_values) {
384 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
385 "%s", _("INSERT statement does not have the same number of target columns and expressions"));
386 return FALSE;
387 }
388 }
389 }
390 else {
391 /* using values list */
392 if (!insert->values_list && (nb_values != 0)) {
393 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
394 "%s", _("Missing values to insert in INSERT statement"));
395 return FALSE;
396 }
397
398 for (list = insert->values_list; list; list = list->next) {
399 if (nb_values == 0) {
400 nb_values = g_slist_length ((GSList *) list->data);
401 if (nb_values == 0) {
402 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
403 "%s", _("Missing values to insert in INSERT statement"));
404 return FALSE;
405 }
406 }
407 else
408 if (g_slist_length ((GSList *) list->data) != nb_values) {
409 if (insert->fields_list)
410 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
411 "%s", _("INSERT statement does not have the same number of target columns and expressions"));
412 else
413 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
414 "%s", _("VALUES lists must all be the same length in INSERT statement"));
415 return FALSE;
416 }
417 }
418 }
419 return TRUE;
420 }
421