Oups. Lost a negation. BTW, I can't seem to find documentation for catch in the modref - where should I look for it?
$ cvs diff -u Sql.pike Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 21 Oct 2003 22:59:05 -0000 @@ -340,9 +340,16 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! Returns +//! @ol +//! @item +//! The result as an array of mappings indexed on the name +//! of the columns. +//! @item +//! 0 if the query didn't return any result (e.g. INSERT or similar). +//! @item +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +366,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHEREe gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
Why not just say
if(err) werror("An error occured.");
? Much clearer IMO. Also, there seems to be one "e" to much in "wheree". :-)
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-22 01:01: Subject: Proposal-patch for documentation of Sql.pike
Oups. Lost a negation. BTW, I can't seem to find documentation for catch in the modref - where should I look for it?
$ cvs diff -u Sql.pike Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 21 Oct 2003 22:59:05 -0000 @@ -340,9 +340,16 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! Returns +//! @ol +//! @item +//! The result as an array of mappings indexed on the name +//! of the columns. +//! @item +//! 0 if the query didn't return any result (e.g. INSERT or similar). +//! @item +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +366,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHEREe gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
=)
On the first cleanup I claim total utter ignorance (After all I was asking for documentation on catch).
On the second I plead guilty. Crap.
$ cvs diff -u Sql.pike Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 21 Oct 2003 23:05:18 -0000 @@ -340,9 +340,16 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! Returns +//! @ol +//! @item +//! The result as an array of mappings indexed on the name +//! of the columns. +//! @item +//! 0 if the query didn't return any result (e.g. INSERT or similar). +//! @item +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +366,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHERE gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 01:03: Subject: Proposal-patch for documentation of Sql.pike
Why not just say
if(err) werror("An error occured.");
? Much clearer IMO. Also, there seems to be one "e" to much in "wheree". :-)
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Uhm, yeah. But where is the source code that defines it?
throw() is documented in src/builtin_functions.c
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 01:13: Subject: Re: Proposal-patch for documentation of Sql.pike
in the chapterized manual.
greetings, martin.
/ Brevbäraren
language.yacc. catch is a language construct, not a function.
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-22 01:21: Subject: Re: Proposal-patch for documentation of Sql.pike
Uhm, yeah. But where is the source code that defines it?
throw() is documented in src/builtin_functions.c
/ Peter Lundqvist (disjunkt)
catch isn't a function but a language construct so it is defined in language.yacc.
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 01:21: Subject: Re: Proposal-patch for documentation of Sql.pike
Uhm, yeah. But where is the source code that defines it?
throw() is documented in src/builtin_functions.c
/ Peter Lundqvist (disjunkt)
2.
(Plus points for different word order though. ;)
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Previous text:
2003-10-22 01:25: Subject: Re: Proposal-patch for documentation of Sql.pike
catch isn't a function but a language construct so it is defined in language.yacc.
/ Martin Nilsson (saturator)
I shouldn't have spent a lot of precious time to verify that it was indeed implemented in language.yacc...
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 01:26: Subject: Re: Proposal-patch for documentation of Sql.pike
(Plus points for different word order though. ;)
/ Marcus Comstedt (ACROSS) (Hail Ilpalazzo!)
Oh, then that makes sense - sort of.
Hmm.. This leavs quite a few @[catch] that don't lead anywhere. Should they be removed, or should there be a documentation of catch somewhere?
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 01:27: Subject: Re: Proposal-patch for documentation of Sql.pike
I shouldn't have spent a lot of precious time to verify that it was indeed implemented in language.yacc...
/ Martin Nilsson (saturator)
Do they really? I would have thought that they wasn't turned into links at all when the presentation format was generated.
They should in any event not be removed.
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 01:32: Subject: Re: Proposal-patch for documentation of Sql.pike
Oh, then that makes sense - sort of.
Hmm.. This leavs quite a few @[catch] that don't lead anywhere. Should they be removed, or should there be a documentation of catch somewhere?
/ Peter Lundqvist (disjunkt)
They should in any event not be removed.
Then just what is their purpose? OTOH I guess they don't waste an incredible amount of space...
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 01:36: Subject: Re: Proposal-patch for documentation of Sql.pike
Do they really? I would have thought that they wasn't turned into links at all when the presentation format was generated.
They should in any event not be removed.
/ Martin Nilsson (saturator)
To signify that you want a link to the description of catch. Now, since catch isn't in the module documentation you won't get one there and since no links are created at all in the chapterized manual you won't get one there either. But if someone took the time to write code that generates links for that one as well, then you would.
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 01:38: Subject: Re: Proposal-patch for documentation of Sql.pike
They should in any event not be removed.
Then just what is their purpose? OTOH I guess they don't waste an incredible amount of space...
/ Peter Lundqvist (disjunkt)
Oh, BTW. I was asked to ask to explain SQL injections yesterday. Would this ammendment be superfluous in a pike manual?
$ cvs diff -u Sql.pike Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 22 Oct 2003 00:10:36 -0000 @@ -28,6 +28,20 @@
//! @decl string quote(string s) //! Quote a string @[s] so that it can safely be put in a query. +//! +//! All input that is used in SQL-querys should be quoted to prevent +//! SQL injections. +//! +//! Consider this harmfull code: +//! @code +//! string my_input = "rob' OR name!='rob"; +//! string my_query = "DELETE FROM tblUsers WHERE name='"+my_input+"'"; +//! my_db->query(my_query); +//! @endcode +//! +//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@}
function(string:string) quote = .sql_util.quote;
@@ -340,9 +354,16 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! Returns +//! @ol +//! @item +//! The result as an array of mappings indexed on the name +//! of the columns. +//! @item +//! 0 if the query didn't return any result (e.g. INSERT or similar). +//! @item +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +380,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHERE gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 01:42: Subject: Re: Proposal-patch for documentation of Sql.pike
To signify that you want a link to the description of catch. Now, since catch isn't in the module documentation you won't get one there and since no links are created at all in the chapterized manual you won't get one there either. But if someone took the time to write code that generates links for that one as well, then you would.
/ Martin Nilsson (saturator)
You don't have CVS-access of your own?
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 02:15: Subject: Re: Proposal-patch for documentation of Sql.pike
Oh, BTW. I was asked to ask to explain SQL injections yesterday. Would this ammendment be superfluous in a pike manual?
$ cvs diff -u Sql.pike Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 22 Oct 2003 00:10:36 -0000 @@ -28,6 +28,20 @@
//! @decl string quote(string s) //! Quote a string @[s] so that it can safely be put in a query. +//! +//! All input that is used in SQL-querys should be quoted to prevent +//! SQL injections. +//! +//! Consider this harmfull code: +//! @code +//! string my_input = "rob' OR name!='rob"; +//! string my_query = "DELETE FROM tblUsers WHERE name='"+my_input+"'"; +//! my_db->query(my_query); +//! @endcode +//! +//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@}
function(string:string) quote = .sql_util.quote;
@@ -340,9 +354,16 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! Returns +//! @ol +//! @item +//! The result as an array of mappings indexed on the name +//! of the columns. +//! @item +//! 0 if the query didn't return any result (e.g. INSERT or similar). +//! @item +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +380,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHERE gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
You might want to add that the by far easiest way to avoid the problem is to use the 'sprintf' like feature of query (and big query).
As in:
query( "SELECT name FROM customers WHERE ident=%s", ident );
This will automatically do the quoting for you. The same goes for the :foo syntax.
/ Per Hedbor ()
Previous text:
2003-10-22 05:06: Subject: Re: Proposal-patch for documentation of Sql.pike
(. Sure I do - I just like to spam this list with patches .) ;-)
/ Peter Lundqvist (disjunkt)
Good point.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 06:31: Subject: Re: Proposal-patch for documentation of Sql.pike
You might want to add that the by far easiest way to avoid the problem is to use the 'sprintf' like feature of query (and big query).
As in:
query( "SELECT name FROM customers WHERE ident=%s", ident );
This will automatically do the quoting for you. The same goes for the :foo syntax.
/ Per Hedbor ()
Index: Sql.pike =================================================================== RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 22 Oct 2003 13:46:49 -0000 @@ -28,6 +28,27 @@
//! @decl string quote(string s) //! Quote a string @[s] so that it can safely be put in a query. +//! +//! All input that is used in SQL-querys should be quoted to prevent +//! SQL injections. +//! +//! Consider this harmfull code: +//! @code +//! string my_input = "rob' OR name!='rob"; +//! string my_query = "DELETE FROM tblUsers WHERE name='"+my_input+"'"; +//! my_db->query(my_query); +//! @endcode +//! +//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@} +//! +//! Usually this is done - not by calling quote explicitly - but through +//! using a @[sprintf] like syntax +//! @code +//! string my_input = "rob' OR name!='rob"; +//! my_db->query("DELETE FROM tblUsers WHERE name=%s",my_input); +//! @endcode
function(string:string) quote = .sql_util.quote;
@@ -340,9 +361,20 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! @returns +//! Returns one of the following on success: +//! @mixed +//! @type array(mapping(string:string)) +//! The result as an array of mappings indexed on the name +//! of the columns +//! @type zero +//! The value @expr{0@} (zero) if the query didn't return any +//! result (eg @tt{INSERT@} or similar). +//! @endmixed +//! +//! @throws +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +391,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHERE gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 13:26: Subject: Re: Proposal-patch for documentation of Sql.pike
Good point.
/ Peter Lundqvist (disjunkt)
+//! @returns
[...]
+//! @throws
[...]
//! @param q
Parameters should by convention be described before return values.
/ Henrik Grubbström (Lysator)
Previous text:
2003-10-22 15:48: Subject: Re: Proposal-patch for documentation of Sql.pike
Index: Sql.pike
RCS file: /cvs/Pike/7.5/lib/modules/Sql.pmod/Sql.pike,v retrieving revision 1.68 diff -u -r1.68 Sql.pike --- Sql.pike 30 Jul 2003 02:30:33 -0000 1.68 +++ Sql.pike 22 Oct 2003 13:46:49 -0000 @@ -28,6 +28,27 @@
//! @decl string quote(string s) //! Quote a string @[s] so that it can safely be put in a query. +//! +//! All input that is used in SQL-querys should be quoted to prevent +//! SQL injections. +//! +//! Consider this harmfull code: +//! @code +//! string my_input = "rob' OR name!='rob"; +//! string my_query = "DELETE FROM tblUsers WHERE name='"+my_input+"'"; +//! my_db->query(my_query); +//! @endcode +//! +//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@} +//! +//! Usually this is done - not by calling quote explicitly - but through +//! using a @[sprintf] like syntax +//! @code +//! string my_input = "rob' OR name!='rob"; +//! my_db->query("DELETE FROM tblUsers WHERE name=%s",my_input); +//! @endcode
function(string:string) quote = .sql_util.quote;
@@ -340,9 +361,20 @@ return ({sprintf(query,@args), b}); }
-//! Send an SQL query to the underlying SQL-server. The result is returned -//! as an array of mappings indexed on the name of the columns. -//! Returns 0 if the query didn't return any result (e.g. INSERT or similar). +//! Send an SQL query to the underlying SQL-server. +//! @returns +//! Returns one of the following on success: +//! @mixed +//! @type array(mapping(string:string)) +//! The result as an array of mappings indexed on the name +//! of the columns +//! @type zero +//! The value @expr{0@} (zero) if the query didn't return any +//! result (eg @tt{INSERT@} or similar). +//! @endmixed +//! +//! @throws +//! Throws an exception if the query fails. //! //! @param q //! Query to send to the SQL-server. This can either be a string with the @@ -359,8 +391,12 @@ //! the variable is used. //! //! @code -//! query("select foo from bar where gazonk=:baz", -//! ([":baz":"value"])) ) +//! mixed err = catch { +//! query("SELECT foo FROM bar WHERE gazonk=:baz", +//! ([":baz":"value"])); +//! }; +//! if(!intp(err)) +//! werror("An error occured."); //! @endcode //! //! Binary values (BLOBs) may need to be placed in multisets.
/ Peter Lundqvist (disjunkt)
Makes good sense.
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 16:04: Subject: Re: Proposal-patch for documentation of Sql.pike
+//! @returns
[...]
+//! @throws
[...]
//! @param q
Parameters should by convention be described before return values.
/ Henrik Grubbström (Lysator)
But it is quite a bit slower if I remember correctly.
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 06:31: Subject: Re: Proposal-patch for documentation of Sql.pike
You might want to add that the by far easiest way to avoid the problem is to use the 'sprintf' like feature of query (and big query).
As in:
query( "SELECT name FROM customers WHERE ident=%s", ident );
This will automatically do the quoting for you. The same goes for the :foo syntax.
/ Per Hedbor ()
slower than what? doing quoting manually?
does this imply that sprintf() in generall is slower than other methods?
greetings, martin.
slower than what? doing quoting manually?
Yes.
does this imply that sprintf() in generall is slower than other methods?
No.
/ Martin Nilsson (saturator)
Previous text:
2003-10-22 18:08: Subject: Re: Proposal-patch for documentation of Sql.pike
slower than what? doing quoting manually?
does this imply that sprintf() in generall is slower than other methods?
greetings, martin.
/ Brevbäraren
Yes, but it's not nessesary to mention that in the documentation. Also, it only matters if you do _lota_ of queries at once (50k+).
/ Per Hedbor ()
Previous text:
2003-10-22 15:47: Subject: Re: Proposal-patch for documentation of Sql.pike
But it is quite a bit slower if I remember correctly.
/ Martin Nilsson (saturator)
In the last episode (Oct 22), Peter Lundqvist (disjunkt) @ Pike (-) developers forum said:
Oh, BTW. I was asked to ask to explain SQL injections yesterday. Would this ammendment be superfluous in a pike manual?
+//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@}
You might want to also mention that in most cases it's cleaner to simply use bind variables, and much harder to screw up. Very rarely do you have to actually build a query string such that quote() is needed.
Two more nits:
1- The toplevel Sql description has an example of using %s printf syntax, but there's only an example of :bind syntax in the docs for query(). It'd be nice if both syntax examples were in the query() page.
2- The description for :bind substitution doesn't mention that you can just use "variable" in your mapping instead of ":variable", and I bet most people use the first style anyway.
How about two examples:
mapping m=([ ]); m->baz="value"; result=query("select foo from bar where gazonk=:baz", m);
result=query("select foo from bar where gazonk=%s", "value");
I'm not sure what you mean. Should the toplevel code example be extended or removed?
/ Peter Lundqvist (disjunkt)
Previous text:
2003-10-22 06:56: Subject: Re: Proposal-patch for documentation of Sql.pike
In the last episode (Oct 22), Peter Lundqvist (disjunkt) @ Pike (-) developers forum said:
Oh, BTW. I was asked to ask to explain SQL injections yesterday. Would this ammendment be superfluous in a pike manual?
+//! This type of problems can be avoided by quoting @tt{my_input@}. +//! @tt{my_input@} would then probably read something like +//! @i{rob' OR name!='rob@}
You might want to also mention that in most cases it's cleaner to simply use bind variables, and much harder to screw up. Very rarely do you have to actually build a query string such that quote() is needed.
Two more nits:
1- The toplevel Sql description has an example of using %s printf syntax, but there's only an example of :bind syntax in the docs for query(). It'd be nice if both syntax examples were in the query() page.
2- The description for :bind substitution doesn't mention that you can just use "variable" in your mapping instead of ":variable", and I bet most people use the first style anyway.
How about two examples:
mapping m=([ ]); m->baz="value"; result=query("select foo from bar where gazonk=:baz", m);
result=query("select foo from bar where gazonk=%s", "value");
-- Dan Nelson dnelson@allantgroup.com
/ Brevbäraren
pike-devel@lists.lysator.liu.se