473,442 Members | 1,985 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

QuoteSQL

Why doesn't MySQLdb provide a function like this:

def QuoteSQL(Str, DoWild) :
"""returns a MySQL string literal which evaluates to Str. Needed
for those times when MySQLdb's automatic quoting isn't good enough."""
Result = []
for Ch in str(Str) :
if Ch == "\0" :
Ch = "\\0"
elif Ch == "\010" :
Ch = "\\b"
elif Ch == "\011" :
Ch = "\\t"
elif Ch == "\012" :
Ch = "\\n"
elif Ch == "\015" :
Ch = "\\r"
elif Ch == "\032" :
Ch = "\\z"
elif Ch == "'" or Ch == "\"" or Ch == "\\" :
Ch = "\\" + Ch
elif DoWild and (Ch == "%" or Ch == "_") :
Ch = "\\" + Ch
#end if
Result.append(Ch)
#end for
return "\"" + "".join(Result) + "\""
#end QuoteSQL

Sep 23 '06
67 2235
Dennis Lee Bieber wrote:
So.. In the case of MySQLdb, one can modify the dictionary of quote
converters... Seems like one could create a "class" for "LIKE" wildcard
strings, rather than just pass plain strings, and add that "type" to the
list of quote converters. That way, one's custom quote function CAN work
through the regular auto-quote method:

cr.execute(SQL, (LikeType(some_string_with_wildcards),) )

http://mail.python.org/pipermail/pyt...er/189583.html

I believe SQLite has a similar capability -- possibly other DB
adapters also have a means of attaching converters (in both directions).
using the term "auto-quoting" for bound parameters isn't very portable,
though. intelligent database engines don't even attempt to pass such
data through the SQL parser.

(does MySQL still do that, btw? or has that always been a PHP issue?)

</F>

Sep 26 '06 #51
In message <sl**********************@schuimige.stuvel.eu>, Sybren Stuvel
wrote:
Tim Chase enlightened us with:
>>cur.execute("select * from people where last_name in (%s)" %
','.join('%s' for i in xrange(len(t))),
t)

But since the value of 'i' isn't used at all, it can be abbreviated
to:
>>>cur.execute("select * from people where last_name in (%s)" %
','.join('%s' for i in t),
t)
Stuff this. Here are some new functions, separating the escaping of specials
from that of wildcards:

def SQLString(Str) :
"""returns a MySQL string literal which evaluates to Str. Needed
for those times when MySQLdb's automatic quoting isn't good
enough."""
Result = []
for Ch in str(Str) :
if Ch == "\0" :
Ch = "\\0"
elif Ch == "\010" :
Ch = "\\b"
elif Ch == "\011" :
Ch = "\\t"
elif Ch == "\012" :
Ch = "\\n"
elif Ch == "\015" :
Ch = "\\r"
elif Ch == "\032" :
Ch = "\\z"
elif Ch == "'" or Ch == "\"" or Ch == "\\" :
Ch = "\\" + Ch
#end if
Result.append(Ch)
#end for
return "\"" + "".join(Result) + "\""
#end SQLString

def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

So to turn the result from EscapeSQLWild into a string, you still need to
wrap it in SQLString.

And here is the corresponding replacement for my previous QuoteSQLList
routine:

def SQLStringList(TheList) :
"""returns a MySQL list containing the items of TheList, suitable
for use in an "in" clause."""
return \
"(" + ", ".join([SQLString(Str) for Str in TheList]) + ")"
#end SQLStringList

So Tim Chase's example above now becomes:

cur.execute("select * from people where last_name in %s" %
SQLStringList(t))

Much simpler, isn't it?

And there are other, more dynamic cases where explicit quoting using
SQLString is easier than trying to make do with autoquoting.
Sep 26 '06 #52
In message <ma**************************************@python.o rg>, Steve
Holden wrote:
Lawrence D'Oliveiro wrote:
>In message <ma**************************************@python.o rg>, Steve
Holden wrote:

>>>Lawrence D'Oliveiro wrote:

In message <ma**************************************@python.o rg>, Steve
Holden wrote:

>When you use the DB API correctly and paramterise your queries you
>still need to quote wildcards in search arguments, but you absolutely
>shouldn't quote the other SQL specials.
>
>That's what parameterised queries are for on the first place...
So you're suggesting I quote the wildcards, then rely on autoquoted
parameters to handle the rest? Unfortunately, that's stupid mistake
number 2.

Ah, so your quoting function will deduce the context in which arguments
intended for parameter substitution in the query will be used? Or are
you suggesting that it's unwise to rely on autoquoted parameters?


No, I'm saying it's _incorrect_ to use the existing autoquoting mechanism
in combination with a separate function that escapes the wildcards. I
previously described the two stupid mistakes that can arise from having a
separate function for doing just the wildcard quoting: this is the second
one.
Sadly your assertions alone fail to convince. Perhaps you could provide
a concrete example?
Sorry, that turned out to be wrong. You do in fact need to escape the
escapes on wildcards.
Sep 26 '06 #53
In message <ma**************************************@python.o rg>, Steve
Holden wrote:
Lawrence D'Oliveiro wrote:
>In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
>>>In particular it currently turns newlines in backslash followed by n
which (since MySQL ignores the extra backslash escape) is equivalent to
turning newlines into the character n.

But \n is valid MySQL syntax for a newline.

Phew. It's a good hob that MySQL is the only database in the known
universe, then, isn't it.
It's the one I was talking about in this thread.
Sep 26 '06 #54
Lawrence D'Oliveiro wrote:
In message <ma**************************************@python.o rg>, Steve
Holden wrote:
[...]
>>Sadly your assertions alone fail to convince. Perhaps you could provide
a concrete example?


Sorry, that turned out to be wrong. You do in fact need to escape the
escapes on wildcards.
Thank you.
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden

Sep 26 '06 #55
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild
That doesn't quite work. If you want to stop wildcards being interpreted as
such in a string used as a parameter to a query, then you have to escape
the escape character as well. In a LIKE clause, backslash percent matches a
percent character, but double backslash matches a single backslash and
double backslash percent matches a backslash followed by anything.

I think this version should work, (or rewrite it as a 'for' loop if you
prefer, though I think the replace version is clearer as well as being
between 3 and 222 times faster on the inputs I tried):

def EscapeSQLWild(s):
s = s.replace('\\', '\\\\')
s = s.replace('%', '\\%')
s = s.replace('_', '\\_')
return s

Sep 27 '06 #56
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
> def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

That doesn't quite work. If you want to stop wildcards being interpreted
as such in a string used as a parameter to a query, then you have to
escape the escape character as well.
That's part of the separation of function. Note that the above function does
not generate a MySQL string literal: you must still put it through the
previously-defined SQLString routine, which will automatically escape all
the specials added by EscapeSQLWild.

Sep 27 '06 #57
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
In message <Xn*************************@127.0.0.1>, Duncan Booth
wrote:
>Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
>> def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

That doesn't quite work. If you want to stop wildcards being
interpreted as such in a string used as a parameter to a query, then
you have to escape the escape character as well.

That's part of the separation of function. Note that the above
function does not generate a MySQL string literal: you must still put
it through the previously-defined SQLString routine, which will
automatically escape all the specials added by EscapeSQLWild.
You are still missing the point. I'm not talking about generating a MySQL
string literal, I'm talking about preventing wildcards characters having
their special meaning when using the string as a parameter in
cursor.execute. You still have to escape the escape character, and you have
to do that before or at the same time as you escape the wildcards. No
string literals are involved anywhere.

Calling the SQLString routine in this situation would be wrong because it
would escape characters such as newline which must not be escaped.
Sep 27 '06 #58
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
>In message <Xn*************************@127.0.0.1>, Duncan Booth
wrote:
>>Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:

def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

That doesn't quite work. If you want to stop wildcards being
interpreted as such in a string used as a parameter to a query, then
you have to escape the escape character as well.

That's part of the separation of function. Note that the above
function does not generate a MySQL string literal: you must still put
it through the previously-defined SQLString routine, which will
automatically escape all the specials added by EscapeSQLWild.
You are still missing the point. I'm not talking about generating a MySQL
string literal, I'm talking about preventing wildcards characters having
their special meaning when using the string as a parameter in
cursor.execute.
But that's what cursor.execute will do if you use its parameter-substitution
mechanism--generate a string literal.
You still have to escape the escape character...
Which will be done by cursor.execute if you use its parameter-substitution
mechanism.
Calling the SQLString routine in this situation would be wrong because it
would escape characters such as newline which must not be escaped.
SQLString will convert newlines into the \n sequence in the generated string
literal, which MySQL will interpret as a newline. cursor.execute's
parameter-substitution mechanism would do exactly the same thing.
Sep 27 '06 #59
Ben

Lawrence D'Oliveiro wrote:
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
In message <Xn*************************@127.0.0.1>, Duncan Booth
wrote:

Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:

def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

That doesn't quite work. If you want to stop wildcards being
interpreted as such in a string used as a parameter to a query, then
you have to escape the escape character as well.

That's part of the separation of function. Note that the above
function does not generate a MySQL string literal: you must still put
it through the previously-defined SQLString routine, which will
automatically escape all the specials added by EscapeSQLWild.
You are still missing the point. I'm not talking about generating a MySQL
string literal, I'm talking about preventing wildcards characters having
their special meaning when using the string as a parameter in
cursor.execute.

But that's what cursor.execute will do if you use its parameter-substitution
mechanism--generate a string literal.
You still have to escape the escape character...

Which will be done by cursor.execute if you use its parameter-substitution
mechanism.
Calling the SQLString routine in this situation would be wrong because it
would escape characters such as newline which must not be escaped.

SQLString will convert newlines into the \n sequence in the generated string
literal, which MySQL will interpret as a newline. cursor.execute's
parameter-substitution mechanism would do exactly the same thing.
But cursor.execute does not necessarily do parameter-substitution. It
can send the data directly to the database with no escaping. In this
case, doing it yourself is a massive pessimization, and you're more
likely to get it wrong than the driver writers

Ben

Sep 27 '06 #60
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
>You are still missing the point. I'm not talking about generating a
MySQL string literal, I'm talking about preventing wildcards
characters having their special meaning when using the string as a
parameter in cursor.execute.

But that's what cursor.execute will do if you use its
parameter-substitution mechanism--generate a string literal.
The current implementation of the MySQL database adapter will do that.
Other database adaptors may handle parameters without generating string
literals.
>
>You still have to escape the escape character...

Which will be done by cursor.execute if you use its
parameter-substitution mechanism.
Too late and not enough. Too late, because if you want to search for the
literal "\\%" (single backslash percent) you need to escape the backslash
before you escape the percent. Not enough because at the point MySQLdb
finally converts it to a string literal a literal backslash to be used in a
context where wildcards are allowed needs to be spelled with 4 backslashes.
i.e. it needs to be escaped twice, once for the string literal and once to
stop it being interpreted as an escape within the wildcard string.
>
>Calling the SQLString routine in this situation would be wrong
because it would escape characters such as newline which must not be
escaped.

SQLString will convert newlines into the \n sequence in the generated
string literal, which MySQL will interpret as a newline.
cursor.execute's parameter-substitution mechanism would do exactly the
same thing.
Correct: they both do the same thing. So you have to use either SQLString
or the parameter substitution. You cannot use both. Calling SQLString on a
string to be passed in to the parameter substitution mechanism will not
work correctly.

May I suggest that the way for you to progress would be if you wrote some
unit tests? So, create a simple table containing a few strings with special
characters and do a few wildcard searches looking for %, newline etc. That
way you can post not just a function, but some runnable code which either
demonstrates that your function does what you say, or lets people suggest a
new test which demonstrates that it fails to handle some particular edge
case.

Here, I'll even give you a start. Run the code below (you might need to
create a database called 'test' if you don't already have one), and then
explain why test_escapebackslashwild fails, and either why you think the
test is broken or how you would fix your code? All the other tests should
pass.
---------------- mysqltest.py ---------------
import unittest
import MySQLdb

def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

class Tests(unittest.TestCase):
values = "x%x", "xnx", "x\nx", "x\\nx", "x\\%x"
def setUp(self):
db = self.db = MySQLdb.connect("", "", "", "test")
cursor = self.cursor = db.cursor()
cursor.execute('''create temporary table pythontest
(id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
name VARCHAR(30))''')
cursor.executemany(
"insert into pythontest(name) values(%s)",
self.values)

def tearDown(self):
self.cursor.execute("drop table pythontest")

def test_wildcard(self):
n = self.cursor.execute(
"select name from pythontest where name like %s",
"x%x")
self.assertEqual(n, 5)

def test_nonwildcard(self):
self.cursor.execute(
"select name from pythontest where name like %s",
"x\\%x")
expected = (('x%x',),)
self.assertEqual(expected, self.cursor.fetchall())

def test_newline(self):
self.cursor.execute(
"select name from pythontest where name like %s",
"x\nx")
expected = (('x\nx',),)
self.assertEqual(expected, self.cursor.fetchall())

def test_backslashn(self):
self.cursor.execute(
"select name from pythontest where name like %s",
"x\\\\nx")
expected = (('x\\nx',),)
self.assertEqual(expected, self.cursor.fetchall())

def test_backslashpercent(self):
self.cursor.execute(
"select name from pythontest where name like %s",
"x\\\\\\%x")
expected = (('x\\%x',),)
self.assertEqual(expected, self.cursor.fetchall())

def test_escapewild(self):
self.cursor.execute(
"select name from pythontest where name like %s",
EscapeSQLWild("x%x"))
expected = (('x%x',),)
self.assertEqual(expected, self.cursor.fetchall())

def test_escapebackslashwild(self):
self.cursor.execute(
"select name from pythontest where name like %s",
EscapeSQLWild("x\\%x"))
expected = (('x\\%x',),)
self.assertEqual(expected, self.cursor.fetchall())

if __name__=='__main__':
unittest.main()
---------------------------------------------
Sep 27 '06 #61
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
>>You are still missing the point. I'm not talking about generating a
MySQL string literal, I'm talking about preventing wildcards
characters having their special meaning when using the string as a
parameter in cursor.execute.

But that's what cursor.execute will do if you use its
parameter-substitution mechanism--generate a string literal.

The current implementation of the MySQL database adapter will do that.
Other database adaptors may handle parameters without generating string
literals.
Doesn't matter what other implementations of parametrization might or might
not do. The syntax I generate is valid for MySQL, therefore it will work
with the MySQL database adapter regardless of what else the adaptor might
do.
>>You still have to escape the escape character...

Which will be done by cursor.execute if you use its
parameter-substitution mechanism.

Too late and not enough. Too late, because if you want to search for the
literal "\\%" (single backslash percent) you need to escape the backslash
before you escape the percent. Not enough because at the point MySQLdb
finally converts it to a string literal a literal backslash to be used in
a context where wildcards are allowed needs to be spelled with 4
backslashes. i.e. it needs to be escaped twice, once for the string
literal and once to stop it being interpreted as an escape within the
wildcard string.
I'm assuming you mean, how would you get from a Python expression to a MySQL
clause that looks like

name like "%\\\\%%"

(wildcard % followed by literal backslash \\ followed by literal percent \%
followed by wildcard %.) That's easy:

EscapeSQLWild(r"\%") =r"\\%"
SQLString(r"\\%") =r'"\\\\%"'

So the Python expression

"name like %s" % SQLString("%" + EscapeSQLWild(r"\%") + "%")

gives you what you want.
Correct: they both do the same thing. So you have to use either SQLString
or the parameter substitution. You cannot use both. Calling SQLString on a
string to be passed in to the parameter substitution mechanism will not
work correctly.
I thought I had made that clear already.

Sep 27 '06 #62
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
I'm assuming you mean, how would you get from a Python expression to a
MySQL clause that looks like

name like "%\\\\%%"

(wildcard % followed by literal backslash \\ followed by literal
percent \% followed by wildcard %.) That's easy:

EscapeSQLWild(r"\%") =r"\\%"
SQLString(r"\\%") =r'"\\\\%"'

So the Python expression

"name like %s" % SQLString("%" + EscapeSQLWild(r"\%") + "%")

gives you what you want.
Deary me. Did you actually test out that bit of code before you posted it?
No, I thought not. I even gave you a test harness to make it easy for you
to check the quality of your code before posting.

All you had to do was to add another test:

def test_escapebackslashwild2(self):
self.cursor.execute(
("select name from pythontest where name like %s" %
SQLString("%" + EscapeSQLWild(r"\%") + "%")))
expected = (('x\\%x',),)
self.assertEqual(expected, self.cursor.fetchall())

and the output is:
================================================== ====================
FAIL: test_escapebackslashwild2 (__main__.Tests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "mysqltest.py", line 111, in test_escapebackslashwild2
self.assertEqual(expected, self.cursor.fetchall())
AssertionError: (('x\\%x',),) != (('x\\nx',), ('x\\%x',))

----------------------------------------------------------------------

as I said before, your escaping is too late and not enough. You've got a
search for a literal backslash in there sure enough, but you haven't
managed to escape the percent character.

Try again.
Sep 27 '06 #63
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
>I'm assuming you mean, how would you get from a Python expression to a
MySQL clause that looks like

name like "%\\\\%%"

(wildcard % followed by literal backslash \\ followed by literal
percent \% followed by wildcard %.) That's easy:

EscapeSQLWild(r"\%") =r"\\%"
SQLString(r"\\%") =r'"\\\\%"'

So the Python expression

"name like %s" % SQLString("%" + EscapeSQLWild(r"\%") + "%")

gives you what you want.
Deary me. Did you actually test out that bit of code before you posted it?
>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\%'
>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\%%"'
>>EscapeSQLWild(r"\%") == r"\\%"
True
>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\%%"'
True

Sep 27 '06 #64
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
In message <Xn*************************@127.0.0.1>, Duncan Booth wrote:
>Deary me. Did you actually test out that bit of code before you
posted it?
>>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\%'
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\%%"'
>>>EscapeSQLWild(r"\%") == r"\\%"
True
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\%%"'
True
Ah, so that's a 'no' then. I can't see any tests there. How do you know
that those strings work correctly MySQL queries?

Please, open your mind to what I'm saying. I'm not trying to criticise your
aims, just trying to point out the simple fact that your EscapeSQLWild
function has a bug. If nothing else, the fact that you are finding this so
hard to understand shows that there is a need for a correctly written
function to do this.

The fix to EscapeSQLWild to get test_escapebackslashwild2 to work is a
trivial change, and not suprisingly also makes the other failing test in my
script (the one using parameterised queries and EscapeSQLWild) pass.

Again, please, try running the script I posted, and in particular
test_escapebackslashwild2. It uses the SQL query you yourself created, and
it fails because it matches something it shouldn't.
Sep 28 '06 #65
In message <ef**********@lust.ihug.co.nz>, I wrote:
def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild
Correction, backslashes need to be escaped at this level as well. So that
should become

def EscapeSQLWild(Str) :
"""escapes MySQL pattern wildcards in Str."""
Result = []
for Ch in str(Str) :
if Ch == "\\" or Ch == "%" or Ch == "_" :
Result.append("\\")
#end if
Result.append(Ch)
#end for
return "".join(Result)
#end EscapeSQLWild

Sep 28 '06 #66
In message <ef**********@lust.ihug.co.nz>, LI wrote:
>>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\%'
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\%%"'
>>>EscapeSQLWild(r"\%") == r"\\%"
True
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\%%"'
True
With the correction to EscapeSQLWild, this becomes:
>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\\\%'
>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\\\\\%%"'
>>EscapeSQLWild(r"\%") == r"\\\%"
True
>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\\\%%"'
True

Sep 28 '06 #67
Lawrence D'Oliveiro <ld*@geek-central.gen.new_zealandwrote:
In message <ef**********@lust.ihug.co.nz>, LI wrote:
>>>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\%'
>>>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\%%"'
>>>>EscapeSQLWild(r"\%") == r"\\%"
True
>>>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\%%"'
True

With the correction to EscapeSQLWild, this becomes:
>>>execfile("QuoteSQL.py")
EscapeSQLWild(r"\%")
'\\\\\\%'
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%")
'"%\\\\\\\\\\\\%%"'
>>>EscapeSQLWild(r"\%") == r"\\\%"
True
>>>SQLString("%" + EscapeSQLWild(r"\%") + "%") == r'"%\\\\\\%%"'
True
True but irrelevant. The point is that it isn't relevant whether you are
seeing 4, 6, 8, or 12 backslashes, because you wrote the code to produce
the number you thought you wanted and you had misunderstood how MySQL
works. That's why it is important in a situation like this to test against
the code that actually uses the string. I had no idea how MySQL would
handle escapes in this situation, but I didn't need to know, I just wrote
some tests and figured out which strings would make them pass or fail.

Anyway, congratulations on finally getting the message.
Sep 29 '06 #68

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.