[libgda] Correctly parse "NOT LIKE" and "NOT ILIKE" expressions



commit 835c7d599124bd0a579ca59c5e3bf5a738beef7c
Author: Vivien Malerba <malerba gnome-db org>
Date:   Fri Jul 27 12:45:50 2012 +0200

    Correctly parse "NOT LIKE" and "NOT ILIKE" expressions

 libgda/gda-statement.c                         |    6 ++++++
 libgda/sql-parser/gda-sql-parser.c             |   13 +++++++++----
 libgda/sql-parser/gda-statement-struct-parts.c |    4 ++++
 libgda/sql-parser/gda-statement-struct-parts.h |    5 ++++-
 libgda/sql-parser/gda-statement-struct.c       |    2 ++
 libgda/sql-parser/parser.y                     |    4 +++-
 libgda/sqlite/gda-sqlite-provider.c            |    9 +++++++++
 providers/firebird/parser.y                    |    3 ++-
 providers/oracle/parser.y                      |    3 ++-
 providers/reuseable/mysql/parser.y             |    3 ++-
 providers/reuseable/postgres/parser.y          |    4 +++-
 providers/skel-implementation/capi/parser.y    |    3 ++-
 12 files changed, 48 insertions(+), 11 deletions(-)
---
diff --git a/libgda/gda-statement.c b/libgda/gda-statement.c
index 46f2ab1..bac7768 100644
--- a/libgda/gda-statement.c
+++ b/libgda/gda-statement.c
@@ -1803,9 +1803,15 @@ default_render_operation (GdaSqlOperation *op, GdaSqlRenderingContext *context,
 	case GDA_SQL_OPERATOR_TYPE_LIKE:
 		str = g_strdup_printf ("%s LIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
 		break;
+	case GDA_SQL_OPERATOR_TYPE_NOTLIKE:
+		str = g_strdup_printf ("%s NOT LIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
+		break;
 	case GDA_SQL_OPERATOR_TYPE_ILIKE:
 		str = g_strdup_printf ("%s ILIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
 		break;
+	case GDA_SQL_OPERATOR_TYPE_NOTILIKE:
+		str = g_strdup_printf ("%s NOT ILIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
+		break;
 	case GDA_SQL_OPERATOR_TYPE_GT:
 		str = g_strdup_printf ("%s > %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
 		break;
diff --git a/libgda/sql-parser/gda-sql-parser.c b/libgda/sql-parser/gda-sql-parser.c
index 94f3800..8393658 100644
--- a/libgda/sql-parser/gda-sql-parser.c
+++ b/libgda/sql-parser/gda-sql-parser.c
@@ -1033,7 +1033,7 @@ token_as_string (gchar *ptr, gint len)
 	return retval;
 }
 
-static void
+static gboolean
 handle_composed_2_keywords (GdaSqlParser *parser, GValue *retval, gint second, gint replacer);
 
 /*
@@ -1514,8 +1514,11 @@ getToken (GdaSqlParser *parser)
 		handle_composed_2_keywords (parser, retval, L_LOOP, L_ENDLOOP);
 	else if (parser->priv->context->token_type == L_IS)
 		handle_composed_2_keywords (parser, retval, L_NULL, L_ISNULL);
-	else if (parser->priv->context->token_type == L_NOT)
-		handle_composed_2_keywords (parser, retval, L_NULL, L_NOTNULL);
+	else if (parser->priv->context->token_type == L_NOT) {
+		handle_composed_2_keywords (parser, retval, L_NULL, L_NOTNULL) ||
+			handle_composed_2_keywords (parser, retval, L_LIKE, L_NOTLIKE) ||
+			handle_composed_2_keywords (parser, retval, L_ILIKE, L_NOTILIKE);
+	}
 	else if (parser->priv->context->token_type == L_SIMILAR)
 		handle_composed_2_keywords (parser, retval, L_TO, L_SIMILAR);
 
@@ -1533,7 +1536,7 @@ getToken (GdaSqlParser *parser)
 	return retval;
 }
 
-static void
+static gboolean
 handle_composed_2_keywords (GdaSqlParser *parser, GValue *retval, gint second, gint replacer)
 {
 	gint npushed, nmatched;
@@ -1547,11 +1550,13 @@ handle_composed_2_keywords (GdaSqlParser *parser, GValue *retval, gint second, g
 		newstr = g_strdup_printf ("%s %s", g_value_get_string (retval), g_value_get_string (v));
 		g_value_reset (retval);
 		g_value_take_string (retval, newstr);
+		return TRUE;
 	}
 	if (v) {
 		g_value_reset (v);
 		g_free (v);
 	}
+	return FALSE;
 }
 
 static GValue *
diff --git a/libgda/sql-parser/gda-statement-struct-parts.c b/libgda/sql-parser/gda-statement-struct-parts.c
index b656a70..9a5a37c 100644
--- a/libgda/sql-parser/gda-statement-struct-parts.c
+++ b/libgda/sql-parser/gda-statement-struct-parts.c
@@ -773,6 +773,10 @@ gda_sql_operation_operator_to_string (GdaSqlOperatorType op)
 		return "|";
 	case GDA_SQL_OPERATOR_TYPE_BITNOT:
 		return "~";
+	case GDA_SQL_OPERATOR_TYPE_NOTLIKE:
+		return "NOT LIKE";
+	case GDA_SQL_OPERATOR_TYPE_NOTILIKE:
+		return "NOT ILIKE";
 	default:
 		g_error ("Unhandled operator constant %d\n", op);
 		return NULL;
diff --git a/libgda/sql-parser/gda-statement-struct-parts.h b/libgda/sql-parser/gda-statement-struct-parts.h
index b1ded29..956feec 100644
--- a/libgda/sql-parser/gda-statement-struct-parts.h
+++ b/libgda/sql-parser/gda-statement-struct-parts.h
@@ -312,7 +312,10 @@ typedef enum {
 	GDA_SQL_OPERATOR_TYPE_BITAND,
 	GDA_SQL_OPERATOR_TYPE_BITOR,
 	GDA_SQL_OPERATOR_TYPE_BITNOT,
-	GDA_SQL_OPERATOR_TYPE_ILIKE
+	GDA_SQL_OPERATOR_TYPE_ILIKE,
+
+	GDA_SQL_OPERATOR_TYPE_NOTLIKE,
+	GDA_SQL_OPERATOR_TYPE_NOTILIKE
 } GdaSqlOperatorType;
 
 /**
diff --git a/libgda/sql-parser/gda-statement-struct.c b/libgda/sql-parser/gda-statement-struct.c
index b6e4a1c..1094901 100644
--- a/libgda/sql-parser/gda-statement-struct.c
+++ b/libgda/sql-parser/gda-statement-struct.c
@@ -1052,7 +1052,9 @@ gda_sql_any_part_check_structure (GdaSqlAnyPart *node, GError **error)
 		case GDA_SQL_OPERATOR_TYPE_EQ:
 		case GDA_SQL_OPERATOR_TYPE_IS:
 		case GDA_SQL_OPERATOR_TYPE_LIKE:
+		case GDA_SQL_OPERATOR_TYPE_NOTLIKE:
 		case GDA_SQL_OPERATOR_TYPE_ILIKE:
+		case GDA_SQL_OPERATOR_TYPE_NOTILIKE:
 		case GDA_SQL_OPERATOR_TYPE_GT:
 		case GDA_SQL_OPERATOR_TYPE_LT:
 		case GDA_SQL_OPERATOR_TYPE_GEQ:
diff --git a/libgda/sql-parser/parser.y b/libgda/sql-parser/parser.y
index 16c4d8a..e87fe62 100644
--- a/libgda/sql-parser/parser.y
+++ b/libgda/sql-parser/parser.y
@@ -254,7 +254,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE ILIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE NOTILIKE ILIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -824,6 +824,8 @@ expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
 expr(C) ::= expr(L) ILIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_ILIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
+expr(C) ::= expr(L) NOTILIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTILIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);
diff --git a/libgda/sqlite/gda-sqlite-provider.c b/libgda/sqlite/gda-sqlite-provider.c
index 6236c80..bfada09 100644
--- a/libgda/sqlite/gda-sqlite-provider.c
+++ b/libgda/sqlite/gda-sqlite-provider.c
@@ -2018,6 +2018,15 @@ sqlite_render_operation (GdaSqlOperation *op, GdaSqlRenderingContext *context, G
 	case GDA_SQL_OPERATOR_TYPE_LIKE:
 		str = g_strdup_printf ("%s LIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
 		break;
+	case GDA_SQL_OPERATOR_TYPE_NOTLIKE:
+		str = g_strdup_printf ("%s NOT LIKE %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
+		break;
+	case GDA_SQL_OPERATOR_TYPE_ILIKE:
+	case GDA_SQL_OPERATOR_TYPE_NOTILIKE:
+		g_set_error (error, GDA_STATEMENT_ERROR, GDA_STATEMENT_SYNTAX_ERROR,
+			     "%s", _("ILIKE operation sot supported"));
+		goto out;
+		break;
 	case GDA_SQL_OPERATOR_TYPE_GT:
 		str = g_strdup_printf ("%s > %s", SQL_OPERAND (sql_list->data)->sql, SQL_OPERAND (sql_list->next->data)->sql);
 		break;
diff --git a/providers/firebird/parser.y b/providers/firebird/parser.y
index 1b50e1e..622296d 100644
--- a/providers/firebird/parser.y
+++ b/providers/firebird/parser.y
@@ -251,7 +251,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -821,6 +821,7 @@ expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR
 expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);
diff --git a/providers/oracle/parser.y b/providers/oracle/parser.y
index 739ec16..2c43450 100644
--- a/providers/oracle/parser.y
+++ b/providers/oracle/parser.y
@@ -251,7 +251,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -821,6 +821,7 @@ expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR
 expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);
diff --git a/providers/reuseable/mysql/parser.y b/providers/reuseable/mysql/parser.y
index e6d4a4f..8c98f4a 100644
--- a/providers/reuseable/mysql/parser.y
+++ b/providers/reuseable/mysql/parser.y
@@ -251,7 +251,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -821,6 +821,7 @@ expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR
 expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);
diff --git a/providers/reuseable/postgres/parser.y b/providers/reuseable/postgres/parser.y
index 478532a..ba05097 100644
--- a/providers/reuseable/postgres/parser.y
+++ b/providers/reuseable/postgres/parser.y
@@ -253,7 +253,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE ILIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE NOTILIKE ILIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -824,6 +824,8 @@ expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
 expr(C) ::= expr(L) ILIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_ILIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
+expr(C) ::= expr(L) NOTILIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTILIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);
diff --git a/providers/skel-implementation/capi/parser.y b/providers/skel-implementation/capi/parser.y
index 5941ce8..8003f5e 100644
--- a/providers/skel-implementation/capi/parser.y
+++ b/providers/skel-implementation/capi/parser.y
@@ -251,7 +251,7 @@ compose_multiple_compounds (GdaSqlStatementCompoundType ctype, GdaSqlStatement *
 %left OR.
 %left AND.
 %right NOT.
-%left IS MATCH LIKE IN ISNULL NOTNULL DIFF EQ.
+%left IS MATCH NOTLIKE LIKE IN ISNULL NOTNULL DIFF EQ.
 %left BETWEEN.
 %left GT LEQ LT GEQ.
 %left REGEXP REGEXP_CI NOT_REGEXP NOT_REGEXP_CI.
@@ -821,6 +821,7 @@ expr(C) ::= expr(L) CONCAT expr(R). {C = compose_multiple_expr (GDA_SQL_OPERATOR
 expr(C) ::= expr(L) GT|LEQ|GEQ|LT(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) DIFF|EQ(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) LIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_LIKE, L, R);}
+expr(C) ::= expr(L) NOTLIKE expr(R). {C = create_two_expr (GDA_SQL_OPERATOR_TYPE_NOTLIKE, L, R);}
 expr(C) ::= expr(L) REGEXP|REGEXP_CI|NOT_REGEXP|NOT_REGEXP_CI|SIMILAR(O) expr(R). {C = create_two_expr (string_to_op_type (O), L, R);}
 expr(C) ::= expr(L) BETWEEN expr(R) AND expr(E). {GdaSqlOperation *cond;
 						  C = gda_sql_expr_new (NULL);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]