New TARGET satement, to redirect target function.
authorMarko Kreen <markokr@gmail.com>
Thu, 20 Jan 2011 15:12:44 +0000 (17:12 +0200)
committerMarko Kreen <markokr@gmail.com>
Thu, 20 Jan 2011 15:12:44 +0000 (17:12 +0200)
Makefile
doc/syntax.txt
src/parser.y
src/plproxy.h
src/query.c
src/scanner.l

index 30583a697e984e46d05df2fe44292d5c5952b501..8890abd3d073e0131bf99134430e3a3ef6f8fd23 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -37,7 +37,7 @@ DIST_FILES = Makefile src/plproxy.h src/rowstamp.h src/scanner.l src/parser.y \
 # regression testing setup
 REGRESS = plproxy_init plproxy_test plproxy_select plproxy_many \
          plproxy_errors plproxy_clustermap plproxy_dynamic_record \
-         plproxy_encoding plproxy_split
+         plproxy_encoding plproxy_split plproxy_target
 
 # SQL files
 PLPROXY_SQL = plproxy_lang.sql
index 95805db029d120c704f4435799cdf435b4951d1b..1b06c555fdb216f1961b249d880029c4c884f3f5 100644 (file)
@@ -130,6 +130,24 @@ And target partitions get queries:
   SELECT * FROM set_profiles(ARRAY['bar'], ARRAY['b']);
 
 
+== TARGET ==
+
+Specify function name on remote side to be called.  By default
+PL/Proxy uses current function name.
+
+Following function:
+
+  CREATE FUNCTION some_function(username text, num int4)
+  RETURNS SETOF text AS $$
+    CLUSTER 'userdb';
+    RUN ON hashtext(username);
+    TARGET other_function;
+  $$ LANGUAGE plproxy;
+
+will run following query on remote side:
+
+  SELECT * FROM other_function(username, num);
+
 == SELECT ==
 
   SELECT .... ;
index 13c7295dd28e0c3ea636c1cac8f1427e702c033d..a49ca2e7cfbdce25e304d681e7ea84a97acb9b95 100644 (file)
@@ -35,7 +35,7 @@ void plproxy_yy_scan_bytes(const char *bytes, int len);
 static ProxyFunction *xfunc;
 
 /* remember what happened */
-static int got_run, got_cluster, got_connect, got_split;
+static int got_run, got_cluster, got_connect, got_split, got_target;
 
 static QueryBuffer *cluster_sql;
 static QueryBuffer *select_sql;
@@ -48,7 +48,7 @@ static QueryBuffer *cur_sql;
 /* keep the resetting code together with variables */
 static void reset_parser_vars(void)
 {
-       got_run = got_cluster = got_connect = got_split = 0;
+       got_run = got_cluster = got_connect = got_split = got_target = 0;
        cur_sql = select_sql = cluster_sql = hash_sql = connect_sql = NULL;
        xfunc = NULL;
 }
@@ -59,7 +59,7 @@ static void reset_parser_vars(void)
 
 %token <str> CONNECT CLUSTER RUN ON ALL ANY SELECT
 %token <str> IDENT NUMBER FNCALL SPLIT STRING
-%token <str> SQLIDENT SQLPART
+%token <str> SQLIDENT SQLPART TARGET
 
 %union
 {
@@ -70,7 +70,7 @@ static void reset_parser_vars(void)
 
 body: | body stmt ;
 
-stmt: cluster_stmt | split_stmt | run_stmt | select_stmt | connect_stmt ;
+stmt: cluster_stmt | split_stmt | run_stmt | select_stmt | connect_stmt | target_stmt;
 
 connect_stmt: CONNECT connect_spec ';' {
                                        if (got_connect)
@@ -117,6 +117,15 @@ cluster_func: FNCALL       { cluster_sql = plproxy_query_start(xfunc, false);
 cluster_name: STRING   { xfunc->cluster_name = plproxy_func_strdup(xfunc, $1); }
                        ;
 
+target_stmt: TARGET target_name ';' {
+                                                       if (got_target)
+                                                               yyerror("Only one TARGET statement allowed");
+                                                       got_target = 1; }
+                  ;
+
+target_name: IDENT { xfunc->target_name = plproxy_func_strdup(xfunc, $1); }
+                  ;
+
 split_stmt: SPLIT split_spec ';' {
                                                        if (got_split)
                                                                yyerror("Only one SPLIT statement allowed");
@@ -237,6 +246,9 @@ void plproxy_run_parser(ProxyFunction *func, const char *body, int len)
                yyerror("SELECT statement not allowed");
 #endif
 
+       if (select_sql && got_target)
+               yyerror("TARGET cannot be used with SELECT");
+
        /* release scanner resources */
        plproxy_yylex_destroy();
 
index 31e6583f3b365fb81aa6ec11d20a6018fb6902f5..60ba3b2ad3cb620925b5ac1fa3b2438b69a9b2c6 100644 (file)
@@ -304,6 +304,7 @@ typedef struct ProxyFunction
        int                     exact_nr;               /* Hash value for R_EXACT */
        const char *connect_str;        /* libpq string for CONNECT function */
        ProxyQuery *connect_sql;        /* Optional query for CONNECT function */
+       const char *target_name;        /* Optional target function name */
 
        /*
         * calculated data
index d0e0577a2818251705f1c5b4887caa685f33700e..4386a20e721b3e972eadbf611e1f1504bb1f28fc 100644 (file)
@@ -163,6 +163,7 @@ plproxy_standard_query(ProxyFunction *func, bool add_types)
 {
        StringInfoData sql;
        ProxyQuery *pq;
+       const char *target;
        int                     i,
                                len;
 
@@ -193,7 +194,8 @@ plproxy_standard_query(ProxyFunction *func, bool add_types)
                appendStringInfo(&sql, "r::%s", func->ret_scalar->name);
 
        /* function call */
-       appendStringInfo(&sql, " from %s(", func->name);
+       target = func->target_name ? func->target_name : func->name;
+       appendStringInfo(&sql, " from %s(", target);
 
        /* fill in function arguments */
        for (i = 0; i < func->arg_count; i++)
index b494c9aabbeff009a5547e8381fad05cbc3da1a6..4c6079db742d06d9f85c6ded4f703622e930c24a 100644 (file)
@@ -183,6 +183,7 @@ on                  { return ON; }
 all                    { return ALL; }
 any                    { return ANY; }
 split          { return SPLIT; }
+target         { return TARGET; }
 select                 { BEGIN(sql); yylval.str = yytext; return SELECT; }
 
        /* function call */