<?php
/**
* Short Query Notation Library
*
* SQN is a small library that allows you to write
* convention based SQL queries using a short notation.
* SQL is a very flexible and powerful language. Since SQL
* does not rely on assumptions you have to specify a lot.
* The SQN-library uses some basic assumptions regarding
* naming conventions and in return it gives you a shorter notation.
*
* Usage:
*
* <code>
* R::sqn('shop<product<price'); - left joins shop, product and price
* R::sqn('book<<tag'); - doubly left joins book, and tag using book_tag
* </code>
*
* SQN assumes id fields follow the following conventions:
*
* Primary key: id
* Foreign key: {table}_id
* No table prefix.
*
* SQN can also generate additional aliases:
*
* <code>
* R::sqn( ..., 'area/x,y;place/x,y' ) - area_x area_y place_x place_y
* </code>
*
* @author Gabor de Mooij
* @license BSD/GPLv2
*
* @copyright
* copyright (c) G.J.G.T. (Gabor) de Mooij
* This source file is subject to the BSD License that is bundled
* with this source code in the file license.txt.
*/
R::ext('sqn', function( $query, $aliases = null, $q = '`' ) {
$map = [
'|' => 'INNER JOIN',
'||' => 'INNER JOIN',
'>' => 'RIGHT JOIN',
'>>' => 'RIGHT JOIN',
'<' => 'LEFT JOIN',
'<<' => 'LEFT JOIN',
];
$select = [];
$from = '';
$joins = [];
$prev = '';
$ents = preg_split( '/[^\w_]+/', $query );
$tokens = preg_split( '/[\w_]+/', $query );
array_pop($tokens);
foreach( $ents as $i => $ent ) {
$select[] = " {$q}{$ent}{$q}.* ";
if (!$i) {
$from = $ent;
$prev = $ent;
continue;
}
if ( $tokens[$i] == '<' || $tokens[$i] == '>' || $tokens[$i] == '|') {
$join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$ent}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
}
if ( $tokens[$i] == '<<' || $tokens[$i] == '>>' || $tokens[$i] == '||') {
$combi = [$prev, $ent];
sort( $combi );
$combi = implode( '_', $combi );
$select[] = " {$q}{$combi}{$q}.* ";
$join[] = " {$map[$tokens[$i]]} {$q}{$combi}{$q} ON {$q}{$combi}{$q}.{$prev}_id = {$q}{$prev}{$q}.id ";
$join[] = " {$map[$tokens[$i]]} {$q}{$ent}{$q} ON {$q}{$combi}{$q}.{$ent}_id = {$q}{$ent}{$q}.id ";
}
$prev = $ent;
}
if (!is_null($aliases)) {
$aliases = explode(';', $aliases);
foreach($aliases as $alias) {
list($table, $cols) = explode('/', $alias);
$cols = explode(',', $cols);
foreach($cols as $col) {
$select[] = " {$q}{$table}{$q}.{$q}{$col}{$q} AS {$q}{$table}_{$col}{$q} ";
}
}
}
$selectSQL = implode( ",\n", $select );
$joinSQL = implode( "\n", $join );
return "SELECT{$selectSQL}\n FROM {$q}{$from}{$q}\n{$joinSQL}";
});
|