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-select.h>
26 #include <libgda/sql-parser/gda-statement-struct-pspec.h>
27 #include <string.h>
28 #include <glib/gi18n-lib.h>
29
30 static gpointer gda_sql_statement_select_new (void);
31 static gboolean gda_sql_statement_select_check_structure (GdaSqlAnyPart *stmt, gpointer data, GError **error);
32 static gboolean gda_sql_statement_select_check_validity (GdaSqlAnyPart *stmt, gpointer data, GError **error);
33
34 GdaSqlStatementContentsInfo select_infos = {
35 GDA_SQL_STATEMENT_SELECT,
36 "SELECT",
37 gda_sql_statement_select_new,
38 _gda_sql_statement_select_free,
39 _gda_sql_statement_select_copy,
40 _gda_sql_statement_select_serialize,
41
42 gda_sql_statement_select_check_structure,
43 gda_sql_statement_select_check_validity,
44 NULL,
45 NULL,
46 NULL,
47 NULL
48 };
49
50 GdaSqlStatementContentsInfo *
_gda_sql_statement_select_get_infos(void)51 _gda_sql_statement_select_get_infos (void)
52 {
53 return &select_infos;
54 }
55
56 static gpointer
gda_sql_statement_select_new(void)57 gda_sql_statement_select_new (void)
58 {
59 GdaSqlStatementSelect *stmt;
60 stmt = g_new0 (GdaSqlStatementSelect, 1);
61 GDA_SQL_ANY_PART (stmt)->type = GDA_SQL_ANY_STMT_SELECT;
62 return (gpointer) stmt;
63 }
64
65 void
_gda_sql_statement_select_free(gpointer stmt)66 _gda_sql_statement_select_free (gpointer stmt)
67 {
68 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt;
69
70 if (select->distinct_expr)
71 gda_sql_expr_free (select->distinct_expr);
72 if (select->expr_list) {
73 g_slist_foreach (select->expr_list, (GFunc) gda_sql_select_field_free, NULL);
74 g_slist_free (select->expr_list);
75 }
76 gda_sql_select_from_free (select->from);
77 gda_sql_expr_free (select->where_cond);
78 if (select->group_by) {
79 g_slist_foreach (select->group_by, (GFunc) gda_sql_expr_free, NULL);
80 g_slist_free (select->group_by);
81 }
82 gda_sql_expr_free (select->having_cond);
83 if (select->order_by) {
84 g_slist_foreach (select->order_by, (GFunc) gda_sql_select_order_free, NULL);
85 g_slist_free (select->order_by);
86 }
87 gda_sql_expr_free (select->limit_count);
88 gda_sql_expr_free (select->limit_offset);
89 g_free (select);
90 }
91
92 gpointer
_gda_sql_statement_select_copy(gpointer src)93 _gda_sql_statement_select_copy (gpointer src)
94 {
95 GdaSqlStatementSelect *dest;
96 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) src;
97 GSList *list;
98
99 dest = gda_sql_statement_select_new ();
100 dest->distinct = select->distinct;
101
102 dest->distinct_expr = gda_sql_expr_copy (select->distinct_expr);
103 gda_sql_any_part_set_parent (dest->distinct_expr, dest);
104
105 for (list = select->expr_list; list; list = list->next) {
106 dest->expr_list = g_slist_prepend (dest->expr_list,
107 gda_sql_select_field_copy ((GdaSqlSelectField*) list->data));
108 gda_sql_any_part_set_parent (dest->expr_list->data, dest);
109 }
110 dest->expr_list = g_slist_reverse (dest->expr_list);
111
112 dest->from = gda_sql_select_from_copy (select->from);
113 gda_sql_any_part_set_parent (dest->from, dest);
114
115 dest->where_cond = gda_sql_expr_copy (select->where_cond);
116 gda_sql_any_part_set_parent (dest->where_cond, dest);
117
118 for (list = select->group_by; list; list = list->next) {
119 dest->group_by = g_slist_prepend (dest->group_by,
120 gda_sql_expr_copy ((GdaSqlExpr*) list->data));
121 gda_sql_any_part_set_parent (dest->group_by->data, dest);
122 }
123 dest->group_by = g_slist_reverse (dest->group_by);
124
125 dest->having_cond = gda_sql_expr_copy (select->having_cond);
126 gda_sql_any_part_set_parent (dest->having_cond, dest);
127
128 for (list = select->order_by; list; list = list->next) {
129 dest->order_by = g_slist_prepend (dest->order_by,
130 gda_sql_select_order_copy ((GdaSqlSelectOrder*) list->data));
131 gda_sql_any_part_set_parent (dest->order_by->data, dest);
132 }
133 dest->order_by = g_slist_reverse (dest->order_by);
134
135 dest->limit_count = gda_sql_expr_copy (select->limit_count);
136 gda_sql_any_part_set_parent (dest->limit_count, dest);
137
138 dest->limit_offset = gda_sql_expr_copy (select->limit_offset);
139 gda_sql_any_part_set_parent (dest->limit_offset, dest);
140
141 return dest;
142 }
143
144 gchar *
_gda_sql_statement_select_serialize(gpointer stmt)145 _gda_sql_statement_select_serialize (gpointer stmt)
146 {
147 GString *string;
148 gchar *str;
149 GSList *list;
150 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt;
151
152 g_return_val_if_fail (stmt, NULL);
153
154 string = g_string_new ("\"contents\":{");
155 /* distinct */
156 g_string_append (string, "\"distinct\":");
157 g_string_append (string, select->distinct ? "\"true\"" : "\"false\"");
158 if (select->distinct_expr) {
159 g_string_append (string, ",\"distinct_on\":");
160 str = gda_sql_expr_serialize (select->distinct_expr);
161 g_string_append (string, str);
162 g_free (str);
163 }
164 g_string_append (string, ",\"fields\":");
165 if (select->expr_list) {
166 g_string_append_c (string, '[');
167 for (list = select->expr_list; list; list = list->next) {
168 if (list != select->expr_list)
169 g_string_append_c (string, ',');
170 str = gda_sql_select_field_serialize ((GdaSqlSelectField*) 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 if (select->from) {
180 g_string_append (string, ",\"from\":");
181 str = gda_sql_select_from_serialize (select->from);
182 g_string_append (string, str);
183 g_free (str);
184 }
185
186 if (select->where_cond) {
187 g_string_append (string, ",\"where\":");
188 str = gda_sql_expr_serialize (select->where_cond);
189 g_string_append (string, str);
190 g_free (str);
191 }
192
193 if (select->group_by) {
194 g_string_append (string, ",\"group_by\":");
195 g_string_append_c (string, '[');
196 for (list = select->group_by; list; list = list->next) {
197 if (list != select->group_by)
198 g_string_append_c (string, ',');
199 str = gda_sql_expr_serialize ((GdaSqlExpr*) list->data);
200 g_string_append (string, str);
201 g_free (str);
202 }
203 g_string_append_c (string, ']');
204 }
205
206 if (select->having_cond) {
207 g_string_append (string, ",\"having\":");
208 str = gda_sql_expr_serialize (select->having_cond);
209 g_string_append (string, str);
210 g_free (str);
211 }
212
213 if (select->order_by) {
214 g_string_append (string, ",\"order_by\":");
215 g_string_append_c (string, '[');
216 for (list = select->order_by; list; list = list->next) {
217 if (list != select->order_by)
218 g_string_append_c (string, ',');
219 str = gda_sql_select_order_serialize ((GdaSqlSelectOrder*) list->data);
220 g_string_append (string, str);
221 g_free (str);
222 }
223 g_string_append_c (string, ']');
224 }
225
226 if (select->limit_count) {
227 g_string_append (string, ",\"limit\":");
228 str = gda_sql_expr_serialize (select->limit_count);
229 g_string_append (string, str);
230 g_free (str);
231
232 if (select->limit_offset) {
233 g_string_append (string, ",\"offset\":");
234 str = gda_sql_expr_serialize (select->limit_offset);
235 g_string_append (string, str);
236 g_free (str);
237 }
238 }
239
240 g_string_append_c (string, '}');
241 str = string->str;
242 g_string_free (string, FALSE);
243 return str;
244 }
245
246 /**
247 * gda_sql_statement_select_take_distinct
248 * @stmt: a #GdaSqlStatement pointer
249 * @distinct: a TRUE/FALSE value
250 * @distinct_expr: (allow-none): a #GdaSqlExpr pointer representing what the DISTINCT is on, or %NULL
251 *
252 * Sets the DISTINCT clause of @stmt.
253 *
254 * @distinct_expr's ownership is transferred to
255 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
256 */
257 void
gda_sql_statement_select_take_distinct(GdaSqlStatement * stmt,gboolean distinct,GdaSqlExpr * distinct_expr)258 gda_sql_statement_select_take_distinct (GdaSqlStatement *stmt, gboolean distinct, GdaSqlExpr *distinct_expr)
259 {
260 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
261 select->distinct = distinct;
262 select->distinct_expr = distinct_expr;
263 gda_sql_any_part_set_parent (select->distinct_expr, select);
264 }
265
266 /**
267 * gda_sql_statement_select_take_expr_list
268 * @stmt: a #GdaSqlStatement pointer
269 * @expr_list: a list of #GdaSqlSelectField pointers
270 *
271 * Sets list of expressions selected by @stmt
272 *
273 * @expr_list's ownership is transferred to
274 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
275 */
276 void
gda_sql_statement_select_take_expr_list(GdaSqlStatement * stmt,GSList * expr_list)277 gda_sql_statement_select_take_expr_list (GdaSqlStatement *stmt, GSList *expr_list)
278 {
279 GSList *l;
280 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
281 select->expr_list = expr_list;
282 for (l = expr_list; l; l = l->next)
283 gda_sql_any_part_set_parent (l->data, select);
284 }
285
286 /**
287 * gda_sql_statement_select_take_from
288 * @stmt: a #GdaSqlStatement pointer
289 * @from: a #GdaSqlSelectFrom pointer
290 *
291 * Sets the FROM clause of @stmt
292 *
293 * @from's ownership is transferred to
294 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
295 */
296 void
gda_sql_statement_select_take_from(GdaSqlStatement * stmt,GdaSqlSelectFrom * from)297 gda_sql_statement_select_take_from (GdaSqlStatement *stmt, GdaSqlSelectFrom *from)
298 {
299 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
300 select->from = from;
301 gda_sql_any_part_set_parent (from, select);
302 }
303
304 /**
305 * gda_sql_statement_select_take_where_cond
306 * @stmt: a #GdaSqlStatement pointer
307 * @expr: a #GdaSqlExpr pointer
308 *
309 * Sets the WHERE clause of @stmt
310 *
311 * @expr's ownership is transferred to
312 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
313 */
314 void
gda_sql_statement_select_take_where_cond(GdaSqlStatement * stmt,GdaSqlExpr * expr)315 gda_sql_statement_select_take_where_cond (GdaSqlStatement *stmt, GdaSqlExpr *expr)
316 {
317 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
318 select->where_cond = expr;
319 gda_sql_any_part_set_parent (expr, select);
320 }
321
322 /**
323 * gda_sql_statement_select_take_group_by
324 * @stmt: a #GdaSqlStatement pointer
325 * @group_by: a list of #GdaSqlExpr pointer
326 *
327 * Sets the GROUP BY clause of @stmt
328 *
329 * @group_by's ownership is transferred to
330 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
331 */
332 void
gda_sql_statement_select_take_group_by(GdaSqlStatement * stmt,GSList * group_by)333 gda_sql_statement_select_take_group_by (GdaSqlStatement *stmt, GSList *group_by)
334 {
335 GSList *l;
336 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
337 select->group_by = group_by;
338 for (l = group_by; l; l = l->next)
339 gda_sql_any_part_set_parent (l->data, select);
340 }
341
342 /**
343 * gda_sql_statement_select_take_having_cond
344 * @stmt: a #GdaSqlStatement pointer
345 * @expr: a #GdaSqlExpr pointer
346 *
347 * Sets the HAVING clause of @stmt
348 *
349 * @expr's ownership is transferred to
350 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
351 */
352 void
gda_sql_statement_select_take_having_cond(GdaSqlStatement * stmt,GdaSqlExpr * expr)353 gda_sql_statement_select_take_having_cond (GdaSqlStatement *stmt, GdaSqlExpr *expr)
354 {
355 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
356 select->having_cond = expr;
357 gda_sql_any_part_set_parent (expr, select);
358 }
359
360 /**
361 * gda_sql_statement_select_take_order_by
362 * @stmt: a #GdaSqlStatement pointer
363 * @order_by: a list of #GdaSqlSelectOrder pointer
364 *
365 * Sets the ORDER BY clause of @stmt
366 *
367 * @order_by's ownership is transferred to
368 * @stmt (which means @stmt is then responsible for freeing it when no longer needed).
369 */
370 void
gda_sql_statement_select_take_order_by(GdaSqlStatement * stmt,GSList * order_by)371 gda_sql_statement_select_take_order_by (GdaSqlStatement *stmt, GSList *order_by)
372 {
373 GSList *l;
374 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
375 select->order_by = order_by;
376 for (l = order_by; l; l = l->next)
377 gda_sql_any_part_set_parent (l->data, select);
378 }
379
380 /**
381 * gda_sql_statement_select_take_limits
382 * @stmt: a #GdaSqlStatement pointer
383 * @count: a #GdaSqlExpr pointer
384 * @offset: a #GdaSqlExpr pointer
385 *
386 * Sets the LIMIT clause of @stmt
387 *
388 * @count and @offset's responsibility are transferred to
389 * @stmt (which means @stmt is then responsible for freeing them when no longer needed).
390 */
391 void
gda_sql_statement_select_take_limits(GdaSqlStatement * stmt,GdaSqlExpr * count,GdaSqlExpr * offset)392 gda_sql_statement_select_take_limits (GdaSqlStatement *stmt, GdaSqlExpr *count, GdaSqlExpr *offset)
393 {
394 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt->contents;
395 select->limit_count = count;
396 gda_sql_any_part_set_parent (count, select);
397 select->limit_offset = offset;
398 gda_sql_any_part_set_parent (offset, select);
399 }
400
401 static gboolean
gda_sql_statement_select_check_structure(GdaSqlAnyPart * stmt,G_GNUC_UNUSED gpointer data,GError ** error)402 gda_sql_statement_select_check_structure (GdaSqlAnyPart *stmt, G_GNUC_UNUSED gpointer data, GError **error)
403 {
404 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt;
405 if (!select->expr_list) {
406 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
407 "%s", _("SELECT does not contain any expression"));
408 return FALSE;
409 }
410
411 if (select->distinct_expr && !select->distinct) {
412 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
413 "%s", _("SELECT can't have a DISTINCT expression if DISTINCT is not set"));
414 return FALSE;
415 }
416
417 if (select->having_cond && !select->group_by) {
418 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
419 "%s", _("SELECT can't have a HAVING without GROUP BY"));
420 return FALSE;
421 }
422
423 if (select->limit_offset && !select->limit_count) {
424 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_STRUCTURE_CONTENTS_ERROR,
425 "%s", _("SELECT can't have a limit offset without a limit"));
426 return FALSE;
427 }
428 return TRUE;
429 }
430
431 static gboolean
gda_sql_statement_select_check_validity(GdaSqlAnyPart * stmt,G_GNUC_UNUSED gpointer data,GError ** error)432 gda_sql_statement_select_check_validity (GdaSqlAnyPart *stmt, G_GNUC_UNUSED gpointer data, GError **error)
433 {
434 GdaSqlStatementSelect *select = (GdaSqlStatementSelect *) stmt;
435 gboolean retval = TRUE;
436
437 /* validate target's names and aliases:
438 * - there can't be 2 targets with the same alias
439 * - each target name or alias can only reference at most one target
440 */
441 if (select->from && select->from->targets) {
442 GHashTable *hash; /* key = target name or alias, value = GdaSqlSelectTarget pointer */
443 GSList *list;
444 hash = g_hash_table_new (g_str_hash, g_str_equal);
445 for (list = select->from->targets; list; list = list->next) {
446 GdaSqlSelectTarget *t = (GdaSqlSelectTarget*) list->data;
447 if (t->as) {
448 if (g_hash_table_lookup (hash, t->as)) {
449 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_VALIDATION_ERROR,
450 _("Multiple targets named or aliased '%s'"), t->as);
451 retval = FALSE;
452 break;
453 }
454 g_hash_table_insert (hash, t->as, t);
455 }
456 else if (t->table_name) {
457 if (g_hash_table_lookup (hash, t->table_name)) {
458 g_set_error (error, GDA_SQL_ERROR, GDA_SQL_VALIDATION_ERROR,
459 _("Multiple targets named or aliased '%s'"), t->table_name);
460 retval = FALSE;
461 break;
462 }
463 g_hash_table_insert (hash, t->table_name, t);
464 }
465
466 if (!retval)
467 break;
468 }
469 g_hash_table_destroy (hash);
470 }
471
472 return retval;
473 }
474