{"id":17196396,"url":"https://github.com/darold/datalink","last_synced_at":"2025-04-11T11:54:18.901Z","repository":{"id":145546070,"uuid":"207076862","full_name":"darold/datalink","owner":"darold","description":"PostgreSQL extension for SQL/MED external file access also named Datalink in others RDBMS ","archived":false,"fork":false,"pushed_at":"2019-09-09T06:44:44.000Z","size":1316,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-25T08:14:57.820Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PLpgSQL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"postgresql","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darold.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-08T07:24:30.000Z","updated_at":"2024-09-13T19:11:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"fc337f27-6751-493e-bcb5-cb0a9cdd68af","html_url":"https://github.com/darold/datalink","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fdatalink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fdatalink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fdatalink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darold%2Fdatalink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darold","download_url":"https://codeload.github.com/darold/datalink/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248391290,"owners_count":21095987,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T01:53:06.602Z","updated_at":"2025-04-11T11:54:18.881Z","avatar_url":"https://github.com/darold.png","language":"PLpgSQL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PostgreSQL SQL/MED DATALINK extension\n\nDATALINK is an SQL data type that allows to store a reference to a file that\nis external to the database system. The purpose of Datalink is to provide a\nmechanism to implement the referential integrity, recovery and access control\nof the external files and the SQL-data associated with them. Files can be\nmodified using file system commands or via SQL.\n\nThis extension aims to add this feature to PostgreSQL.\n\n## Disclaimer\n\nThis extension is a proof of concept for implementing DATALINK in PostgreSQL,\nit must not be used in production until an official release will be published.\nExpect changes in the implementation and behaviors before the official release.\n\nThe documentation is at its early stage, for more detailled information look\nat the presentation at [PgConf Asia 2019 conference](http://www.pgconf.asia)\n\n## Installation\n\nThe Datalink extension requires the `uuid-ossp` and the [uri](https://github.com/darold/uri) extensions.\n \nIn order to install the Datalink extension download latest development sources\nfrom [GitHub](https://github.com/darold/datalink) and use the following command\nto build and install the extension. `pg_config` must be in found from your PATH\nenvironment variable.\n\n        make\n        sudo make install\n\nTo test the extension run, it is required that the user running the script be\nPostgreSQL superuser and able to execute commands using sudo:\n\n        cd test/\n\tsh dl_test.sh\n\nTo use the extension in your database execute:\n\n        CREATE EXTENSION uri;\n\nThe default values for GUC related to the DATALINK extension are forced to:\n\n\tdatalink.dl_naptime = 10\n\tdatalink.dl_base_directory = '/tmp/test_datalink'\n\tdatalink.dl_token_path = '/tmp/test_datalink/pg_dltoken'\n\tdatalink.dl_token_expiry = 60\n\tdatalink.dl_keep_max_copies = 5\n\nThis is the one I use for the proof of concept, feel free to adjust them in\ndatalink.h before compiling. This is not possible to change them from the\nconfiguration file for the moment but it will be possible as soon as the\nextension move to beta stage.\n\n## Description\n\nSQL/MED allows a variety of attributes to be specified for DATALINK columns.\nThey are used to defined how the database system controls the file. This can\nbe from no control at all (the file does not even have to exist) to full\ncontrol, where removal of the datalink value from the database leads to a\ndeletion of the physical file.\n\nExample of use:\n\n```\n    CREATE TABLE persons\n    (\n        id integer,\n        fullname text,\n        picture DATALINK\n    );\n\n    INSERT INTO persons VALUES (1, 'Jon Doe',\n            DLVALUE('img1.jpg', 'MyBaseDir', 'A comment'));\n```\n\nA DATALINK is formally composed by:\n\n* a base directory representing mount points where external files can be\n  read or written\n* an URI corresponding to the path of the file relative to its base directory\n* a comment\n\nThe base directories must exists on file system and be registered into table\n`pg_datalink_bases`, only PostgreSQL superuser can do that.\n\n```\n    INSERT INTO pg_datalink_bases (dirname, base)\n\t\tVALUES (‘MyBaseDir’, ‘file:///var/www/mysite1/’);\n```\n\nNo verification if the path exists is done.\n\nThe `postgres` user must have read/write permission on the directory if files\nwill be managed by SQL.\n\nSee `test/` directory for more example of use.\n\nA background worker is started with PostgreSQL and the process is named\n\"Datalink background worker\". This background worker scan periodically a\ndirectory where access control token are stored. Default is each 10 seconds\n(controlled by GUC _datalink.dl_naptime_) for testing.\n\nThis background worker is responsible of removing token that have expired\nfrom directory `$PGDATA/pg_token/` (GUC _datalink.dl_base_directory_). The\ndefault expiry time is 60 seconds, the value can be changed using GUC\n_datalink.dl_token_expiry_. For read token it also remove all link to\nexternal files when the token expires. For write access token the backround\nworker remove all obsolete copies that correspond to a rollbacked transaction.\n\nSee file SQL-MED-DATALINK-PgConfAsia2019.pdf for detailed information about\nthe DATALINK implementation.\n\n### Permission modes\n\nDATALINKs supports two permission modes to read and write datalinks, namely\n\n  * READ/WRITE PERMISSION FS (Controlled by the File System)\n  * READ/WRITE PERMISSION DB (Controlled by the Database system)\n\nThere is a third mode WRITE PERMISSION BLOCKED that provides data recovery\nfunctionality for an SQL-mediated file (WRITE PERMISSION DB), as long as the\nRECOVERY option is specified as YES.\n\nThis third option mean that a user cannot update the file while the file is\nreferenced in a DATALINK column. Updating the content of a file that in this\nmode requires three distinct steps:\n\n\t1. Unlinking the file\n\t2. Modifying the file\n\t3. Re-linking the file\n\nThe extension use a Copy-On-Write mechanism so this mode is always used in\nterm that it never modify a file in place.\n\n### PERMISSION FS\n\nWhen READ or WRITE PERMISSION FS is specified, the system that control the\nDATALINK functionality allows user to update a file while the file remains\nlinked to the database. This mode does not provide consistency and file data\nrecovery. Which means that in case of crashes or a user needs to restore the\ndatabase, there is no backup data to recover. In cases of transaction failure,\nthis may cause inconsistency between the file data and the database data.\n\nIn this mode, read/write access privileges are determined by the file system\npermissions assigned to the file. PostgreSQL only allow access to external\nfile through the user running the database system, mostly the postgres user.\n\nFor all these reasons it is not recommended to used this mode. Although the\nDATALINK extension provide this mode, this is only through the postgres user.\n\nREAD/WRITE PERMISSION FS does not support a token-based access model like the\none provided with READ/WRITE PERMISSION DB/ADMIN.\n\nWhen READ or WRITE PERMISSION DB is specified, the system that control the\nDATALINK functionality allows user to update a file while the file remains\n\n### PERMISSION DB/ADMIN\n\nWhen READ PERMISSION DB is specified, this is the database server that control\nwhich users are authorized to access the file. Writing is controlled by the\nDatabase system if WRITE PERMISSION ADMIN option is set. \n\nThese options can be followed by either the keywords REQUIRING TOKEN FOR UPDATE\nor the keywords NOT REQUIRING TOKEN FOR UPDATE.\n\n* \"REQUIRING TOKEN FOR UPDATE\" indicates that the token, which was included\nin the file reference returned to the user when he requested an access to the\nfile, is needed to update the DATALINK value in question.\n* \"NOT REQUIRING TOKEN FOR UPDATE\" indicates that this token is not\nneeded to update the DATALINK value.\n\n\"NOT TOKEN FOR UPDATE\" does not allow concurrency level at Database side, it\nmust be handled by the application. Although it is implemented in the extension\nit is recommended to always used \"REQUIRING TOKEN FOR UPDATE\" by this way file\ndata recovery can be supported in an implementation-dependent way, as long as\nthe RECOVERY option is set to YES.\n\n## DATALINK functions\n\n### DLVALUE ( data-location , directory-base , comment )\n\nThe DLVALUE function returns a DATALINK value. When the function is in a\nVALUES clause in an INSERT statement, it creates a link to an external file.\n\nIf only a comment is specified, the data-location is a zero-length string and\nthe DATALINK value is created with no file link.\n\n**data-location**\n\nUri data type containing an URL value or a path.\n\n**directory-base**\n\nAn optional text expression that specifies the link base directory of the\nDATALINK value. The valid value are 'URL', 'FILE' and any other value\nrepresenting a directory that is registered in pg_catalog.pg_datalink_bases\ntable.\n\n**comment-string**\n\nAn optional text value that provides a comment or additional information.\n\nThe result of the function is a DATALINK value. If the data-location is\nnull, the result is the null value.\n\n**Examples**\n\nInsert a DATALINK URL using the default base directory:\n\n\tINSERT INTO dl_example VALUES( 1, DLVALUE('http://www.darold.net/', NULL, 'Web site');\n\nInsert a local path DATALINK:\n\n\tINSERT INTO dl_example VALUES( 1, DLVALUE('/var/lib/pgsql/files/info.dat', 'FILE', 'Local path');\n\nInsert a NULL DATALINK:\n\n\tINSERT INTO dl_example VALUES( 1, DLVALUE(NULL, 'FILE', 'Return null');\n\nInsert an empty URL:\n\n\tINSERT INTO dl_example VALUES( 1, DLVALUE('', 'URL', 'Empty uri value') );\n\nInsert just a comment with empty uri:\n\n\tINSERT INTO dl_example VALUES( 1, DLVALUE('Empty uri value') );\n\n\n### DLVALUE ( datalink, data-location , directory-base-string , comment-string )\n\nThe DLVALUE function returns a DATALINK value. In this form the function is to\nbe used on the right side of a SET clause in an UPDATE statement, it replace\nthe link to an external file.\n\nSame description as DLVALUE for INSERT statement except first parameter that\nis the DATALINK column that has to be updated. In future implementation this\nparameter will be removed in respect to the standard SQL as the value must be\ntaken from the left operand of the UPDATE statement. This mean that in a short\nterm there will be just one version of the DLVALUE() function, the same as the\none use with INSERT statement.\n\nThe result of the function is a DATALINK value. If the data-location is\nnull, the result is the null value.\n\n**Examples**\n\nUpdate a DATALINK URL:\n\n\tUPDATE dl_example SET efile = DLVALUE('http://www.darold.net/', MyWebSite', 'Web site') WHERE id = 1;\n\n\n### DLCOMMENT ( datalink )\n\nThe DLCOMMENT function returns the comment value of a DATALINK record.\nThe argument must be an expression that results in a DATALINK type value.\n\nThe result of the function is of type text and can be null if the value is null.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://pgcluu.darold.net/index.html','URL','Main page of pgCluu site')\n\nthen call to the function on that DATALINK will return:\n\n\tSELECT DLCOMMENT(EFILE)\n\nwill return the value:\n\n\tMain page of pgCluu site\n\n\n### DLLINKTYPE ( datalink )\n\nThe DLLINKTYPE function returns the link type value from a DATALINK. The\nargument must be a DATALINK data type.\n\nThe result of the function is of type text and can be null if the value is null.\n\nThe link type value is either FILE, URL or the base directory of the DATALINK\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://pgcluu.darold.net/index.html','URL','Main page of pgCluu site')\nor\n\tDLVALUE('http://pgcluu.darold.net/index.html', NULL,'Main page of pgCluu site')\n\nthen call to the function on that DATALINK will return:\n\n\tSELECT DLLINKTYPE(EFILE)\n\nwill return the value:\n\n\tURL\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('/var/log/postgresql/postgresql-11.log','FILE','PostgreSQL log file')\nor\n\tDLVALUE('/var/log/postgresql/postgresql-11.log',NULL,'PostgreSQL log file')\n\nthen call to the function on that DATALINK will return:\n\n\tSELECT DLLINKTYPE(EFILE)\n\nwill return the value:\n\n\tFILE\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('/tmp/test_datalink/jatfttd.txt','test_directory','Just a temporary file to test directory')\n\nthen call to the function on that DATALINK will return:\n\n\tSELECT DLLINKTYPE(EFILE)\n\nwill return the value:\n\n\ttest_directory\n\n\n### DLURLSCHEME ( datalink )\n\nThe DLURLSCHEME function returns the scheme from a DATALINK value.\nThe value will always be in lower case. The argument must be a value\nwith data type DATALINK.\n\nThe result of the function is text. If the argument is null, the result is\nthe null value. If the DATALINK value only includes the comment the result\nreturned is a zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://pgbadger.darold.net/images/logo.png','URL','a comment')\n\nthen the following function operating on that value:\n\n\tDLURLSCHEME(EFILE)\n\nwill return the value:\n\n\thttp\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('/var/log/postgresql/postgresql-11.log','FILE','PostgreSQL log file')\nor\n\tDLVALUE('/var/log/postgresql/postgresql-11.log',NULL,'PostgreSQL log file')\n\nthe return value is:\n\n\tfile\n\n### DLURLSERVER ( datalink )\n\nThe DLURLSERVER function returns the file server from a DATALINK value when\nthe uri scheme is http. The value returned is always in lower case.\n\nThe argument must be an expression that results in a value with data type\nDATALINK.\n\nThe result of the function is text. If the argument is null, the result is\nthe null value.  If the DATALINK value only includes the comment the result\nreturned is a zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://pgbadger.darold.net/index.html','URL','a comment')\n\nthen the following function operating on that value:\n\n\tDLURLSERVER(EFILE)\n\nwill return the value:\n\n\tpgbadger.darold.net\n\n\n### DLURLCOMPLETE ( datalink )\n\nThe DLURLCOMPLETE function returns the data location attribute from a\nDATALINK value in a form of an URL. When _datalink_ is a\nDATALINK column defined with the attribute READ PERMISSION DB, the\nvalue includes a file access token.\n\nThe argument must be a value with data type DATALINK.\n\nThe result of the function of type text. If the argument is null, the result\nis the null value. If the DATALINK value only includes the comment the result\nreturned is a zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://www.darold.net/logo.png','URL','a comment')\n\nthe following function operating on that value:\n\n\tDLURLCOMPLETE(EFILE)\n\nreturns:\n\n\thttp://www.darold.net/00f59e3-60a5-4bfa-a45b-214ccb08e425;logo.png\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the access token.\n\n\n### DLURLCOMPLETEONLY ( datalink )\n\nThe DLURLCOMPLETEONLY function returns the data location attribute\nfrom a DATALINK value in form of an URL. The value returned never\nincludes a file access token.\n\nThe argument must be a DATALINK data type value.\n\nThe result of the function is text. If the argument is null, the result is\nthe null value.\n\nIf the DATALINK value only includes a comment, the result is a zero length\nstring.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into a DATALINK column EFILE\n(defined with READ PERMISSION DB) using function:\n\n\tDLVALUE('http://pgbadger.darold.net/logo.png','URL','a comment')\n\nthe following function operating on that value:\n\n\tDLURLCOMPLETEONLY(EFILE)\n\nreturns:\n\n\thttp://pgbadger.darold.net/logo.png\n\n\n### DLURLPATH ( datalink )\n\nThe DLURLPATH function returns the full path to the external file linked\nfrom a DATALINK value. When _datalink_ is a DATALINK column defined with\nthe attribute READ PERMISSION DB, the value includes a file access token.\n\nThe argument must be an expression that results in a value with data type\nDATALINK.\n\nThe result of the function is text. If the argument is null, the result is\nthe null value. If the DATALINK value only includes the comment the result\nreturned is a zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using the function:\n\n\tDLVALUE('http://pgbadgr.darold.net/images/logo.png','URL','a comment')\n\nthen the following function operating on that value:\n\n\tDLURLPATH(EFILE)\n\nreturns the value:\n\n\t/images/00f59e3-60a5-4bfa-a45b-214ccb08e425;logo.png\n\n(where 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the access token)\n\n\n### DLURLPATHONLY ( datalink )\n\nThe DLURLPATHONLY function returns the full path to an external file linked\nfrom a DATALINK value. The value returned never includes a file access token.\n\nThe argument must be an expression that results in a value with data type\nDATALINK. The result of the function is text. If the argument is null, the\nresult is the null value. If the DATALINK value only includes the comment the\nresult returned is a zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE using function:\n\n\tDLVALUE('http://pgbadger.darold.net/images/logo.png','URL','a comment')\n\nthen the following function operating on that value:\n\n\tDLURLPATHONLY(EFILE)\n\nreturns the value:\n\n\t/images/logo.png\n\n\n### DLURLCOMPLETEWRITE ( datalink )\n\nThe DLURLCOMPLETEWRITE function returns the complete URL value from a DATALINK\nvalue in the form of an URL. If the DATALINK value comes from a DATALINK\ncolumn defined with WRITE PERMISSION ADMIN, a write token is included in the\nreturn value.\n\nThe returned value can be used to locate and update the linked file. If the\nDATALINK column is defined with another WRITE PERMISSION option (not ADMIN)\nor NO LINK CONTROL, DLURLCOMPLETEWRITE returns just the URL value without a\nwrite token. If the file reference is derived from a DATALINK column defined\nwith WRITE PERMISSION FS, a token is not required to write to the file, because\nwrite permission is controlled by the file system.\n\nThe argument must be a value with data type DATALINK.\n\nThe result of the function is text. If the argument is null, the result is\nthe null value. If the DATALINK value only includes a comment, the result is\na zero length string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into a DATALINK column EFILE (defined\nwith WRITE PERMISSION ADMIN) using function:\n\n\tDLVALUE('http://pgbadger.darold.net/logo.png','URL','a comment')\n\nthe following function operating on that value:\n\n\tDLURLCOMPLETEWRITE(EFILE)\n\nreturns:\n\n\thttp://pgbadger.darold.net/00f59e3-60a5-4bfa-a45b-214ccb08e425;logo.png\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the write token. If EFILE\nis not defined with WRITE PERMISSION ADMIN, the write token will not be present.\n\n\n### DLURLPATHWRITE ( datalink )\n\nThe DLURLPATHWRITE function returns the full path necessary to access an\nexternal file given from a DATALINK value in a form of an absolute file path.\nThe value returned includes a write token if the DATALINK value specified as\nparameter comes from a DATALINK column defined with WRITE PERMISSION ADMIN.\n\nIf the DATALINK column is defined with other WRITE PERMISSION options (not\nADMIN) or NO LINK CONTROL, DLURLPATHWRITE returns the full path to the external\nfile without a write token. If the file reference is derived from a DATALINK\ncolumn defined with WRITE PERMISSION FS, a token is not required to write to\nthe file, because write permission is controlled by the file system.\n\nThe argument must be an expression that results in a value with data type\nDATALINK.\n\nThe result of the function is text. If the argument is null, the result is the\nnull value. If the DATALINK value only includes a comment, the result is a zero\nlength string.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into a DATALINK column EFILE (defined\nwith WRITE PERMISSION ADMIN) using function:\n\n\tDLVALUE('http://pgbadger.darold.net/images/logo.png','URL','a comment')\n\nthe following function operating on that value:\n\n\tDLURLPATHWRITE(EFILE)\n\nreturns:\n\n\t/images/00f59e3-60a5-4bfa-a45b-214ccb08e425;logo.png\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the write token. If EFILE\nis not defined with WRITE PERMISSION ADMIN, the write token will not be present.\n\n\n### DLNEWCOPY ( datalink, data-location, has-token )\n\nThe DLNEWCOPY function returns a DATALINK value indicating that the referenced\nfile has changed with the new URI in the DATALINK value.\n\nThe value is assigned to a DATALINK column as a result of an UPDATE statement.\nIf the DATALINK column/directory is defined with option RECOVERY YES, the new\nversion of the linked file is archived asynchronously.\n\nIf DLNEWCOPY is not called in  an UPDATE statement an error is returned.\n\n**datalink**\n\nThe DATALINK to be modified. In future implementation this parameter will\nbe removed in respect to the standard SQL as the value must be taken from\nthe left operand of the UPDATE statement.\n\n**data-location**\n\nA text expression that specifies a complete URL value. The value may have been\nobtained earlier by a SELECT statement through the DLURLCOMPLETEWRITE function.\n\n**has-token**\n\nA boolean value that indicates whether the URL contains a write token.  An error\noccurs if the token embedded in the data location is not valid.\n\nThe result of the function is a DATALINK value.\n\nParameters data-location and has-token can not be null.\n\nFor a DATALINK column defined with WRITE PERMISSION ADMIN REQUIRING TOKEN FOR\nUPDATE, the write token must be in the data location to complete the SQL UPDATE\nstatement.\n\nOn the other hand, for WRITE PERMISSION ADMIN NOT REQUIRING TOKEN FOR UPDATE,\nthe write token is not required, but is allowed in the data location.\n\nFor a DATALINK column defined with WRITE PERMISSION ADMIN and REQUIRING TOKEN\nFOR UPDATE, the write token must be the same as the one used to open the\nspecified file, if it was opened.\n\nFor any WRITE PERMISSION ADMIN column, even if the write token has expired,\nthe token is still considered valid as long as the transaction is still open.\n\nIn a case where no file update has taken place, or the DATALINK file is\nlinked with other options, such as WRITE PERMISSION BLOCKED/FS or NO\nLINK CONTROL, this function will behave like DLVALUE.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE (defined with\nWRITE PERMISSION ADMIN REQUIRING TOKEN FOR UPDATE) using function:\n\n\tDLVALUE('file:///home/postgres/datafiles/file1.txt','FILE','A local file')\n\nUse the scalar function DLURLCOMPLETEWRITE to fetch the value:\n\n\tSELECT DLURLCOMPLETEWRITE(EFILE) FROM DL_EXAMPLE WHERE ...\n\nIt returns:\n\n\t/home/postgres/datafiles/00f59e3-60a5-4bfa-a45b-214ccb08e425;file1.txt\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the write token.\n\nUse the above value to locate and update the content of the file. Issue the\nfollowing SQL UPDATE statement to indicate that the file has been successfully\nchanged:\n\n\tUPDATE t1 SET EFILE = DLNEWCOPY(EFILE, 'file:///home/postgres/datafiles/00f59e3-60a5-4bfa-a45b-214ccb08e425;file1.txt', 1)\n\tWHERE ...\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the same write token used\nto modify the file referenced by the URL value. Note that if EFILE is defined\nwith WRITE PERMISSION ADMIN NOT REQUIRING TOKEN FOR UPDATE, the write token is\nnot required in the above example.\n\n### DLPREVIOUSCOPY ( datalink, data-location , has-token )\n\nThe DLPREVIOUSCOPY function returns a DATALINK value indicating that the\nprevious version of the file should be restored.\n\nThe value is assigned to a DATALINK column as a result of an UPDATE statement.\nThis function restore the linked file from the previously committed version.\n\nIf DLPREVIOUSCOPY is not called in a result of an UPDATE statement an error is\nreturned.\n\n**datalink**\n\nThe DATALINK to be modified. In future implementation this parameter will\nbe removed in respect to the standard SQL as the value must be taken from\nthe left operand of the UPDATE statement.\n\n**data-location**\n\nA text expression that specifies the complete URL value. The value may have\nbeen obtained earlier by a SELECT statement through the DLURLCOMPLETEWRITE\nfunction.\n\n**has-token**\n\nAn boolean value that indicates whether the URL contains a write token.\nAn error occurs if the token embedded in the data location is not valid.\n\nThe result of the function is a DATALINK value.\n\nParameters data-location and has-token can not be null.\n\nFor a DATALINK column defined with WRITE PERMISSION ADMIN REQUIRING TOKEN\nFOR UPDATE, the write token must be in the data location to complete the\nSQL UPDATE statement. On the other hand, for WRITE PERMISSION ADMIN NOT\nREQUIRING TOKEN FOR UPDATE, the write token is not required, but is allowed\nin the data location.\n\nFor a DATALINK column defined with WRITE PERMISSION ADMIN REQUIRING TOKEN\nFOR UPDATE, the write token must be the same as the one used to open the\nspecified file, if it was opened.\n\nFor any WRITE PERMISSION ADMIN column, even if the write token has expired,\nthe token is still considered valid as long as the transaction is open.\n\n**Examples**\n\nGiven a DATALINK value that was inserted into column EFILE (defined with\nWRITE PERMISSION ADMIN REQUIRING TOKEN FOR UPDATE and RECOVERY YES) using\nfunction:\n\n\tDLVALUE('http://pgcluu.darold.net/index.html','URL','Main page of pgCluu site')\n\nUse the scalar function DLURLCOMPLETEWRITE to fetch the value:\n\n\tSELECT DLURLCOMPLETEWRITE(EFILE) FROM DL_EXAMPLE WHERE ...\n\nIt returns:\n\n\thttp://pgcluu.darold.net/00f59e3-60a5-4bfa-a45b-214ccb08e425;index.html\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the write token.\n\nUse the above value to locate and update the content of the file. Issue the\nfollowing SQL UPDATE statement to back out the file changes and restore\nto the previous committed version:\n\n\tUPDATE DL_EXAMPLE SET EFILE = DLPREVIOUSCOPY('http://pgcluu.darold.net/00f59e3-60a5-4bfa-a45b-214ccb08e425;index.html', 1) WHERE ...\n\nwhere 00f59e3-60a5-4bfa-a45b-214ccb08e425 represents the same write token used\nto modify the file referenced by the URL value. Note that if EFILE is defined\nwith WRITE PERMISSION ADMIN NOT REQUIRING TOKEN FOR UPDATE, the write token is\nnot required in the above example.\n\n### DLREPLACECONTENT ( datalink, data-location-target , data-location-source , comment )\n\nThe DLREPLACECONTENT function returns a DATALINK value. When the\nfunction is on the right hand side of a SET clause in an UPDATE statement, or\nis in a VALUES clause in an INSERT statement, the assignment of the\nreturned value results in replacing the content of a file by another file and\nthen creating a link to it.\n\nThe actual file replacement process is done during commit processing of the\ncurrent transaction.\n\n**datalink-expression**\n\nThe DATALINK to be modified. In future implementation this parameter will\nbe removed in respect to the standard SQL as the value must be taken from\nthe left operand of the UPDATE statement.\n\n**data-location-target**\n\nA text expression that specifies a complete URL value.\n\nAs long as a DATALINK parameter is specified it must be the same URI than\nin the DATALINK.\n\n**data-location-source**\n\nA text expression that specifies the data location of a file in URL format.\nAs a result of an assignment in an UPDATE or an INSERT statement, this file\nis renamed to the name of the file that is pointed to by data-location-target;\nthe ownership and permission attributes of the target file are retained.\n\nThere is a restriction that data-location-source can only be one of the\nfollowing:\n\n  - A zero-length value\n  - A NULL value\n  - The value of data-location-target plus a suffix string. The suffix\n    string can be up to 20 characters in length. The characters of the\n    suffix string must belong to the URL character set. Moreover, the\n    string cannot contain a “\\” character under the UNC scheme, or the\n    “/” character under other valid schemes.\n\n**comment-string**\n\nAn optional text value that contains a comment or additional location\ninformation.\n\nThe result of the function is a DATALINK value. If data-location-target is\nnull, the result is the null value. If data-location-source is null, a\nzero-length string, or exactly the same as data-location-target, the effect\nof DLREPLACECONTENT is the same as DLVALUE.\n\n**Examples**\n\nReplace the content of a linked file by another file. Given a DATALINK value\nthat was inserted into column EFILE using the following INSERT statement:\n\n\tINSERT INTO DL_EXAMPLE (ID, EFILE) VALUES (1, DLVALUE('http://www.darold.net/logo.png'));\n\nReplace the content of this file with another file by issuing the following\nSQL UPDATE statement:\n\n\tUPDATE DL_EXAMPLE SET EFILE = DLREPLACECONTENT('http://www.darold.net/logo.png', 'http://www.darold.net/logo.png.new') WHERE ID = 1;\n\n## Authors\n\nGilles Darold \u003c gilles@darold.net \u003e\n\n## License\n\nThis extension is free software distributed under the PostgreSQL Licence.\n\n        Copyright (c) 2015-2018, Gilles Darold\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarold%2Fdatalink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarold%2Fdatalink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarold%2Fdatalink/lists"}