CNIC Information System with Pakdata Cf In Pakistan
Sql abstract from_query
1. 23.08.14 - Page 1
Département
Office
SQL::Abstract::FromQuery
Building DB requests from Web queries
YAPC::EU::2014, Sofia
laurent.dami@justice.ge.ch
Etat de Genève, Pouvoir Judiciaire Département
Office
2. Power search : the "widget" way
Source: https://rt.cpan.org/Search/Build.html
3. Power search : the "parsed" way
Name : Smi*
Gender : M
Salary : > 4000
Job : ! programmer, analyst
Birth : BETWEEN 01.01.1970 AND 31.12.1990
Address: ! NULL
6. SQL::Abstract ('SQLA') : example
my $sqla = SQL::Abstract->new;
my ($sql, @bind) = $sqla->select(
$table_name,
[qw/col1 col2 col3/],
{ col1 => 'val1',
col2 => {-in => [qw/foo bar/]},
col3 => {-between => [qw/2012-01-01 2012-07-01/]},
col4 => {">" => 999},
col5 => {-like => 'foo%'},
},
[qw/col1 col2/],
);
# SELECT col1, col2, col3 FROM $table_name
# WHERE col1 = ? AND col2 IN (?, ?) AND col3 … etc
# ORDER BY col1, col2
7. Purpose
• generate SQL from Perl data structures
– direct from config or from user input
– avoid painful string manipulations with regex / join / etc.
• placeholders and bind values
– avoid datatype distinctions (strings / numbers /dates / etc.)
– avoid SQL injection
used by DBIx::Class, DBIx::DataModel, …
8. "Special operators" in SQLA
• support for user-defined SQL extensions. For ex :
– fulltext index
– multivalued columns
– case-insensitive
– LIKE / GLOB / etc.
• useful for DBMS-independent queries in apps
– the "special operator" translates to DBMS-specific syntax
{ col1 => {-contains => [qw/YAPC Sofia/]},
col2 => {-anyval => [12, 34, 56]},
col3 => {-glob => 'foo*'},
}
10. 23.08.14 - Page 1
Département
Office
SQLA, SQLAM are for programmers
what about users ?
SQL
Perl
datastructure
SQLA, SQLAMHTTP
query
SQLA::FromQuery
11. HTTP query
Name : Smi*
Gender : M
Salary : > 4000
Job : ! programmer, analyst
Birth : BETWEEN 01.01.1970 AND 31.12.1990
Address: ! NULL
12. Expected SQLA structure
{
Name => {-like => 'Smi%'},
Gender => 'M',
Salary => {'>' => 4000},
Job => {-not_in => [qw/programmer analyst/]},
Birth => {-between => [qw/1970-01-01 1990-12-31/]},
Address => {'<>' => undef},
}
SELECT * FROM people
WHERE Name LIKE 'Smi%'
AND Gender = 'M'
AND Salary > 4000
AND Job NOT IN ('programmer', 'analyst')
AND Birth BETWEEN 1970-01-01 AND 1990-12-31
AND Address IS NOT NULL
13. SYNOPSIS
my $parser = SQL::Abstract::FromQuery->new();
my $criteria = $parser->parse($http_query);
# $http_query is an object with a ->param() method
# .. or it can be just a hashref
my ($sql, @bind)
= $sqla->select($table, @cols, $criteria);
# or
my ($sql, @bind) = $sqlam->select(
-columns => @cols,
-from => $table,
-where => $criteria,
);
14. Options
my $parser = SQL::Abstract::FromQuery->new(
# additional components (optional)
-components => [qw/FR Oracle/],
# grammar rules for some specific fields (optional)
-fields => {
standard => [qw/field1 field2 .../],
bool => [qw/bool_field1/],
...
}
);
15. Components
• FR
– dates au format dd.mm.yyyy
– mots-clés en français (VRAI, FAUX, ENTRE, NUL, etc.)
– messages d'erreur en français
• Oracle
– queries on date and time
• ["to_date(?, '$date_format')", $date]
• ["to_date(?, '$time_format')", $date]
WHERE D_BIRTH > TO_DATE('DD.MM.YYYY', ?)
• Contains
– generate fulltext queries
• … (user-defined)
16. Field types : which grammar to apply
• Standard
– a plain value (number, string, date or time).
– a list of values, separated by ','.
– a negated value or list of values; negation is expressed by ! or != or - or
<>
– a comparison operator <=, <, >=, > followed by a plain value
– the special word NULL
– BETWEEN val1 AND val2
– boolean values YES, NO, TRUE or FALSE
• Restricted
– string / bool / date / … (user-defined)
23. Features
• flexible syntax for user input
– plain value
– list of values
– comparison operators
– patterns
– special constructs (BETWEEN, MATCH, etc.)
– Including SQLA "special ops"
• internationalization
• automate specific behaviours for some form fields
– data conversion
– inject special ops