Index: src/bin/psql/mainloop.c =================================================================== --- src/bin/psql/mainloop.c (HEAD) +++ src/bin/psql/mainloop.c (working copy) Index: src/bin/psql/mainloop.c @@ -13,8 +13,33 @@ #include "common.h" #include "input.h" #include "settings.h" +#include "mb/pg_wchar.h" +static bool +is_valid_encoding(int expected_encoding, const char *str) +{ + const char * s; + + if (expected_encoding == PG_SQL_ASCII) + return true; /* always accepted */ + + if (expected_encoding == pset.encoding) + return true; /* matched */ + + for (s = str; *s; s++) + { + if (IS_HIGHBIT_SET(*s)) + { + psql_error("explicit encoding is required: %s expected\n", + pg_encoding_to_char(expected_encoding)); + return false; + } + } + + return true; /* accepted because all characters are in ascii */ +} + /* * Main processing loop for reading lines of input * and sending them to the backend. @@ -36,6 +61,7 @@ int added_nl_pos; bool success; bool line_saved_in_history; + int expected_encoding = PG_SQL_ASCII; volatile int successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; @@ -134,8 +160,17 @@ else { line = gets_fromFile(source); - if (!line && ferror(source)) - successResult = EXIT_FAILURE; + if (!line) + { + if (ferror(source)) + successResult = EXIT_FAILURE; + } + else if (pset.lineno == 0 && strncmp(line, "\xef\xbb\xbf", 3) == 0) + { + /* trim BOM sequence to whitespaces */ + memmove(line, line + 3, strlen(line + 3) + 1); + expected_encoding = PG_UTF8; + } } /* @@ -248,7 +283,8 @@ } /* execute query */ - success = SendQuery(query_buf->data); + success = is_valid_encoding(expected_encoding, query_buf->data) && + SendQuery(query_buf->data); slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR; /* transfer query to previous_buf by pointer-swapping */ @@ -266,6 +302,7 @@ else if (scan_result == PSCAN_BACKSLASH) { /* handle backslash command */ + PQExpBuffer buf; /* * If we added a newline to query_buf, and nothing else has @@ -292,9 +329,11 @@ } /* execute backslash command */ - slashCmdStatus = HandleSlashCmds(scan_state, - query_buf->len > 0 ? - query_buf : previous_buf); + buf = query_buf->len > 0 ? query_buf : previous_buf; + if (is_valid_encoding(expected_encoding, buf->data)) + slashCmdStatus = HandleSlashCmds(scan_state, buf); + else + slashCmdStatus = PSQL_CMD_ERROR; success = slashCmdStatus != PSQL_CMD_ERROR; @@ -378,7 +417,8 @@ pg_send_history(history_buf); /* execute query */ - success = SendQuery(query_buf->data); + success = is_valid_encoding(expected_encoding, query_buf->data) && + SendQuery(query_buf->data); if (!success && die_on_error) successResult = EXIT_USER;