@@ -480,6 +480,7 @@ typedef enum MetaCommand
480480META_SHELL ,/* \shell */
481481META_SLEEP ,/* \sleep */
482482META_GSET ,/* \gset */
483+ META_ASET ,/* \aset */
483484META_IF ,/* \if */
484485META_ELIF ,/* \elif */
485486META_ELSE ,/* \else */
@@ -504,14 +505,16 @@ static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
504505 *not applied.
505506 * first_lineA short, single-line extract of 'lines', for error reporting.
506507 * typeSQL_COMMAND or META_COMMAND
507- * metaThe type of meta-command, or META_NONE if command is SQL
508+ * metaThe type of meta-command, with META_NONE/GSET/ASET if command
509+ *is SQL.
508510 * argcNumber of arguments of the command, 0 if not yet processed.
509511 * argvCommand arguments, the first of which is the command or SQL
510512 *string itself. For SQL commands, after post-processing
511513 *argv[0] is the same as 'lines' with variables substituted.
512- * varprefix SQL commands terminated with \gset have this set
514+ * varprefix SQL commands terminated with \gsetor \aset have this set
513515 *to a non NULL value. If nonempty, it's used to prefix the
514516 *variable name that receives the value.
517+ * asetdo gset on all possible queries of a combined query (\;).
515518 * exprParsed expression, if needed.
516519 * statsTime spent in this command.
517520 */
@@ -2489,6 +2492,8 @@ getMetaCommand(const char *cmd)
24892492mc = META_ENDIF ;
24902493else if (pg_strcasecmp (cmd ,"gset" )== 0 )
24912494mc = META_GSET ;
2495+ else if (pg_strcasecmp (cmd ,"aset" )== 0 )
2496+ mc = META_ASET ;
24922497else
24932498mc = META_NONE ;
24942499return mc ;
@@ -2711,17 +2716,25 @@ sendCommand(CState *st, Command *command)
27112716 * Process query response from the backend.
27122717 *
27132718 * If varprefix is not NULL, it's the variable name prefix where to store
2714- * the results of the *last* command.
2719+ * the results of the *last* command (META_GSET) or *all* commands
2720+ * (META_ASET).
27152721 *
27162722 * Returns true if everything is A-OK, false if any error occurs.
27172723 */
27182724static bool
2719- readCommandResponse (CState * st ,char * varprefix )
2725+ readCommandResponse (CState * st ,MetaCommand meta , char * varprefix )
27202726{
27212727PGresult * res ;
27222728PGresult * next_res ;
27232729int qrynum = 0 ;
27242730
2731+ /*
2732+ * varprefix should be set only with \gset or \aset, and SQL commands do
2733+ * not need it.
2734+ */
2735+ Assert ((meta == META_NONE && varprefix == NULL )||
2736+ ((meta == META_GSET || meta == META_ASET )&& varprefix != NULL ));
2737+
27252738res = PQgetResult (st -> con );
27262739
27272740while (res != NULL )
@@ -2736,7 +2749,7 @@ readCommandResponse(CState *st, char *varprefix)
27362749{
27372750case PGRES_COMMAND_OK :/* non-SELECT commands */
27382751case PGRES_EMPTY_QUERY :/* may be used for testing no-op overhead */
2739- if (is_last && varprefix != NULL )
2752+ if (is_last && meta == META_GSET )
27402753{
27412754pg_log_error ("client %d script %d command %d query %d: expected one row, got %d" ,
27422755st -> id ,st -> use_file ,st -> command ,qrynum ,0 );
@@ -2745,14 +2758,22 @@ readCommandResponse(CState *st, char *varprefix)
27452758break ;
27462759
27472760case PGRES_TUPLES_OK :
2748- if (is_last && varprefix != NULL )
2761+ if (( is_last && meta == META_GSET ) || meta == META_ASET )
27492762{
2750- if (PQntuples (res )!= 1 )
2763+ int ntuples = PQntuples (res );
2764+
2765+ if (meta == META_GSET && ntuples != 1 )
27512766{
2767+ /* under \gset, report the error */
27522768pg_log_error ("client %d script %d command %d query %d: expected one row, got %d" ,
27532769st -> id ,st -> use_file ,st -> command ,qrynum ,PQntuples (res ));
27542770gotoerror ;
27552771}
2772+ else if (meta == META_ASET && ntuples <=0 )
2773+ {
2774+ /* coldly skip empty result under \aset */
2775+ break ;
2776+ }
27562777
27572778/* store results into variables */
27582779for (int fld = 0 ;fld < PQnfields (res );fld ++ )
@@ -2763,9 +2784,9 @@ readCommandResponse(CState *st, char *varprefix)
27632784if (* varprefix != '\0' )
27642785varname = psprintf ("%s%s" ,varprefix ,varname );
27652786
2766- /* store result as a string */
2767- if (!putVariable (st ,"gset" ,varname ,
2768- PQgetvalue (res ,0 ,fld )))
2787+ /* storelast row result as a string */
2788+ if (!putVariable (st ,meta == META_ASET ? "aset" : "gset" ,varname ,
2789+ PQgetvalue (res ,ntuples - 1 ,fld )))
27692790{
27702791/* internal error */
27712792pg_log_error ("client %d script %d command %d query %d: error storing into variable %s" ,
@@ -3181,7 +3202,9 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg)
31813202return ;/* don't have the whole result yet */
31823203
31833204/* store or discard the query results */
3184- if (readCommandResponse (st ,sql_script [st -> use_file ].commands [st -> command ]-> varprefix ))
3205+ if (readCommandResponse (st ,
3206+ sql_script [st -> use_file ].commands [st -> command ]-> meta ,
3207+ sql_script [st -> use_file ].commands [st -> command ]-> varprefix ))
31853208st -> state = CSTATE_END_COMMAND ;
31863209else
31873210st -> state = CSTATE_ABORTED ;
@@ -4660,7 +4683,7 @@ process_backslash_command(PsqlScanState sstate, const char *source)
46604683syntax_error (source ,lineno ,my_command -> first_line ,my_command -> argv [0 ],
46614684"unexpected argument" ,NULL ,-1 );
46624685}
4663- else if (my_command -> meta == META_GSET )
4686+ else if (my_command -> meta == META_GSET || my_command -> meta == META_ASET )
46644687{
46654688if (my_command -> argc > 2 )
46664689syntax_error (source ,lineno ,my_command -> first_line ,my_command -> argv [0 ],
@@ -4804,10 +4827,10 @@ ParseScript(const char *script, const char *desc, int weight)
48044827if (command )
48054828{
48064829/*
4807- * If this is gset, merge into the preceding command. (We
4808- * don't use a command slot in this case).
4830+ * If this is gset or aset , merge into the preceding command.
4831+ *(We don't use a command slot in this case).
48094832 */
4810- if (command -> meta == META_GSET )
4833+ if (command -> meta == META_GSET || command -> meta == META_ASET )
48114834{
48124835Command * cmd ;
48134836
@@ -4830,6 +4853,9 @@ ParseScript(const char *script, const char *desc, int weight)
48304853else
48314854cmd -> varprefix = pg_strdup (command -> argv [1 ]);
48324855
4856+ /* update the sql command meta */
4857+ cmd -> meta = command -> meta ;
4858+
48334859/* cleanup unused command */
48344860free_command (command );
48354861