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