psql_ir.patch
text/x-patch
Filename: psql_ir.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/bin/psql/command.c | 31 | 3 |
| src/bin/psql/command.h | 1 | 1 |
| src/bin/psql/help.c | 1 | 0 |
| src/bin/psql/startup.c | 3 | 3 |
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index d7cdcf6..bc3949e 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -785,7 +785,8 @@ exec_command(const char *cmd,
/* \i is include file */
- else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0)
+ /* \ir is include file relative to currently processed file */
+ else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 || strcmp(cmd, "ir") == 0)
{
char *fname = psql_scan_slash_option(scan_state,
OT_NORMAL, NULL, true);
@@ -798,7 +799,7 @@ exec_command(const char *cmd,
else
{
expand_tilde(&fname);
- success = (process_file(fname, false) == EXIT_SUCCESS);
+ success = (process_file(fname, false, (cmd[1] == 'r')) == EXIT_SUCCESS);
free(fname);
}
}
@@ -1971,14 +1972,18 @@ do_edit(const char *filename_arg, PQExpBuffer query_buf,
* 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
* 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;
PGresult *res;
+ char *last_slash = NULL;
if (!filename)
return EXIT_FAILURE;
@@ -1986,6 +1991,29 @@ process_file(char *filename, bool single_txn)
if (strcmp(filename, "-") != 0)
{
canonicalize_path(filename);
+
+ if (use_relative_path && pset.inputfile)
+ {
+ /* find the / that splits the file from its path */
+ last_slash = strrchr(pset.inputfile, '/');
+
+ if (last_slash && !is_absolute_path(filename))
+ {
+ size_t dir_len = (last_slash - pset.inputfile) + 1;
+ size_t file_len = strlen(filename);
+
+ char *relative_file = pg_malloc(dir_len + 1 + file_len + 1);
+
+ relative_file[0] = '\0';
+ strncat(relative_file, pset.inputfile, dir_len);
+ strcat(relative_file, filename);
+
+ canonicalize_path(relative_file);
+
+ filename = relative_file;
+ }
+ }
+
fd = fopen(filename, PG_BINARY_R);
}
else
diff --git a/src/bin/psql/command.h b/src/bin/psql/command.h
index 852d645..9d0c31c 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 ac5edca..d459934 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -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 execute commands from FILE, placed relative to currently processing file\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/startup.c b/src/bin/psql/startup.c
index 7b8078c..3c17eec 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);
}