aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/command.c37
-rw-r--r--src/bin/psql/command.h2
-rw-r--r--src/bin/psql/help.c3
-rw-r--r--src/bin/psql/settings.h2
-rw-r--r--src/bin/psql/startup.c6
-rw-r--r--src/bin/psql/tab-complete.c3
-rw-r--r--src/include/port.h1
-rw-r--r--src/port/path.c11
8 files changed, 53 insertions, 12 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 378330b96ae..16ff9e91e55 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -784,8 +784,9 @@ exec_command(const char *cmd,
}
- /* \i is include file */
- else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
+ /* \i and \ir include files */
+ else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0
+ || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
{
char *fname = psql_scan_slash_option(scan_state,
OT_NORMAL, NULL, true);
@@ -797,8 +798,12 @@ exec_command(const char *cmd,
}
else
{
+ bool include_relative;
+
+ include_relative = (strcmp(cmd, "ir") == 0
+ || strcmp(cmd, "include_relative") == 0);
expand_tilde(&fname);
- success = (process_file(fname, false) == EXIT_SUCCESS);
+ success = (process_file(fname, false, include_relative) == EXIT_SUCCESS);
free(fname);
}
}
@@ -1969,15 +1974,19 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
* process_file
*
* Read commands from filename and then them to the main processing loop
- * Handler for \i, but can be used for other things as well. Returns
+ * Handler for \i and \ir, but can be used for other things as well. Returns
* MainLoop() error code.
+ *
+ * If use_relative_path is true and filename is not an absolute path, then open
+ * the file from where the currently processed file (if any) is located.
*/
int
-process_file(char *filename, bool single_txn)
+process_file(char *filename, bool single_txn, bool use_relative_path)
{
FILE *fd;
int result;
char *oldfilename;
+ char relpath[MAXPGPATH];
PGresult *res;
if (!filename)
@@ -1986,6 +1995,24 @@ process_file(char *filename, bool single_txn)
if (strcmp(filename, "-") != 0)
{
canonicalize_path(filename);
+
+ /*
+ * If we were asked to resolve the pathname relative to the location
+ * of the currently executing script, and there is one, and this is
+ * a relative pathname, then prepend all but the last pathname
+ * component of the current script to this pathname.
+ */
+ if (use_relative_path && pset.inputfile && !is_absolute_path(filename)
+ && !has_drive_prefix(filename))
+ {
+ snprintf(relpath, MAXPGPATH, "%s", pset.inputfile);
+ get_parent_directory(relpath);
+ join_path_components(relpath, relpath, filename);
+ canonicalize_path(relpath);
+
+ filename = relpath;
+ }
+
fd = fopen(filename, PG_BINARY_R);
}
else
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index 852d645cfd0..9d0c31c1030 100644
--- a/src/bin/psql/command.h
+++ b/src/bin/psql/command.h
@@ -27,7 +27,7 @@ typedef enum _backslashResult
extern backslashResult HandleSlashCmds(PsqlScanState scan_state,
PQExpBuffer query_buf);
-extern int process_file(char *filename, bool single_txn);
+extern int process_file(char *filename, bool single_txn, bool use_relative_path);
extern bool do_pset(const char *param,
const char *value,
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index ac5edca65dd..e56ab61ac63 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -158,7 +158,7 @@ slashUsage(unsigned short int pager)
{
FILE *output;
- output = PageOutput(92, pager);
+ output = PageOutput(93, pager);
/* if you add/remove a line here, change the row count above */
@@ -184,6 +184,7 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\copy ... perform SQL COPY with data stream to the client host\n"));
fprintf(output, _(" \\echo [STRING] write string to standard output\n"));
fprintf(output, _(" \\i FILE execute commands from file\n"));
+ fprintf(output, _(" \\ir FILE as \\i, but relative to location of current script\n"));
fprintf(output, _(" \\o [FILE] send all query results to file or |pipe\n"));
fprintf(output, _(" \\qecho [STRING] write string to query output stream (see \\o)\n"));
fprintf(output, "\n");
diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h
index 7228f9d0eea..3aebf532991 100644
--- a/src/bin/psql/settings.h
+++ b/src/bin/psql/settings.h
@@ -81,7 +81,7 @@ typedef struct _psqlSettings
bool cur_cmd_interactive;
int sversion; /* backend server version */
const char *progname; /* in case you renamed psql */
- char *inputfile; /* for error reporting */
+ char *inputfile; /* file being currently processed, if any */
char *dirname; /* current directory for \s display */
uint64 lineno; /* also for error reporting */
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 7b8078c21e4..3c17eece7b8 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -256,7 +256,7 @@ main(int argc, char *argv[])
if (!options.no_psqlrc)
process_psqlrc(argv[0]);
- successResult = process_file(options.action_string, options.single_txn);
+ successResult = process_file(options.action_string, options.single_txn, false);
}
/*
@@ -604,9 +604,9 @@ process_psqlrc_file(char *filename)
sprintf(psqlrc, "%s-%s", filename, PG_VERSION);
if (access(psqlrc, R_OK) == 0)
- (void) process_file(psqlrc, false);
+ (void) process_file(psqlrc, false, false);
else if (access(filename, R_OK) == 0)
- (void) process_file(filename, false);
+ (void) process_file(filename, false, false);
free(psqlrc);
}
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index 32f418306cd..4f7df367e5a 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -735,7 +735,7 @@ psql_completion(char *text, int start, int end)
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL",
"\\dn", "\\do", "\\dp", "\\drds", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du",
"\\e", "\\echo", "\\ef", "\\encoding",
- "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\l",
+ "\\f", "\\g", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l",
"\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink",
"\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r",
"\\set", "\\sf", "\\t", "\\T",
@@ -2874,6 +2874,7 @@ psql_completion(char *text, int start, int end)
strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 ||
strcmp(prev_wd, "\\g") == 0 ||
strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 ||
+ strcmp(prev_wd, "\\ir") == 0 || strcmp(prev_wd, "\\include_relative") == 0 ||
strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 ||
strcmp(prev_wd, "\\s") == 0 ||
strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0
diff --git a/src/include/port.h b/src/include/port.h
index 4c7ed643177..2cab65fbde7 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -34,6 +34,7 @@ extern bool pg_set_block(pgsocket sock);
/* Portable path handling for Unix/Win32 (in path.c) */
+extern bool has_drive_prefix(const char *filename);
extern char *first_dir_separator(const char *filename);
extern char *last_dir_separator(const char *filename);
extern char *first_path_var_separator(const char *pathlist);
diff --git a/src/port/path.c b/src/port/path.c
index 6991bc7247b..13ca4f3f1c1 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -75,6 +75,17 @@ skip_drive(const char *path)
#endif
/*
+ * has_drive_prefix
+ *
+ * Return true if the given pathname has a drive prefix.
+ */
+bool
+has_drive_prefix(const char *path)
+{
+ return skip_drive(path) != path;
+}
+
+/*
* first_dir_separator
*
* Find the location of the first directory separator, return