Let's try to make the following SQL statement work:
SELECT file.read('/tmp/test.txt');
We can start by creating the file /tmp/test.txt
with the following contents:
Hello PostgreSQL!
The next step is to create a simple plpgsql
function named file.read
!
CREATE FUNCTION file.read(file text)
RETURNS text AS $$
DECLARE
content text;
BEGIN
content := 'Static content for now!';
RETURN content;
END;
$$ LANGUAGE plpgsql VOLATILE;
This initial placeholder function just returns static content so that we can make sure things are working properly so far.
SELECT file.read('/tmp/test.txt');
read
------------------------
Static content for now
(1 row)
Now we just need to fill in the function with logic to read from the filesystem!
CREATE FUNCTION file.read(file text)
RETURNS text AS $$
DECLARE
content text;
tmp text;
BEGIN
file := quote_literal(file);
tmp := quote_ident(uuid_generate_v4()::text);
EXECUTE 'CREATE TEMP TABLE ' || tmp || ' (content text)';
EXECUTE 'COPY ' || tmp || ' FROM ' || file;
EXECUTE 'SELECT content FROM ' || tmp INTO content;
EXECUTE 'DROP TABLE ' || tmp;
RETURN content;
END;
$$ LANGUAGE plpgsql VOLATILE;
Now we should see the contents of the file that we created!
SELECT file.read('/tmp/test.txt');
read
------------------------
Hello PostgreSQL!
(1 row)
OK... so what's going on here? Let's break it down!
We begin by declaring a couple of variables using the text
data type.
content
- stores the contents of the file read from the filesystemtmp
- a unique string used as the name of a temporary table
Then we move into the BEGIN
block and set a couple of variables.
file
- the quoted file name that the function was called withtmp
- the quoted unique name for a temporary table
Once we have our variables all setup, we EXECUTE
some SQL to read the file contents.
- First we create a temporary table named
tmp
with a single field namedcontent
- Then we use PostgreSQL's COPY command to read the contents of
file
into thetmp
table - Once the data has been imported, we
SELECT
the contents from thetmp
table and insert itINTO
the localcontent
variable - Finally we
DROP
thetmp
table since we don't need it anymore
This was pretty interesting to get working! PostgreSQL has some other ways to read files from the filesystem.
- file_fdw - a read-only foreign data wrapper for filesystem access built on the
COPY
command - pg_read_file - this function is restricted to superusers and only allows files within the database cluster directory and the log_directory to be accessed
- pgsql-fio - an extension for basic file system functions
Another interesting challenge could be to write a file.write
function to save content to a file!