Hi
> > > There's a whitespace-only hunk that shouldn't be included. > > > > > > I don't agree with the single-column/single-row restriction on these. > I > > > can certainly see a case where someone might want to, say, dump out a > > > bunch of binary integers into a file for later processing. > > > > > > The tab-completion for 'gstore' wasn't correct (you didn't include the > > > double-backslash). The patch also has conflicts against current master > > > now. > > > > > > I guess my thinking about moving this forward would be to simplify it > to > > > just '\gb' which will pull the data from the server side in binary > > > format and dump it out to the filename or command given. If there's a > > > new patch with those changes, I'll try to find time to look at it. > > > > ok I'll prepare patch > > Great, thanks! > I rewrote these patches - it allows binary export/import from psql and the code is very simple. The size of the patch is bigger due including 4KB binary file (in hex format 8KB). What is done: create table foo foo(a bytea); -- import insert into foo values($1) \gloadfrom ~/xxx.jpg bytea -- export \pset format binary select a from foo \g ~/xxx2.jpg tested on import 55MB binary file Comments, notes? Available import formats are limited to text, bytea, xml - these formats are safe for receiving data via recv function. Regards Pavel > > Stephen >
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 2a9c412020..f26d406f89 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1945,6 +1945,38 @@ CREATE INDEX <varlistentry> + <term><literal>\gloadfrom <replaceable class="parameter">filename</replaceable> <optional> <replaceable class="parameter">format</replaceable> </optional> </literal></term> + + <listitem> + <para> + Sends the current query input buffer to the server. The current + query should to have one query parameter <literal>$1</literal>. + The content of <literal>filename</literal> file will be used as + the value of this parameter. + </para> + + <para> + When <literal>format</literal> is not specified, then data are + passed in text format. When format is specified, then data are + passed in binary format. The available formats are: + <literal>text</literal>, <literal>bytea</literal> + or <literal>xml</literal> type. In the example the XML document is + imported to table <structname>my_table</>: +<programlisting> +=> <userinput>CREATE TABLE my_table(id serial, doc xml);</> +=> <userinput>INSERT INTO my_table(doc) VALUES($1) RETURNING id</> +-> <userinput>\gloadfrom ~/Documents/data.xml xml</> + id +---- + 1 +(1 row) +</programlisting> + </para> + </listitem> + </varlistentry> + + + <varlistentry> <term><literal>\gset [ <replaceable class="parameter">prefix</replaceable> ]</literal></term> <listitem> @@ -2366,8 +2398,8 @@ lo_import 152801 <literal>aligned</literal>, <literal>wrapped</literal>, <literal>html</literal>, <literal>asciidoc</literal>, <literal>latex</literal> (uses <literal>tabular</literal>), - <literal>latex-longtable</literal>, or - <literal>troff-ms</literal>. + <literal>latex-longtable</literal>, <literal>troff-ms</literal> or + <literal>binary</literal>. Unique abbreviations are allowed. (That would mean one letter is enough.) </para> @@ -2404,6 +2436,12 @@ lo_import 152801 also requires the <application>LaTeX</application> <literal>longtable</literal> and <literal>booktabs</> packages. </para> + + <para> + The <literal>binary</> format is simply output values in + binary format. + </para> + </listitem> </varlistentry> diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 4f4a0aa9bd..51ed3df58c 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -28,6 +28,7 @@ #endif #include "catalog/pg_class.h" +#include "catalog/pg_type.h" #include "portability/instr_time.h" #include "libpq-fe.h" @@ -936,6 +937,50 @@ exec_command(const char *cmd, status = PSQL_CMD_SEND; } + /* + * \gloadfrom filename -- send query and use content of file as parameter + */ + else if (strcmp(cmd, "gloadfrom") == 0) + { + char *fmt = NULL; + char *fname = psql_scan_slash_option(scan_state, + OT_FILEPIPE, NULL, false); + + if (!fname) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + /* try to get separate format arg */ + fmt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + if (fmt) + { + if (strcmp(fmt, "text") == 0) + pset.gloadfrom_fmt = TEXTOID; + else if (strcmp(fmt, "bytea") == 0) + pset.gloadfrom_fmt = BYTEAOID; + else if (strcmp(fmt, "xml") == 0) + pset.gloadfrom_fmt = XMLOID; + else + { + psql_error("\\%s: only [text, bytea, xml] format can be specified\n", cmd); + success = false; + } + } + else + pset.gloadfrom_fmt = 0; /* UNKNOWNOID */ + + expand_tilde(&fname); + pset.gloadfrom = pg_strdup(fname); + } + free(fname); + status = PSQL_CMD_SEND; + } + /* \gset [prefix] -- send query and store result into variables */ else if (strcmp(cmd, "gset") == 0) { @@ -2518,6 +2563,9 @@ _align2string(enum printFormat in) case PRINT_TROFF_MS: return "troff-ms"; break; + case PRINT_BINARY: + return "binary"; + break; } return "unknown"; } @@ -2589,9 +2637,11 @@ do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) popt->topt.format = PRINT_LATEX_LONGTABLE; else if (pg_strncasecmp("troff-ms", value, vallen) == 0) popt->topt.format = PRINT_TROFF_MS; + else if (pg_strncasecmp("binary", value, vallen) == 0) + popt->topt.format = PRINT_BINARY; else { - psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n"); + psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms, binary\n"); return false; } } diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index e9d4fe6786..d9a52d17e6 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -12,6 +12,7 @@ #include <limits.h> #include <math.h> #include <signal.h> +#include <sys/stat.h> #ifndef WIN32 #include <unistd.h> /* for write() */ #else @@ -32,6 +33,7 @@ static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec); static bool command_no_begin(const char *query); static bool is_select_command(const char *query); +static bool read_file(char *fname, PQExpBuffer rawbuf); /* @@ -1285,7 +1287,8 @@ SendQuery(const char *query) } if (pset.fetch_count <= 0 || pset.gexec_flag || - pset.crosstab_flag || !is_select_command(query)) + pset.crosstab_flag || !is_select_command(query) || + pset.popt.topt.format == PRINT_BINARY || pset.gloadfrom) { /* Default fetch-it-all-and-print mode */ instr_time before, @@ -1294,7 +1297,56 @@ SendQuery(const char *query) if (pset.timing) INSTR_TIME_SET_CURRENT(before); - results = PQexec(pset.db, query); + /* + * PQexecParams disallow multiple commands often + * used by -c option. From compatibility reason the + * PQexecParams is used only when it is necessary. + */ + if (pset.popt.topt.format == PRINT_BINARY || pset.gloadfrom) + { + if (pset.gloadfrom) + { + PQExpBufferData rawbuf; + + initPQExpBuffer(&rawbuf); + + if (read_file(pset.gloadfrom, &rawbuf)) + { + Oid paramTypes[1]; + const char *paramValues[1]; + int paramLengths[1]; + int paramFormats[1]; + + paramTypes[0] = pset.gloadfrom_fmt; + paramFormats[0] = pset.gloadfrom_fmt != 0 ? 1 : 0; + paramValues[0] = rawbuf.data; + paramLengths[0] = rawbuf.len; + + results = PQexecParams(pset.db, query, + 1, + paramTypes, + paramValues, + paramLengths, + paramFormats, + pset.popt.topt.format == PRINT_BINARY); + } + else + { + OK = false; + results = NULL; + } + + termPQExpBuffer(&rawbuf); + } + else + { + results = PQexecParams(pset.db, query, + 0, NULL, NULL, NULL, NULL, + pset.popt.topt.format == PRINT_BINARY); + } + } + else + results = PQexec(pset.db, query); /* these operations are included in the timing result: */ ResetCancelConn(); @@ -1418,6 +1470,13 @@ sendquery_cleanup: pset.gfname = NULL; } + /* reset \gloadfrom input-from-filename trgger */ + if (pset.gloadfrom) + { + free(pset.gloadfrom); + pset.gloadfrom = NULL; + } + /* reset \gx's expanded-mode flag */ pset.g_expanded = false; @@ -2152,3 +2211,53 @@ recognized_connection_string(const char *connstr) { return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL; } + +/* + * read file into buffer + */ +static bool +read_file(char *fname, PQExpBuffer rawbuf) +{ + FILE *fd; + bool result = false; + + fd = fopen(fname, PG_BINARY_R); + if (fd) + { + struct stat fst; + + if (fstat(fileno(fd), &fst) != -1) + { + if (S_ISREG(fst.st_mode)) + { + if (fst.st_size <= ((int64) 1024) * 1024 * 1024) + { + size_t size; + char buf[512]; + + while ((size = fread(buf, 1, sizeof(buf), fd)) > 0) + appendBinaryPQExpBuffer(rawbuf, buf, size); + + if (ferror(fd)) + psql_error("%s: %s\n", fname, strerror(errno)); + else if (PQExpBufferBroken(rawbuf)) + psql_error("out of memory\n"); + else + result = true; + } + else + psql_error("%s is too big (greather than 1GB)\n", fname); + } + else + psql_error("%s is not regular file\n", fname); + } + else + psql_error("%s: %s\n", fname, strerror(errno)); + + fclose(fd); + } + else + psql_error("%s: %s\n", fname, strerror(errno)); + + return result; +} diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index ba14df0344..17d0469697 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -167,7 +167,7 @@ slashUsage(unsigned short int pager) * Use "psql --help=commands | wc" to count correctly. It's okay to count * the USE_READLINE line even in builds without that. */ - output = PageOutput(113, pager ? &(pset.popt.topt) : NULL); + output = PageOutput(114, pager ? &(pset.popt.topt) : NULL); fprintf(output, _("General\n")); fprintf(output, _(" \\copyright show PostgreSQL usage and distribution terms\n")); @@ -175,6 +175,7 @@ slashUsage(unsigned short int pager) fprintf(output, _(" \\g [FILE] or ; execute query (and send results to file or |pipe)\n")); fprintf(output, _(" \\gx [FILE] as \\g, but forces expanded output mode\n")); fprintf(output, _(" \\gexec execute query, then execute each value in its result\n")); + fprintf(output, _(" \\gloadfrom FILE [fmt] execute query, use content of FILE as query parameter\n")); fprintf(output, _(" \\gset [PREFIX] execute query and store results in psql variables\n")); fprintf(output, _(" \\q quit psql\n")); fprintf(output, _(" \\crosstabview [COLUMNS] execute query and display results in crosstab\n")); diff --git a/src/bin/psql/settings.h b/src/bin/psql/settings.h index 70ff1812c8..8078890a10 100644 --- a/src/bin/psql/settings.h +++ b/src/bin/psql/settings.h @@ -91,6 +91,9 @@ typedef struct _psqlSettings printQueryOpt popt; char *gfname; /* one-shot file output argument for \g */ + char *gloadfrom; /* one-shot file input argument for \gloadfrom */ + Oid gloadfrom_fmt; /* one-shot data file format UNKNOWNOID, + * TEXTOID, BYTEAOID or XMLOID */ bool g_expanded; /* one-shot expanded output requested via \gx */ char *gset_prefix; /* one-shot prefix argument for \gset */ bool gexec_flag; /* one-shot flag to execute query's results */ diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index f7494065de..3eb24c4502 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -1410,8 +1410,9 @@ psql_completion(const char *text, int start, int end) "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy", "\\e", "\\echo", "\\ef", "\\encoding", "\\errverbose", "\\ev", - "\\f", "\\g", "\\gexec", "\\gset", "\\gx", "\\h", "\\help", "\\H", - "\\i", "\\ir", "\\l", "\\lo_import", "\\lo_export", "\\lo_list", + "\\f", "\\g", "\\gexec", "\\gloadfrom", "\\gset", "\\gx", + "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l", + "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink", "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r", "\\s", "\\set", "\\setenv", "\\sf", "\\sv", "\\t", "\\T", "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", @@ -3422,7 +3423,7 @@ psql_completion(const char *text, int start, int end) { static const char *const my_list[] = {"unaligned", "aligned", "wrapped", "html", "asciidoc", - "latex", "latex-longtable", "troff-ms", NULL}; + "latex", "latex-longtable", "troff-ms", "binary", NULL}; COMPLETE_WITH_LIST_CS(my_list); } @@ -3443,8 +3444,8 @@ psql_completion(const char *text, int start, int end) } else if (TailMatchesCS2("\\set", MatchAny)) { - if (TailMatchesCS1("AUTOCOMMIT|ON_ERROR_STOP|QUIET|" - "SINGLELINE|SINGLESTEP")) + if (TailMatchesCS1("AUTOCOMMIT|BINARY_PARAM" + "ON_ERROR_STOP|QUIET|SINGLELINE|SINGLESTEP")) COMPLETE_WITH_LIST_CS2("on", "off"); else if (TailMatchesCS1("COMP_KEYWORD_CASE")) COMPLETE_WITH_LIST_CS4("lower", "upper", @@ -3469,7 +3470,7 @@ psql_completion(const char *text, int start, int end) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL); else if (TailMatchesCS1("\\cd|\\e|\\edit|\\g|\\i|\\include|" "\\ir|\\include_relative|\\o|\\out|" - "\\s|\\w|\\write|\\lo_import")) + "\\s|\\w|\\write|\\lo_import|\\gloadfrom")) { completion_charp = "\\"; matches = completion_matches(text, complete_from_files); diff --git a/src/fe_utils/print.c b/src/fe_utils/print.c index 9180b90004..829f9ebc83 100644 --- a/src/fe_utils/print.c +++ b/src/fe_utils/print.c @@ -3293,6 +3293,40 @@ printQuery(const PGresult *result, const printQueryOpt *opt, if (cancel_pressed) return; + /* direct print in binary format */ + if (opt->topt.format == PRINT_BINARY) + { + /* check format */ + for (c = 0; c < PQnfields(result); c++) + if (PQfformat(result, c) == 0) + { + fprintf(stderr, _("invalid data format (internal error)")); + exit(EXIT_FAILURE); + } + + for (r = 0; r < PQntuples(result); r++) + { + for (c = 0; c < PQnfields(result); c ++) + { + if (!PQgetisnull(result, r, c)) + { + int size = PQgetlength(result, r, c); + char *value = PQgetvalue(result, r, c); + bool success; + + success = fwrite(value, 1, size, fout) == size; + if (!success) + { + fprintf(stderr, _("write error (internal error): %s"), + strerror(errno)); + exit(EXIT_FAILURE); + } + } + } + } + return; + } + printTableInit(&cont, &opt->topt, opt->title, PQnfields(result), PQntuples(result)); diff --git a/src/include/fe_utils/print.h b/src/include/fe_utils/print.h index d89b6febcb..64ea406d5c 100644 --- a/src/include/fe_utils/print.h +++ b/src/include/fe_utils/print.h @@ -33,7 +33,8 @@ enum printFormat PRINT_ASCIIDOC, PRINT_LATEX, PRINT_LATEX_LONGTABLE, - PRINT_TROFF_MS + PRINT_TROFF_MS, + PRINT_BINARY /* add your favourite output format here ... */ }; diff --git a/src/test/regress/data/logo.data b/src/test/regress/data/logo.data new file mode 100644 index 0000000000..b324eb2178 --- /dev/null +++ b/src/test/regress/data/logo.data @@ -0,0 +1 @@ +\x47494638396164003a00e600002b89bb007bb3005a9b93cfe3006595008ab2458ab2eef5f9008abb0094c20054940079a8a4d7e888bad699c2d83492be297aaa45a5c80065aa77a8c577bad40085b1dbebf30083b90082ac006ba4005da00076a9007ca9bbdbeac6e6f10068adcce3ef0074a40079ad1475acbbd3e40075ac429bc40081b00085ae66a9cb0074b10090be1b7bb3006da952a4c90061a20064a57cc3dd0071ad0061a5f8fcfd0071a8bce1ee006baf0085b6006daf0081b6b1dceb007dae007db700548d126da80068a91482b665b8d65ab3d5005698007fab0058960078a8ccddea004e8c0c65a2669abc0066a00c6dad66a0c24480ac77b2d1004f92bbd7e8aad0e40c68a7aacbde0560a2246ea152accf77adcf66afcf11689fbbcfe20664a20767a9e0f1f6115f96085e9f3d3d3dffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000021f90400000000002c0000000064003a000007ff806282838485868788898a8b8c8d8a092b91910894083897973a22359c9c2d192f46a2a3a4a20a46a70aaaabacadab464c404c19b435013cb701273d273abe989795082bc3922b09c80982c8c6c294983d25d29d194c0246d7a5a5a7a8ddaca8aeab02b1b4b425b93cbc3abd17c0cec691c9c8cb9092ce983ad22535329cd6d8da027a1b984a15b8561a320029d742448087bb7ae9c03131983062c6981540b10cdebd4b224ac810c9cf9a806b27491119888a88ab243093847389eac5c2852d5ae0d2d5c397af0bed705c2c26a90086a318e879144631a43e192d3408207032a5001faa562af011856b14054a942888f2e38189080f9424f9da8da628269fff7236e429b122a677933014298294a31848f52609bb20c2e9481930a8564599644b0c1b1d76d8b011830504063b32eff87280f2801d1d06b0f84aa4b469231a5a0091db22408f9e3e81debd88a30887bd7c912ab547ac922615fa5464902a75b10f16166240d0a0800a002c340e985012c5c8081703188c8019c6850717594b1b310d236e4e113d78f8fc69b1120e1e1ce2e3469af42fb3669502885011123893171a04589c023f58f0804ca624f1c0003f24b1122a6b3d60a04c4928614304513c281e6aace5f45a6cedb4e31e070bc427df7c47d113586f945ca01f7fc0b500e054020c880505a7540596052c240110404424018105006498040b1e88f5e0ff2802ac26970cae8178010253e240e202259a885b6ef525b314020f05006309a01010608d553150e4620a4410838f5589720d115100604318aa08b0c308dc9022c00b1dcab09e0eb2bd77c4a15866791b8a5d7ac91b9861ee27020c2f0058e9995dd8008002689e64c381a62d26804b49c430c45761ec1985a827a5d6025432c8d01350b29db0c106871e8125892772d9e87df6e010a99825546aa9800258c88202677a0a010b0f0080928e2c4430800761443182073f284004ab0264006bac01104aab081b84706bae89f6ba578af601db9b0e618a29828cc61e2b40173b6c4adcbe5fece0c1183460f16d8d0a3c70c018072459e714a3822b000c32e410abff0c2a98dbc3adb7aa9babae596eb9d7092a3a4acc6bf506d0c27ff95e2a400c0f307b2615dcb270c0171e5851a306510c70adb5746281c5aa12537c31c684f2c071baebb21bf296f0cab3220228d70b04a52d57daa610a80968c500a7281106833b2b3080090ab030c0aa9a725ad5bf1abc7074ace995b081dd4b7facab891cf0c065c9c0525df5435763dd3211765a81ac150ca02640cf00744d0416032401c0da2cec1046ab68c23df748772fdd31ae4e6bc9175f80df27b80e3d84290b0cb01b0e83004dd8f043dc008ec0c09fcc0df0c0ceb473ebc5daa6ca2ce0f101aa8071ac19d41092e8a47fbc6baf514b5d0f45af551d7bec2f184e84ef7f020840ffe3026ab7b306460c11c3d73f78d0c4f9c80ba8bcf2389580eed21e976e7a6ea9d77301ebac734d006050b8ed756f0602a01c116690bb1d280e71390b10808850bb0708c15444885ffc9427035a2c6403f7c31fe9da653addc4cb7aff635df67a200b2014707b1ad896173430831a32c0055f8981c12c35030d1021023863001532a84109be4079aa294761a0d73490edcf84154080f556001415664f35af7b210c10784322504a002338801000f0851110a16501dac1181e10052bcc306e1234e20c54909372302184d04394a216451f4154e08f529447152fb04219b8d085db8b9d061e10c11910e1013b18c20e68308011d0b0523dfc010392a33edb05a8ff87a08c9b04a052478580308f47c0150917f5aefafcf18f2718063268454815aae090b82420ec5e300306188c0826f00000326782cf0880810c24c2102af98021346c8659ab14c5e4a2443c3611517c839a2b61f9ca61506990afb9252e5d288172c240021a408e593c10030f30c00454b081072656431828f30bd91940043e59c37ed6b07bb12a650b42c7b1544a6f7a7c34210a5e5981135420133da0554f5e334e5c4a40971a00c00e1850ade40c60320398d8167b180313b0600408a4a13ffde92a6a02a10604159d1ef9c64a2832f48f14b1956b247a811ce4a4a2872ca70684aa81200000004d28a6002e0a030d7c60072cc8603d61d74feecd20a0a5ffb41b1e53394284be2b377eb969432bb00efb3924a284a4630b3e005472321508e83c93091830d473a6d3062ca8ebf66640d52d6a000858fd44064088b76b824c51ad3c4a586f8a8313e0a0026675886b5e93831bdc60ad1fc86c6681c0d60f94f3b3e59c0124872a548d36a1861298416a57ab5a09f0f255a414ac59f316bd55a20805db64e8634152987a85330795b5ac70354bdce2ce40a3a4fd404607f081d68216b40c1c65603fb144dace747fbef223631ffa9edefa5605976d81702d5bdcf296330736582d3a853004d23ef7b3fd6c0107a9e93c8e89c0a0072d2197162bd64c3844b293ed810c2e3bde0293b7b8e58c240d3560020b044102e685efff0c80a082f9d6d17ea864573619c55fc63e563f616a1dca7c6a60039b37083660808a853983f26696a97c5dde7441684dbded519b28e8f043717a891300f821d9036f894bfc811b6876064d88001600504e177b16c637a87040a19281d9a212a127a24f8efd5880ed62e2c701ee0178810bdcf10677c8cf2d7279e17ad119c857cab16d4861ee5b5044ed0dbb8addb2182ad065dd72b7b13f5ea1986f50d9320f99c8e38df045dfac0200a4000a5048c108acbc81074081025078c002eefcc43c87b5cf111883a847dd01218059d02a30f4998f7a68231bd9c59f25608555d080518bfa002998b3846c3d0603ed6a0c14c0718efdd2e52e87da0113c8c2041aff6081314021c482665daa094de61c48410a1268f570115cce2857180a6320010460f204241c00022250d8019600061f806102073880a63930860964402f7d19b6208a5d81501b20044708c102c278800cf8367b841473b52b2b051210e1cc4486b50472306b1574600c6050c06a3260827a87e0e210f00113041e0200843b04f4b6f77e874dec02187b0c0628c2427150001b8ce10522d00208440d022d648f02031b0308a000800ec49b040dc80100a6c0731734a0013778fa08b22005008cc0010b3bc0141e50e18b83e1a555168109ae00813138c00700dfb4ae1c30060814c1e32bd7b7185cce677f7360c738e00c01626076033ca1d60de80105c66002ff18286102637042162c6081092ce10af19ec0139660810390400052400212a430812b983b0b063080b959a082148c0109296081f3ee5b03d32f8100a5d382c7eb7d6fc56280e5fb767901423d8108f85e08176f40d9a1008b5865610c2ca0000834a082d764e10933200117a2a001b63f21431ab8c218b8a00029d43b0a517002cc8920811684d101afcac2c21836050a04e108e07e4206049ea80574dcde70bf3dcbf5acfbddf39a610d4000a6070106f7102637012e607611f01a3d95031de0701f200507100533e06a52307d12980473340063f00426f0812600021620002d500361700513e000cd76002e3078f2775825727f19e0715a867b73a77bbc17ff7aa14700041002834700fa2159f576032e40023c4701afd101523047e116059a75030d27000f48040f7171ff37063e50828355034c40004bd06ba6370169373d83b7043328861ca07f2c5700b9e772feb600b871773830783fd014221004f506040120032f60008807053da0843010880730032bf4802fa0841a202617a70a58111357200529603f0b705f47b073da47020490285a30001c707157100234e8691bc18637e88630277337d5714ef050271000b2070150a0056122030dd7024af80201307806206241700052a0010fc87cb4d6811cd47a92d66b1950184720020b50793ec0764e50220ba03046e80046907221e06928a07b6de87f0670770ce5ff5046e7028f85055ae70353700000f0104160010e908848a08bbf78005060025af005164002c2c88f15667248300235d0021d97054c506b24f000ce08006cd7003e10044860762e60022e707107b00504f07624706914d09114d08d2ef78dfe860162550141c076a3e6005bf0024160845270711db00507296a1d100027b93020e0025cc08fc35802ca63025c300652b0730d90044cc001ea676b0790053eb08937696b55506f69788563b000de788a2e870119599215800223107a1899013c10125bf004067005a8710e00f0046070442a100a9c620155200025701222d10f4c70054fc09622775f22400010b0974fe0034d09322140007e670046e0034e10ff907ac18390099957d97fbac7950e75023ec601bdd00b3c200d25280d4e5182bfd80100a00227d9811a201224d10982055374b64421307ff47758f11102b67914234000f4a186a5189273b70294d967627599c4e95827c0039da90fca290dbb766b4ee003e2c20fac395025c00185616b1b606b473006dbb90063406fa3f676a38601b68602a3d67ffb069cc1699998599ced890bcba99c1910988329729de00935603fd63967dc2902dcc99ddd5995df39a0273206473106e6c97263e0720bea9bea49997c5692eed99e98b90ec7e914f9b90ffd500dcd739ff95918f0316795a89d002aa0de496fe039067b319ee6296a39d6a00d6a8a05009c0f5a99c209c44b98890114baa3ef890bcfb30f9d803773b69f855189ceb89dec52a2274aa02afa2e069aa008ba500500a39339a3c1c96f7fb4509859013acaa3ef799c608a9c622aa6206a9d446aa4b902a0ba626bde696be2296ae4797b086a6b532a6ae82906347aa574f74a0b459214daa5ef5904c739a6848a9c7de38c22b09f95b8696ac7a8f58765dac48d39c6677a6a8a795aa3fdc7503976023a0aa82720a83c00a64550a8863a96448aa88b8a2530d82e7bc44a89c58dbda9a78e30abb45aabb67aab821008003b diff --git a/src/test/regress/input/psql_export_import.source b/src/test/regress/input/psql_export_import.source new file mode 100644 index 0000000000..a6545c6de5 --- /dev/null +++ b/src/test/regress/input/psql_export_import.source @@ -0,0 +1,29 @@ +-- export/import binary varlena objects +create table test_bin_objects(id integer, doc bytea); +insert into test_bin_objects values(1, E'\\xDE00ADBEEF'); + +\pset format binary +select doc from test_bin_objects where id = 1 +\g results/varlenatest.bin + +insert into test_bin_objects values(2, $1) +\gloadfrom results/varlenatest.bin bytea + +\pset format aligned +select id, doc, md5(doc) from test_bin_objects; + +truncate test_bin_objects; + +insert into test_bin_objects values(1, $1) +\gloadfrom '@abs_srcdir@/data/logo.data' + +\pset format binary +select doc from test_bin_objects where id = 1 +\g results/100x58_1.gif + +insert into test_bin_objects values(2, $1) +\gloadfrom results/100x58_1.gif bytea + +\pset format aligned +-- print when md5 is unexpected (result should be empty) +select id, md5(doc) from test_bin_objects where md5(doc) <> '24da0c4de68bf19682344f8b060faeb5'; diff --git a/src/test/regress/output/psql_export_import.source b/src/test/regress/output/psql_export_import.source new file mode 100644 index 0000000000..bd7dbb3692 --- /dev/null +++ b/src/test/regress/output/psql_export_import.source @@ -0,0 +1,31 @@ +-- export/import binary varlena objects +create table test_bin_objects(id integer, doc bytea); +insert into test_bin_objects values(1, E'\\xDE00ADBEEF'); +\pset format binary +select doc from test_bin_objects where id = 1 +\g results/varlenatest.bin +insert into test_bin_objects values(2, $1) +\gloadfrom results/varlenatest.bin bytea +\pset format aligned +select id, doc, md5(doc) from test_bin_objects; + id | doc | md5 +----+--------------+---------------------------------- + 1 | \xde00adbeef | 70afdd78c75bfb6e76781d3785858b66 + 2 | \xde00adbeef | 70afdd78c75bfb6e76781d3785858b66 +(2 rows) + +truncate test_bin_objects; +insert into test_bin_objects values(1, $1) +\gloadfrom '@abs_srcdir@/data/logo.data' +\pset format binary +select doc from test_bin_objects where id = 1 +\g results/100x58_1.gif +insert into test_bin_objects values(2, $1) +\gloadfrom results/100x58_1.gif bytea +\pset format aligned +-- print when md5 is unexpected (result should be empty) +select id, md5(doc) from test_bin_objects where md5(doc) <> '24da0c4de68bf19682344f8b060faeb5'; + id | md5 +----+----- +(0 rows) + diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index ea7b5b4aa2..053ee03ed3 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -89,7 +89,7 @@ test: brin gin gist spgist privileges init_privs security_label collate matview # ---------- # Another group of parallel tests # ---------- -test: alter_generic alter_operator misc psql async dbsize misc_functions sysviews tsrf +test: alter_generic alter_operator misc psql psql_export_import async dbsize misc_functions sysviews tsrf # rules cannot run concurrently with any test that creates a view test: rules psql_crosstab amutils diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index cf48ea7cc8..32aaa30e15 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -124,6 +124,7 @@ test: alter_generic test: alter_operator test: misc test: psql +test: psql_export_import test: async test: dbsize test: misc_functions
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers