aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
authorTomas Vondra <tomas.vondra@postgresql.org>2019-01-19 23:48:16 +0100
committerTomas Vondra <tomas.vondra@postgresql.org>2019-01-20 00:22:14 +0100
commit31f3817402da736b29014ace470cf70aeb126ac5 (patch)
treeab02bcacacdb944f47996f10435a94c9f0258543 /src/backend/parser
parentd6ef7fe75c1fb7ccc4ad8e3dd38d4e84d6fe9b9f (diff)
downloadpostgresql-31f3817402da736b29014ace470cf70aeb126ac5.tar.gz
postgresql-31f3817402da736b29014ace470cf70aeb126ac5.zip
Allow COPY FROM to filter data using WHERE conditions
Extends the COPY FROM command with a WHERE condition, which allows doing various types of filtering while importing the data (random sampling, condition on a data column, etc.). Until now such filtering required either preprocessing of the input data, or importing all data and then filtering in the database. COPY FROM ... WHERE is an easy-to-use and low-overhead alternative for most simple cases. Author: Surafel Temesgen Reviewed-by: Tomas Vondra, Masahiko Sawada, Lim Myungkyu Discussion: https://www.postgresql.org/message-id/flat/CALAY4q_DdpWDuB5-Zyi-oTtO2uSk8pmy+dupiRe3AvAc++1imA@mail.gmail.com
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y10
-rw-r--r--src/backend/parser/parse_agg.c11
-rw-r--r--src/backend/parser/parse_expr.c5
-rw-r--r--src/backend/parser/parse_func.c3
4 files changed, 28 insertions, 1 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c086235b253..d8a3c2d4cc6 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -2962,7 +2962,8 @@ ClosePortalStmt:
*****************************************************************************/
CopyStmt: COPY opt_binary qualified_name opt_column_list
- copy_from opt_program copy_file_name copy_delimiter opt_with copy_options
+ copy_from opt_program copy_file_name copy_delimiter opt_with
+ copy_options where_clause
{
CopyStmt *n = makeNode(CopyStmt);
n->relation = $3;
@@ -2971,6 +2972,7 @@ CopyStmt: COPY opt_binary qualified_name opt_column_list
n->is_from = $5;
n->is_program = $6;
n->filename = $7;
+ n->whereClause = $11;
if (n->is_program && n->filename == NULL)
ereport(ERROR,
@@ -2978,6 +2980,12 @@ CopyStmt: COPY opt_binary qualified_name opt_column_list
errmsg("STDIN/STDOUT not allowed with PROGRAM"),
parser_errposition(@8)));
+ if (!n->is_from && n->whereClause != NULL)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("WHERE clause not allowed with COPY TO"),
+ parser_errposition(@11)));
+
n->options = NIL;
/* Concatenate user-supplied flags */
if ($2)
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index bd6201e50a7..669fe82c48a 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -523,6 +523,14 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr)
break;
+ case EXPR_KIND_COPY_WHERE:
+ if (isAgg)
+ err = _("aggregate functions are not allowed in COPY FROM WHERE conditions");
+ else
+ err = _("grouping operations are not allowed in COPY FROM WHERE conditions");
+
+ break;
+
/*
* There is intentionally no default: case here, so that the
* compiler will warn if we add a new ParseExprKind without
@@ -902,6 +910,9 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
case EXPR_KIND_CALL_ARGUMENT:
err = _("window functions are not allowed in CALL arguments");
break;
+ case EXPR_KIND_COPY_WHERE:
+ err = _("window functions are not allowed in COPY FROM WHERE conditions");
+ break;
/*
* There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index bff237094ad..a47697a4215 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -1849,6 +1849,9 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
case EXPR_KIND_CALL_ARGUMENT:
err = _("cannot use subquery in CALL argument");
break;
+ case EXPR_KIND_COPY_WHERE:
+ err = _("cannot use subquery in COPY FROM WHERE condition");
+ break;
/*
* There is intentionally no default: case here, so that the
@@ -3475,6 +3478,8 @@ ParseExprKindName(ParseExprKind exprKind)
return "PARTITION BY";
case EXPR_KIND_CALL_ARGUMENT:
return "CALL";
+ case EXPR_KIND_COPY_WHERE:
+ return "WHERE";
/*
* There is intentionally no default: case here, so that the
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index 4661fc4f624..7213f5be17a 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -2370,6 +2370,9 @@ check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
case EXPR_KIND_CALL_ARGUMENT:
err = _("set-returning functions are not allowed in CALL arguments");
break;
+ case EXPR_KIND_COPY_WHERE:
+ err = _("set-returning functions are not allowed in COPY FROM WHERE conditions");
+ break;
/*
* There is intentionally no default: case here, so that the