summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/genfile.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2022-07-29 15:38:49 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2022-07-29 15:38:49 -0400
commit283129e325b721a5a62227f20d7e3d149b379c73 (patch)
treea77377711f7fa536929419cead77d7dcc18f1485 /src/backend/utils/adt/genfile.c
parentfd96d14d950f2b1d19b5cb3b8e5a7d4d2b3fa161 (diff)
Support pg_read_[binary_]file (filename, missing_ok).
There wasn't an especially nice way to read all of a file while passing missing_ok = true. Add an additional overloaded variant to support that use-case. While here, refactor the C code to avoid a rats-nest of PG_NARGS checks, instead handling the argument collection in the outer wrapper functions. It's a bit longer this way, but far more straightforward. (Upon looking at the code coverage report for genfile.c, I was impelled to also add a test case for pg_stat_file() -- tgl) Kyotaro Horiguchi Discussion: https://postgr.es/m/20220607.160520.1984541900138970018.horikyota.ntt@gmail.com
Diffstat (limited to 'src/backend/utils/adt/genfile.c')
-rw-r--r--src/backend/utils/adt/genfile.c200
1 files changed, 135 insertions, 65 deletions
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index 2bf52192567..2f1e907a10d 100644
--- a/src/backend/utils/adt/genfile.c
+++ b/src/backend/utils/adt/genfile.c
@@ -278,81 +278,50 @@ pg_read_file(PG_FUNCTION_ARGS)
*
* No superuser check done here- instead privileges are handled by the
* GRANT system.
+ *
+ * If read_to_eof is true, bytes_to_read must be -1, otherwise negative values
+ * are not allowed for bytes_to_read.
*/
-Datum
-pg_read_file_v2(PG_FUNCTION_ARGS)
+static text *
+pg_read_file_common(text *filename_t, int64 seek_offset, int64 bytes_to_read,
+ bool read_to_eof, bool missing_ok)
{
- text *filename_t = PG_GETARG_TEXT_PP(0);
- int64 seek_offset = 0;
- int64 bytes_to_read = -1;
- bool missing_ok = false;
- char *filename;
- text *result;
-
- /* handle optional arguments */
- if (PG_NARGS() >= 3)
- {
- seek_offset = PG_GETARG_INT64(1);
- bytes_to_read = PG_GETARG_INT64(2);
-
- if (bytes_to_read < 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("requested length cannot be negative")));
- }
- if (PG_NARGS() >= 4)
- missing_ok = PG_GETARG_BOOL(3);
-
- filename = convert_and_check_filename(filename_t);
+ if (read_to_eof)
+ Assert(bytes_to_read == -1);
+ else if (bytes_to_read < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("requested length cannot be negative")));
- result = read_text_file(filename, seek_offset, bytes_to_read, missing_ok);
- if (result)
- PG_RETURN_TEXT_P(result);
- else
- PG_RETURN_NULL();
+ return read_text_file(convert_and_check_filename(filename_t),
+ seek_offset, bytes_to_read, missing_ok);
}
/*
* Read a section of a file, returning it as bytea
+ *
+ * Parameters are interpreted the same as pg_read_file_common().
*/
-Datum
-pg_read_binary_file(PG_FUNCTION_ARGS)
+static bytea *
+pg_read_binary_file_common(text *filename_t,
+ int64 seek_offset, int64 bytes_to_read,
+ bool read_to_eof, bool missing_ok)
{
- text *filename_t = PG_GETARG_TEXT_PP(0);
- int64 seek_offset = 0;
- int64 bytes_to_read = -1;
- bool missing_ok = false;
- char *filename;
- bytea *result;
-
- /* handle optional arguments */
- if (PG_NARGS() >= 3)
- {
- seek_offset = PG_GETARG_INT64(1);
- bytes_to_read = PG_GETARG_INT64(2);
-
- if (bytes_to_read < 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("requested length cannot be negative")));
- }
- if (PG_NARGS() >= 4)
- missing_ok = PG_GETARG_BOOL(3);
-
- filename = convert_and_check_filename(filename_t);
+ if (read_to_eof)
+ Assert(bytes_to_read == -1);
+ else if (bytes_to_read < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("requested length cannot be negative")));
- result = read_binary_file(filename, seek_offset,
- bytes_to_read, missing_ok);
- if (result)
- PG_RETURN_BYTEA_P(result);
- else
- PG_RETURN_NULL();
+ return read_binary_file(convert_and_check_filename(filename_t),
+ seek_offset, bytes_to_read, missing_ok);
}
/*
- * Wrapper functions for the 1 and 3 argument variants of pg_read_file_v2()
- * and pg_read_binary_file().
+ * Wrapper functions for the variants of SQL functions pg_read_file() and
+ * pg_read_binary_file().
*
* These are necessary to pass the sanity check in opr_sanity, which checks
* that all built-in functions that share the implementing C function take
@@ -361,25 +330,126 @@ pg_read_binary_file(PG_FUNCTION_ARGS)
Datum
pg_read_file_off_len(PG_FUNCTION_ARGS)
{
- return pg_read_file_v2(fcinfo);
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ int64 seek_offset = PG_GETARG_INT64(1);
+ int64 bytes_to_read = PG_GETARG_INT64(2);
+ text *ret;
+
+ ret = pg_read_file_common(filename_t, seek_offset, bytes_to_read,
+ false, false);
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_TEXT_P(ret);
+}
+
+Datum
+pg_read_file_off_len_missing(PG_FUNCTION_ARGS)
+{
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ int64 seek_offset = PG_GETARG_INT64(1);
+ int64 bytes_to_read = PG_GETARG_INT64(2);
+ bool missing_ok = PG_GETARG_BOOL(3);
+ text *ret;
+
+ ret = pg_read_file_common(filename_t, seek_offset, bytes_to_read,
+ false, missing_ok);
+
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_TEXT_P(ret);
}
Datum
pg_read_file_all(PG_FUNCTION_ARGS)
{
- return pg_read_file_v2(fcinfo);
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ text *ret;
+
+ ret = pg_read_file_common(filename_t, 0, -1, true, false);
+
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_TEXT_P(ret);
+}
+
+Datum
+pg_read_file_all_missing(PG_FUNCTION_ARGS)
+{
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ bool missing_ok = PG_GETARG_BOOL(1);
+ text *ret;
+
+ ret = pg_read_file_common(filename_t, 0, -1, true, missing_ok);
+
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_TEXT_P(ret);
}
Datum
pg_read_binary_file_off_len(PG_FUNCTION_ARGS)
{
- return pg_read_binary_file(fcinfo);
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ int64 seek_offset = PG_GETARG_INT64(1);
+ int64 bytes_to_read = PG_GETARG_INT64(2);
+ text *ret;
+
+ ret = pg_read_binary_file_common(filename_t, seek_offset, bytes_to_read,
+ false, false);
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_BYTEA_P(ret);
+}
+
+Datum
+pg_read_binary_file_off_len_missing(PG_FUNCTION_ARGS)
+{
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ int64 seek_offset = PG_GETARG_INT64(1);
+ int64 bytes_to_read = PG_GETARG_INT64(2);
+ bool missing_ok = PG_GETARG_BOOL(3);
+ text *ret;
+
+ ret = pg_read_binary_file_common(filename_t, seek_offset, bytes_to_read,
+ false, missing_ok);
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_BYTEA_P(ret);
}
Datum
pg_read_binary_file_all(PG_FUNCTION_ARGS)
{
- return pg_read_binary_file(fcinfo);
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ text *ret;
+
+ ret = pg_read_binary_file_common(filename_t, 0, -1, true, false);
+
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_BYTEA_P(ret);
+}
+
+Datum
+pg_read_binary_file_all_missing(PG_FUNCTION_ARGS)
+{
+ text *filename_t = PG_GETARG_TEXT_PP(0);
+ bool missing_ok = PG_GETARG_BOOL(1);
+ text *ret;
+
+ ret = pg_read_binary_file_common(filename_t, 0, -1, true, missing_ok);
+
+ if (!ret)
+ PG_RETURN_NULL();
+
+ PG_RETURN_BYTEA_P(ret);
}
/*