[libgda] Added support in GdaSqlBuilder for DISTINCT and LIMIT clauses
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Added support in GdaSqlBuilder for DISTINCT and LIMIT clauses
- Date: Sun, 28 Feb 2010 14:10:37 +0000 (UTC)
commit c7499c9e8492c186c8fd51928870d34e3d3eead4
Author: Vivien Malerba <malerba gnome-db org>
Date: Sun Feb 28 15:10:17 2010 +0100
Added support in GdaSqlBuilder for DISTINCT and LIMIT clauses
doc/C/libgda-sections.txt | 2 +
doc/C/tmpl/gda-sql-builder.sgml | 20 ++++++++
libgda/gda-sql-builder.c | 104 +++++++++++++++++++++++++++++++++++++++
libgda/gda-sql-builder.h | 6 ++-
libgda/libgda.symbols | 2 +
tests/test-sql-builder.c | 74 ++++++++++++++++++++++++++--
6 files changed, 202 insertions(+), 6 deletions(-)
---
diff --git a/doc/C/libgda-sections.txt b/doc/C/libgda-sections.txt
index bc06c49..7bcc174 100644
--- a/doc/C/libgda-sections.txt
+++ b/doc/C/libgda-sections.txt
@@ -1692,6 +1692,8 @@ gda_sql_builder_select_add_field
gda_sql_builder_select_join_targets
gda_sql_builder_join_add_field
gda_sql_builder_select_order_by
+gda_sql_builder_select_set_distinct
+gda_sql_builder_select_set_limit
<SUBSECTION>
gda_sql_builder_compound_add_sub_select
gda_sql_builder_compound_set_type
diff --git a/doc/C/tmpl/gda-sql-builder.sgml b/doc/C/tmpl/gda-sql-builder.sgml
index 938eb4e..d124696 100644
--- a/doc/C/tmpl/gda-sql-builder.sgml
+++ b/doc/C/tmpl/gda-sql-builder.sgml
@@ -347,6 +347,26 @@ gda_sql_builder_add_cond2 (b, 5, GDA_SQL_OPERATOR_TYPE_AND, 3, 4); // whole expr
@collation_name:
+<!-- ##### FUNCTION gda_sql_builder_select_set_distinct ##### -->
+<para>
+
+</para>
+
+ builder:
+ distinct:
+ expr_id:
+
+
+<!-- ##### FUNCTION gda_sql_builder_select_set_limit ##### -->
+<para>
+
+</para>
+
+ builder:
+ limit_count_expr_id:
+ limit_offest_expr_id:
+
+
<!-- ##### FUNCTION gda_sql_builder_compound_add_sub_select ##### -->
<para>
diff --git a/libgda/gda-sql-builder.c b/libgda/gda-sql-builder.c
index 4bf5427..a59c3b4 100644
--- a/libgda/gda-sql-builder.c
+++ b/libgda/gda-sql-builder.c
@@ -1307,6 +1307,110 @@ gda_sql_builder_select_order_by (GdaSqlBuilder *builder, guint expr_id,
}
/**
+ * gda_sql_builder_select_set_distinct
+ * @builder: a #GdaSqlBuilder object
+ * @distinct: set to %TRUE to have the DISTINCT requirement
+ * @expr_id: the ID of the DISTINCT ON expression, or %0 if no expression is to be used. It is ignored
+ * if @distinct is %FALSE.
+ *
+ * Defines (if @distinct is %TRUE) or removes (if @distinct is %FALSE) a DISTINCT clause
+ * for a SELECT statement.
+ *
+ * If @distinct is %TRUE, then the ID of an expression can be specified as the @expr_id argument:
+ * if not %0, this is the expression used to apply the DISTINCT clause on (the resuting SQL
+ * will then usually be "... DISTINCT ON <expression>...").
+ *
+ * Since: 4.2
+ */
+void
+gda_sql_builder_select_set_distinct (GdaSqlBuilder *builder, gboolean distinct, guint expr_id)
+{
+ GdaSqlStatementSelect *sel;
+ SqlPart *part = NULL;
+
+ g_return_if_fail (GDA_IS_SQL_BUILDER (builder));
+
+ if (builder->priv->main_stmt->stmt_type != GDA_SQL_STATEMENT_SELECT) {
+ g_warning (_("Wrong statement type"));
+ return;
+ }
+
+ if (expr_id) {
+ part = get_part (builder, expr_id, GDA_SQL_ANY_EXPR);
+ if (!part)
+ return;
+ }
+
+ sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+ if (sel->distinct_expr) {
+ gda_sql_expr_free (sel->distinct_expr);
+ sel->distinct_expr = NULL;
+ }
+
+ if (distinct && part)
+ sel->distinct_expr = (GdaSqlExpr*) use_part (part, GDA_SQL_ANY_PART (sel));
+ sel->distinct = distinct;
+}
+
+/**
+ * gda_sql_builder_select_set_limit
+ * @builder: a #GdaSqlBuilder object
+ * @limit_count_expr_id: the ID of the LIMIT expression, or %0
+ * @limit_offset_expr_id: the ID of the OFFSET expression, or %0
+ *
+ * If @limit_count_expr_id is not %0, defines the maximum number of rows in the #GdaDataModel
+ * resulting from the execution of the built statement. In this case, the offset from which the
+ * rows must be collected can be defined by the @limit_offset_expr_id expression if not %0 (note that
+ * this feature may not be supported by all the database providers).
+ *
+ * If @limit_count_expr_id is %0, then removes any LIMIT which may have been imposed by a previous
+ * call to this method.
+ *
+ * Since: 4.2
+ */
+void
+gda_sql_builder_select_set_limit (GdaSqlBuilder *builder,
+ guint limit_count_expr_id, guint limit_offset_expr_id)
+{
+ GdaSqlStatementSelect *sel;
+ SqlPart *part1 = NULL, *part2 = NULL;
+
+ g_return_if_fail (GDA_IS_SQL_BUILDER (builder));
+
+ if (builder->priv->main_stmt->stmt_type != GDA_SQL_STATEMENT_SELECT) {
+ g_warning (_("Wrong statement type"));
+ return;
+ }
+
+ if (limit_count_expr_id) {
+ part1 = get_part (builder, limit_count_expr_id, GDA_SQL_ANY_EXPR);
+ if (!part1)
+ return;
+ }
+ if (limit_offset_expr_id) {
+ part2 = get_part (builder, limit_offset_expr_id, GDA_SQL_ANY_EXPR);
+ if (!part2)
+ return;
+ }
+
+ sel = (GdaSqlStatementSelect*) builder->priv->main_stmt->contents;
+
+ if (sel->limit_count) {
+ gda_sql_expr_free (sel->limit_count);
+ sel->limit_count = NULL;
+ }
+ if (sel->limit_offset) {
+ gda_sql_expr_free (sel->limit_offset);
+ sel->limit_offset = NULL;
+ }
+ if (part1)
+ sel->limit_count = (GdaSqlExpr*) use_part (part1, GDA_SQL_ANY_PART (sel));
+ if (part2)
+ sel->limit_offset = (GdaSqlExpr*) use_part (part2, GDA_SQL_ANY_PART (sel));
+}
+
+
+/**
* gda_sql_builder_add_function
* @builder: a #GdaSqlBuilder object
* @id: the requested ID, or 0 if to be determined by @builder
diff --git a/libgda/gda-sql-builder.h b/libgda/gda-sql-builder.h
index d3a2ad0..f8f7dd3 100644
--- a/libgda/gda-sql-builder.h
+++ b/libgda/gda-sql-builder.h
@@ -1,6 +1,6 @@
/* gda-sql-builder.h
*
- * Copyright (C) 2009 Vivien Malerba
+ * Copyright (C) 2009 - 2010 Vivien Malerba
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
@@ -115,6 +115,10 @@ guint gda_sql_builder_select_join_targets (GdaSqlBuilder *builder, g
void gda_sql_builder_join_add_field (GdaSqlBuilder *builder, guint join_id, const gchar *field_name);
void gda_sql_builder_select_order_by (GdaSqlBuilder *builder, guint expr_id,
gboolean asc, const gchar *collation_name);
+void gda_sql_builder_select_set_distinct (GdaSqlBuilder *builder,
+ gboolean distinct, guint expr_id);
+void gda_sql_builder_select_set_limit (GdaSqlBuilder *builder,
+ guint limit_count_expr_id, guint limit_offest_expr_id);
/* COMPOUND SELECT Statement API */
void gda_sql_builder_compound_set_type (GdaSqlBuilder *builder, GdaSqlStatementCompoundType compound_type);
diff --git a/libgda/libgda.symbols b/libgda/libgda.symbols
index 21dc7bc..65c919d 100644
--- a/libgda/libgda.symbols
+++ b/libgda/libgda.symbols
@@ -600,6 +600,8 @@
gda_sql_builder_select_add_target_id
gda_sql_builder_select_join_targets
gda_sql_builder_select_order_by
+ gda_sql_builder_select_set_distinct
+ gda_sql_builder_select_set_limit
gda_sql_builder_set_table
gda_sql_builder_set_where
gda_sql_case_copy
diff --git a/tests/test-sql-builder.c b/tests/test-sql-builder.c
index b95abee..92c9be8 100644
--- a/tests/test-sql-builder.c
+++ b/tests/test-sql-builder.c
@@ -40,6 +40,8 @@ static GdaSqlStatement *build6 (void);
static GdaSqlStatement *build7 (void);
static GdaSqlStatement *build8 (void);
static GdaSqlStatement *build9 (void);
+static GdaSqlStatement *build10 (void);
+static GdaSqlStatement *build11 (void);
ATest tests[] = {
{"build0", build0, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"false\",\"fields\":[{\"expr\":{\"value\":\"*\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]}}}"},
@@ -51,7 +53,9 @@ ATest tests[] = {
{"build6", build6, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"false\",\"fields\":[{\"expr\":{\"value\":\"fav_id\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]},\"where\":{\"operation\":{\"operator\":\"AND\",\"operand0\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"order_key\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"orderkey\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}}},\"operand1\":{\"operation\":{\"operator\":\"!=\",\"operand0\":{\"value\":\"fav_id\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"id\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}}}}}}}"},
{"build7", build7, "{\"sql\":null,\"stmt_type\":\"UPDATE\",\"contents\":{\"table\":\"mytable\",\"fields\":[\"rank\"],\"expressions\":[{\"value\":null,\"param_spec\":{\"name\":\"newrank\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}],\"condition\":{\"operation\":{\"operator\":\"AND\",\"operand0\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"fav_id\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"id\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}}},\"operand1\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"order_key\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"orderkey\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}}},\"operand2\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"rank\",\"descr\":null,\"type\":\"in
t\",\"is_param\":true,\"nullok\":false}}}}}}}}"},
{"build8", build8, "{\"sql\":null,\"stmt_type\":\"DELETE\",\"contents\":{\"table\":\"mytable\",\"condition\":{\"operation\":{\"operator\":\"=\",\"operand0\":{\"value\":\"id\",\"sqlident\":\"TRUE\"},\"operand1\":{\"value\":null,\"param_spec\":{\"name\":\"id\",\"descr\":null,\"type\":\"int\",\"is_param\":true,\"nullok\":false}}}}}}"},
- {"build8", build9, "{\"sql\":null,\"stmt_type\":\"INSERT\",\"contents\":{\"table\":\"mytable\",\"fields\":[\"session\",\"name\"],\"values\":[[{\"value\":\"NULL\"},{\"value\":\"NULL\"}]]}}"}
+ {"build9", build9, "{\"sql\":null,\"stmt_type\":\"INSERT\",\"contents\":{\"table\":\"mytable\",\"fields\":[\"session\",\"name\"],\"values\":[[{\"value\":\"NULL\"},{\"value\":\"NULL\"}]]}}"},
+ {"build10", build10, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"true\",\"fields\":[{\"expr\":{\"value\":\"fav_id\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]},\"limit\":{\"value\":\"5\"}}}"},
+ {"build11", build11, "{\"sql\":null,\"stmt_type\":\"SELECT\",\"contents\":{\"distinct\":\"true\",\"distinct_on\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"},\"fields\":[{\"expr\":{\"value\":\"fav_id\",\"sqlident\":\"TRUE\"}},{\"expr\":{\"value\":\"rank\",\"sqlident\":\"TRUE\"}}],\"from\":{\"targets\":[{\"expr\":{\"value\":\"mytable\",\"sqlident\":\"TRUE\"},\"table_name\":\"mytable\"}]},\"limit\":{\"value\":\"5\"},\"offset\":{\"value\":\"2\"}}}"}
};
int
@@ -429,14 +433,74 @@ build9 (void)
gda_sql_builder_add_field_value (builder, "name", value);
gda_value_free (value);
+ stmt = gda_sql_builder_get_sql_statement (builder, FALSE);
+ g_object_unref (builder);
+
+ return stmt;
+}
+
+/*
+ * SELECT DISTINCT fav_id, rank FROM mytable LIMIT 5
+ */
+static GdaSqlStatement *
+build10 (void)
+{
+ GdaSqlBuilder *b;
+ GdaSqlStatement *stmt;
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+ gda_sql_builder_add_field_id (b, gda_sql_builder_add_id (b, 0, "fav_id"), 0);
+ gda_sql_builder_add_field_id (b, gda_sql_builder_add_id (b, 0, "rank"), 0);
+
+ gda_sql_builder_select_add_target_id (b, 0,
+ gda_sql_builder_add_id (b, 0, "mytable"),
+ NULL);
+ gda_sql_builder_select_set_distinct (b, TRUE, 0);
+ gda_sql_builder_select_set_limit (b, gda_sql_builder_add_expr (b, 0, NULL, G_TYPE_INT, 5), 0);
+
{
GdaStatement *st;
- st = gda_sql_builder_get_statement (builder, FALSE);
+ st = gda_sql_builder_get_statement (b, FALSE);
g_print ("[%s]\n", gda_statement_to_sql (st, NULL, NULL));
g_object_unref (st);
}
- stmt = gda_sql_builder_get_sql_statement (builder, FALSE);
- g_object_unref (builder);
-
+
+ stmt = gda_sql_builder_get_sql_statement (b, FALSE);
+ g_object_unref (b);
+ return stmt;
+}
+
+/*
+ * SELECT DISTINCT ON (rank) fav_id, rank FROM mytable LIMIT 5 OFFSET 2
+ */
+static GdaSqlStatement *
+build11 (void)
+{
+ GdaSqlBuilder *b;
+ GdaSqlStatement *stmt;
+
+ b = gda_sql_builder_new (GDA_SQL_STATEMENT_SELECT);
+ gda_sql_builder_add_field_id (b, gda_sql_builder_add_id (b, 0, "fav_id"), 0);
+ gda_sql_builder_add_field_id (b, gda_sql_builder_add_id (b, 0, "rank"), 0);
+
+ gda_sql_builder_select_add_target_id (b, 0,
+ gda_sql_builder_add_id (b, 0, "mytable"),
+ NULL);
+ gda_sql_builder_select_set_distinct (b, TRUE,
+ gda_sql_builder_add_id (b, 0, "rank"));
+ gda_sql_builder_select_set_limit (b, gda_sql_builder_add_expr (b, 0, NULL, G_TYPE_INT, 5),
+ gda_sql_builder_add_expr (b, 0, NULL, G_TYPE_INT, 2));
+
+#ifdef DEBUG_NO
+ {
+ GdaStatement *st;
+ st = gda_sql_builder_get_statement (b, FALSE);
+ g_print ("[%s]\n", gda_statement_to_sql (st, NULL, NULL));
+ g_object_unref (st);
+ }
+#endif
+
+ stmt = gda_sql_builder_get_sql_statement (b, FALSE);
+ g_object_unref (b);
return stmt;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]