views:

538

answers:

2

I am trying to create a record containing the path to a file. The insertion is done into a Postgres database where UTF8 is enabled, using the NpqSQL driver.

My table definition:

CREATE TABLE images
(
    id serial,
    file_location character varying NOT NULL
)

My SQL statement including the code that executes it (boiled down to a minimum):

string sqlStatement = "INSERT INTO images (file_location) VALUES ('\\2010')";

NpgsqlConnection dbConnection = new NpgsqlConnection(connectionString);
dbConnection.Open();
NpgsqlCommand dbCommand = new NpgsqlCommand(sqlStatement , dbConnection);
int result = dbCommand.ExecuteNonQuery();
dbConnection.Close();    

When using pgAdmin to insert the above statement, it works fine. Using the NpgSQL driver through Visual Studio C#, it fails with this exception:

"ERROR: 22021: invalid byte sequence for encoding \"UTF8\": 0x81"

As Milen accurately explains, Postgres interprets the statement as an octal number (\o201 == 0x81).

As Milen also describes, the E infront of the path doesn't help.

So a quick recap: Why is NpqSQL stopping my insertion of the \\2010?

+1  A: 

(Realised my comments look like an answer so converted them accordingly.)

You haven't showed the real code so I suppose your interpreter/compiler interprets the double backslashes as an escaped backslash and then Postgres sees only one backslash followed by some digits. Which is it interprets as a octal byte value (octal 201 = hexadecimal 81).

About the "escape" string constants (strings starting with "E") - in your case they are completely unnecessary. In standard SQL backslash has no special meaning.

Please read "4.1.2.1. String Constants" and "4.1.2.2. String Constants with C-Style Escapes" from the manual (http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS) for details.

Milen A. Radev
@Milen: Thanks for your efforts. I've edited my original post and included the code. I still cannot understand though, where the '\\' is converted to '\'.
Chau
A: 

Milen deserves credit for leading me to the answer - thanks!

Appearantly NpgSQL performs one escape-iteration before inserting my SQL statement into Postgres. Thus to solve my problem, I replaced all the occurances of my backslashes with two backslashes instead:

string path = ... my path ...
path = path.Replace("\\", "\\\\");
sqlStatement = "INSERT INTO images (file_location) VALUES ('" + path + "')";
Chau
C# uses the backslash (http://msdn.microsoft.com/en-us/library/362314fe.aspx) for escape sequences in normal strings. Thus to include a single backslash in a string you need two backslashes. But there exist "Verbatim string literals", prefixed with @, which could be helpful in this case (@"c:\Docs\Source\a.txt" vs. "c:\\Docs\\Source\\a.txt").
Milen A. Radev
@Milen: Yeah the @ is normally very useful, but when the string is passed to NpgSQL the backslashes are removed :(
Chau