@@ -480,6 +480,7 @@ typedef enum MetaCommand
480480 META_SHELL , /* \shell */
481481 META_SLEEP , /* \sleep */
482482 META_GSET , /* \gset */
483+ META_ASET , /* \aset */
483484 META_IF , /* \if */
484485 META_ELIF , /* \elif */
485486 META_ELSE , /* \else */
@@ -504,14 +505,16 @@ static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
504505 * not applied.
505506 * first_line A short, single-line extract of 'lines', for error reporting.
506507 * type SQL_COMMAND or META_COMMAND
507- * meta The type of meta-command, or META_NONE if command is SQL
508+ * meta The type of meta-command, with META_NONE/GSET/ASET if command
509+ * is SQL.
508510 * argc Number of arguments of the command, 0 if not yet processed.
509511 * argv Command 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 \gset or \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+ * aset do gset on all possible queries of a combined query (\;).
515518 * expr Parsed expression, if needed.
516519 * stats Time spent in this command.
517520 */
@@ -2489,6 +2492,8 @@ getMetaCommand(const char *cmd)
24892492 mc = META_ENDIF ;
24902493 else if (pg_strcasecmp (cmd , "gset" ) == 0 )
24912494 mc = META_GSET ;
2495+ else if (pg_strcasecmp (cmd , "aset" ) == 0 )
2496+ mc = META_ASET ;
24922497 else
24932498 mc = META_NONE ;
24942499 return 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{
27212727 PGresult * res ;
27222728 PGresult * next_res ;
27232729 int 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+
27252738 res = PQgetResult (st -> con );
27262739
27272740 while (res != NULL )
@@ -2736,7 +2749,7 @@ readCommandResponse(CState *st, char *varprefix)
27362749 {
27372750 case PGRES_COMMAND_OK : /* non-SELECT commands */
27382751 case 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 {
27412754 pg_log_error ("client %d script %d command %d query %d: expected one row, got %d" ,
27422755 st -> id , st -> use_file , st -> command , qrynum , 0 );
@@ -2745,14 +2758,22 @@ readCommandResponse(CState *st, char *varprefix)
27452758 break ;
27462759
27472760 case 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 */
27522768 pg_log_error ("client %d script %d command %d query %d: expected one row, got %d" ,
27532769 st -> id , st -> use_file , st -> command , qrynum , PQntuples (res ));
27542770 goto error ;
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 */
27582779 for (int fld = 0 ; fld < PQnfields (res ); fld ++ )
@@ -2763,9 +2784,9 @@ readCommandResponse(CState *st, char *varprefix)
27632784 if (* varprefix != '\0' )
27642785 varname = psprintf ("%s%s" , varprefix , varname );
27652786
2766- /* store result as a string */
2767- if (!putVariable (st , "gset" , varname ,
2768- PQgetvalue (res , 0 , fld )))
2787+ /* store last 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 */
27712792 pg_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)
31813202 return ; /* 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 ))
31853208 st -> state = CSTATE_END_COMMAND ;
31863209 else
31873210 st -> state = CSTATE_ABORTED ;
@@ -4660,7 +4683,7 @@ process_backslash_command(PsqlScanState sstate, const char *source)
46604683 syntax_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 {
46654688 if (my_command -> argc > 2 )
46664689 syntax_error (source , lineno , my_command -> first_line , my_command -> argv [0 ],
@@ -4804,10 +4827,10 @@ ParseScript(const char *script, const char *desc, int weight)
48044827 if (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 {
48124835 Command * cmd ;
48134836
@@ -4830,6 +4853,9 @@ ParseScript(const char *script, const char *desc, int weight)
48304853 else
48314854 cmd -> varprefix = pg_strdup (command -> argv [1 ]);
48324855
4856+ /* update the sql command meta */
4857+ cmd -> meta = command -> meta ;
4858+
48334859 /* cleanup unused command */
48344860 free_command (command );
48354861
0 commit comments