views:

2593

answers:

5

I think you can guess the problem I'm having. I'm inserting filenames in to an sql database in C++ Builder. Some files have an apostrophe in their name. This breaks the sql insert query. the usual way to fix this is to double up and apostrophes you want to be part of the field value.

For example if I want to add 'george's' to field 'owner' the sql query would be "insert into table (owner) values ('george''s')"

I'm ok with that bit. I just need to get the single apostrophes replaced with double ones. AnsiString doesn't seem to have a built in function for this. Is there a simple way to do it without having to include a whole new header file?

+1  A: 

I haven't used AnsiString, but basically I'd do the following:

  • Reverse find single quotes in your string
  • Look to the left and right of the current single quote index
  • If there's not a single quote there already, insert a single quote after your current index
  • Continue looping until you hit index 0.
Eddie Parker
I was posting my own answer before I saw yours. but thanks anyway.
MrVimes
That's OK if you just want to make sure no apostrophe is bare, but it's no good if you actually want to preserve the data. A double-apostrophe will become a single apostrophe upon insertion in the database, and it won't be re-doubled upon selection, so you won't know what was originally inserted.
Rob Kennedy
+4  A: 

Actually I got the answer by myself...

item = StringReplace( item, "'", "''", TReplaceFlags() );

(so there is a built in replace function in AnsiString afterall)

MrVimes
Am I missing something, but wouldn't that make double apostrophes triple apostrophes as well?
Ray
Don't know. One way to find out. I'll put a double quote in a filename and see what happens...It seems to work fine. It turns double quotes into quadrouple quotes, which would preserve the double quotes in the database.
MrVimes
So I guess it will always give an even number of quotes (every quote is turned into two), which would always 'work' in the database.
MrVimes
p.s. the correct syntax for what I'm doing is...item = StringReplace( item, "'", "''", TReplaceFlags()<<rfReplaceAll);
MrVimes
A: 

The usual way to do this is to use prepared statements as opposed to generating your own sql. Look up SQL Injection for one reason why this is bad. Basically, if anywhere in your app, you forget to double up the quotes in any sql statement, and an attacker can somehow submit a value into that sql statement, your database is hacked. (See this xkcd comic for a humourous example of what can happen.)

Eclipse
Can you explain that? My filenames are being generated in real time so I need to insert them one at a time after the name has been aquired. how do I do prepared statements?
MrVimes
SQL Injection. What I'm doing is for my own use so nobody else will be able to see it. But I'll read up on SQL Injection anyway as I may one day be doing lots of sql for a website.
MrVimes
The actual details will depend on your database API that you are using. Look through it for something like prepared statements or parameterized queries.
Eclipse
A: 

In C++ Builder, you're looking for the AnsiQuotedStr function, in SysUtils. Its inverse is AnsiExtractQuotedStr. They aren't methods of the AnsiString type itself because they don't need intimate knowledge of the type's internals.

More importantly, though, you should be using parameterized queries. If the components you're using for database access don't support those, then get a different database library. There is no shortage of database choices, so you can afford to be picky about features, and parameterized queries should be near the top of the list.

Note that despite their names, the AnsiX functions accept UnicodeString parameters, not AnsiString, in Delphi and C++ Builder 2009.

Rob Kennedy
A: 

What happens if you substitute it like that

item = StringReplace( item, "'", "\'", TReplaceFlags() );
Riho
I get an SQL error.
MrVimes
OK. Also it should be possible to use ", like that : values("O'Malley's")
Riho