docs.roxen.comBack to normal mode
DocsRoxenWebServer 3.3TutorialsDatabase Tutorial
Copyright © 2004, Roxen Internet Software
Suggestions, comments & compliments
manuals@roxen.com

Quoting

As better explained in the Conditions page, constants (especially string constants) must be quoted in SQL. How the quoting must actually be composed will be explained later, now we'll introduce the facilities Pike and RXML offer to perform the quoting operation. The operation is server-transparent (that is, it adapts to the various servers' quoting schemes.

Pike

The Pike solution is pretty straightforward: quoting is handled via the Sql.sql->quote(string) method. It returns a string, which is the quoted argument.

It is supposed to be used when assembling a query, and is strongly encouraged to use it whenever a query is interactively built from some user's input: a malformed input could break the query by causing an SQL syntax error. It's useless to say that it could also be used maliciously, to completely alter the query structure, thus giving access to the lowlevel database contents.

Let's write a small interactive Pike application which prints the background for user-entered countries.


#!/usr/local/bin/pike
#define DATABASE "mysql://user:password@localhost/sample"

//sample program: find out some country's background information
int main() {
  object readline=Stdio.Readline();               //used for interactive input
  object db=Sql.sql(DATABASE);                    //connect to the DB
  readline->set_prompt("Country (q to quit)> ");
  string input;
  array(mapping(string:mixed)) result;
  while (input=readline->read()) {                //while !eof
    if (input=="q") break;                        //exit on "q"
    //query-building. I like to use sprintf to build parametric queries, as
    //it shows the query structure in the source (increased readability),
    //as well as allowing easier control over the SQL statement
    string query=sprintf("select background from countries, ids "
                         "where countries.country=ids.code and "
                         "name='%s'",
                         db->quote(input)         //notice the quoting!
                         );
    result=db->query(query);
    if (!sizeof(result)) {
      write("No such country in the database\n");
      continue;
    }
    write(result[0]->background+"\n");
  }
}

RXML

There are two occasions in which you'll want to do quoting in RXML when performing SQL-related operations: parametric query building and results quoting (for instance to populate a selection list). In most cases the RXML parser tries to do the "sensible" thing, but sometimes that's just not enough, and you'll need to manually override the parser's "opinion".

On production systems, any degree of freedom is a risk: on such systems it is thus recommended to always specify the encodingq, as it will lessen the probability of errors, failures or security vulnerabilities.

Parametric Queries

You can use the standard entity-syntax to build parametric queries: just use entities in your query strings. Make sure to force the sql-encoding, or you might head into trouble.

The example beneath does the same task as the above pike application using RXML. It performs both of the encoding operations: results-encoding to populate a selection list and variable encoding to perform a parametric query:


<form method="post" action="&page.url;">
Select a country: <select name="country">
<emit source="sql"
      query="SELECT name,code FROM ids,countries
             WHERE countries.country=ids.code
             ORDER BY name">
<option value="&_.code;">&_.name;</option></sqloutput>
</select>
<input type="submit">
</form>

<if variable='form.country'>
<sqltable host="mysql://user:password@localhost/sample"
  query="SELECT name,background FROM countries,ids
          WHERE countries.country=ids.code
            AND ids.code='&form.country:sql;'"/>
</if>