Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit c7f2349

Browse files
committed
Add \ir command to psql.
\ir is short for "include relative"; when used from a script, the supplied pathname will be interpreted relative to the input file, rather than to the current working directory. Gurjeet Singh, reviewed by Josh Kupershmidt, with substantial further cleanup by me.
1 parent 5ac6b76 commit c7f2349

File tree

9 files changed

+68
-12
lines changed

9 files changed

+68
-12
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,6 +1625,21 @@ Tue Oct 26 21:40:57 CEST 1999
16251625
</varlistentry>
16261626

16271627

1628+
<varlistentry>
1629+
<term><literal>\ir <replaceable class="parameter">filename</replaceable></literal></term>
1630+
<listitem>
1631+
<para>
1632+
The <literal>\ir</> command is similar to <literal>\i</>, but resolves
1633+
relative pathnames differently. When executing in interactive mode,
1634+
the two commands behave identically. However, when invoked from a
1635+
script, <literal>\ir</literal> interprets pathnames relative to the
1636+
directory in which the script is located, rather than the current
1637+
working directory.
1638+
</para>
1639+
</listitem>
1640+
</varlistentry>
1641+
1642+
16281643
<varlistentry>
16291644
<term><literal>\l</literal> (or <literal>\list</literal>)</term>
16301645
<term><literal>\l+</literal> (or <literal>\list+</literal>)</term>

src/bin/psql/command.c

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -784,8 +784,9 @@ exec_command(const char *cmd,
784784
}
785785

786786

787-
/* \i is include file */
788-
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
787+
/* \i and \ir include files */
788+
else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0
789+
|| strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
789790
{
790791
char *fname = psql_scan_slash_option(scan_state,
791792
OT_NORMAL, NULL, true);
@@ -797,8 +798,12 @@ exec_command(const char *cmd,
797798
}
798799
else
799800
{
801+
bool include_relative;
802+
803+
include_relative = (strcmp(cmd, "ir") == 0
804+
|| strcmp(cmd, "include_relative") == 0);
800805
expand_tilde(&fname);
801-
success = (process_file(fname, false) == EXIT_SUCCESS);
806+
success = (process_file(fname, false, include_relative) == EXIT_SUCCESS);
802807
free(fname);
803808
}
804809
}
@@ -1969,15 +1974,19 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
19691974
* process_file
19701975
*
19711976
* Read commands from filename and then them to the main processing loop
1972-
* Handler for \i, but can be used for other things as well. Returns
1977+
* Handler for \i and \ir, but can be used for other things as well. Returns
19731978
* MainLoop() error code.
1979+
*
1980+
* If use_relative_path is true and filename is not an absolute path, then open
1981+
* the file from where the currently processed file (if any) is located.
19741982
*/
19751983
int
1976-
process_file(char *filename, bool single_txn)
1984+
process_file(char *filename, bool single_txn, bool use_relative_path)
19771985
{
19781986
FILE *fd;
19791987
int result;
19801988
char *oldfilename;
1989+
char relpath[MAXPGPATH];
19811990
PGresult *res;
19821991

19831992
if (!filename)
@@ -1986,6 +1995,24 @@ process_file(char *filename, bool single_txn)
19861995
if (strcmp(filename, "-") != 0)
19871996
{
19881997
canonicalize_path(filename);
1998+
1999+
/*
2000+
* If we were asked to resolve the pathname relative to the location
2001+
* of the currently executing script, and there is one, and this is
2002+
* a relative pathname, then prepend all but the last pathname
2003+
* component of the current script to this pathname.
2004+
*/
2005+
if (use_relative_path && pset.inputfile && !is_absolute_path(filename)
2006+
&& !has_drive_prefix(filename))
2007+
{
2008+
snprintf(relpath, MAXPGPATH, "%s", pset.inputfile);
2009+
get_parent_directory(relpath);
2010+
join_path_components(relpath, relpath, filename);
2011+
canonicalize_path(relpath);
2012+
2013+
filename = relpath;
2014+
}
2015+
19892016
fd = fopen(filename, PG_BINARY_R);
19902017
}
19912018
else

src/bin/psql/command.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ typedef enum _backslashResult
2727
extern backslashResult HandleSlashCmds(PsqlScanState scan_state,
2828
PQExpBuffer query_buf);
2929

30-
extern int process_file(char *filename, bool single_txn);
30+
extern int process_file(char *filename, bool single_txn, bool use_relative_path);
3131

3232
extern bool do_pset(const char *param,
3333
const char *value,

src/bin/psql/help.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ slashUsage(unsigned short int pager)
158158
{
159159
FILE *output;
160160

161-
output = PageOutput(92, pager);
161+
output = PageOutput(93, pager);
162162

163163
/* if you add/remove a line here, change the row count above */
164164

@@ -184,6 +184,7 @@ slashUsage(unsigned short int pager)
184184
fprintf(output, _(" \\copy ... perform SQL COPY with data stream to the client host\n"));
185185
fprintf(output, _(" \\echo [STRING] write string to standard output\n"));
186186
fprintf(output, _(" \\i FILE execute commands from file\n"));
187+
fprintf(output, _(" \\ir FILE as \\i, but relative to location of current script\n"));
187188
fprintf(output, _(" \\o [FILE] send all query results to file or |pipe\n"));
188189
fprintf(output, _(" \\qecho [STRING] write string to query output stream (see \\o)\n"));
189190
fprintf(output, "\n");

src/bin/psql/settings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ typedef struct _psqlSettings
8181
bool cur_cmd_interactive;
8282
int sversion; /* backend server version */
8383
const char *progname; /* in case you renamed psql */
84-
char *inputfile; /* for error reporting */
84+
char *inputfile; /* file being currently processed, if any */
8585
char *dirname; /* current directory for \s display */
8686

8787
uint64 lineno; /* also for error reporting */

src/bin/psql/startup.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ main(int argc, char *argv[])
256256
if (!options.no_psqlrc)
257257
process_psqlrc(argv[0]);
258258

259-
successResult = process_file(options.action_string, options.single_txn);
259+
successResult = process_file(options.action_string, options.single_txn, false);
260260
}
261261

262262
/*
@@ -604,9 +604,9 @@ process_psqlrc_file(char *filename)
604604
sprintf(psqlrc, "%s-%s", filename, PG_VERSION);
605605

606606
if (access(psqlrc, R_OK) == 0)
607-
(void) process_file(psqlrc, false);
607+
(void) process_file(psqlrc, false, false);
608608
else if (access(filename, R_OK) == 0)
609-
(void) process_file(filename, false);
609+
(void) process_file(filename, false, false);
610610
free(psqlrc);
611611
}
612612

src/bin/psql/tab-complete.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ psql_completion(char *text, int start, int end)
735735
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
736736
"\\dn", "\\do", "\\dp", "\\drds", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du",
737737
"\\e", "\\echo", "\\ef", "\\encoding",
738-
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
738+
"\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
739739
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
740740
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
741741
"\\set", "\\sf", "\\t", "\\T",
@@ -2874,6 +2874,7 @@ psql_completion(char *text, int start, int end)
28742874
strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
28752875
strcmp(prev_wd, "\\g") == 0 ||
28762876
strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 ||
2877+
strcmp(prev_wd, "\\ir") == 0 || strcmp(prev_wd, "\\include_relative") == 0 ||
28772878
strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 ||
28782879
strcmp(prev_wd, "\\s") == 0 ||
28792880
strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0

src/include/port.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern bool pg_set_block(pgsocket sock);
3434

3535
/* Portable path handling for Unix/Win32 (in path.c) */
3636

37+
extern bool has_drive_prefix(const char *filename);
3738
extern char *first_dir_separator(const char *filename);
3839
extern char *last_dir_separator(const char *filename);
3940
extern char *first_path_var_separator(const char *pathlist);

src/port/path.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ skip_drive(const char *path)
7474
#define skip_drive(path) (path)
7575
#endif
7676

77+
/*
78+
* has_drive_prefix
79+
*
80+
* Return true if the given pathname has a drive prefix.
81+
*/
82+
bool
83+
has_drive_prefix(const char *path)
84+
{
85+
return skip_drive(path) != path;
86+
}
87+
7788
/*
7889
* first_dir_separator
7990
*

0 commit comments

Comments
 (0)