-
package com.angrysprite.query {
-
-
import com.angrysprite.errors.QuerySetError;
-
-
public class QS {
-
-
protected var filterGroups:Object;
-
protected var filters:Array;
-
protected var excludes:Array;
-
protected var bindParameters:Object;
-
protected var parameterCount:Object;
-
protected var queryTerms:Array = [
-
'exact', // exact match "="
-
'iexact', // case insensitive match
-
'contains', // like match: col LIKE %parameter%
-
'icontains', // case insensitive like match: lower(col) LIKE %parameter% (SQLite LIKE is case insensitive)
-
'gt', // greater than match: col> parameter
-
'gte', // greater than or equal match: col>= parameter
-
'lt', // less than match: col <parameter
-
'lte', // less than or equal match: col <= parameter
-
'in', // in match: col IN (parameter1, parameter2, parameter3)
-
'startswith', // starts with match: col LIKE parameter%
-
'istartswith', // case insensitive starts with match: col LIKE parameter% (SQLite LIKE is case insensitive)
-
'endswith', // ends with match: col LIKE %parameter
-
'iendswith', // case insensitive ends with match: col LIKE %parameter (SQLite LIKE is case insensitive)
-
'isnull', // null match: col IS NULL
-
'notnull', // is not null match: col IS NOT NULL
-
//'range', //
-
//'year', //
-
//'month','day', //
-
//'search', //
-
//'regex', //
-
//'iregex', //
-
];
-
public function QS() {
-
filterGroups = {filters: [], excludes: []};
-
bindParameters = new Object();
-
parameterCount = new Object();
-
}
-
-
public function filter(filter:Array):QS {
-
for (var i:int = 0; i <filter.length; i++) {
-
filterGroups.filters.push(parseFilters(filter[i]));
-
}
-
return this;
-
}
-
-
public function exclude(filter:Array):QS {
-
for (var i:int = 0; i <filter.length; i++) {
-
filterGroups.excludes.push(parseFilters(filter[i]));
-
}
-
return this;
-
}
-
-
public function get parameters():Object {
-
return bindParameters;
-
}
-
-
public function output():String {
-
var sql:String = "";
-
var filters:Array = new Array();
-
var excludes:Array = new Array();
-
for (var filterIndex:int = 0; filterIndex <filterGroups.filters.length; filterIndex++) {
-
filters.push("(" + filterGroups.filters[filterIndex].join(" AND ") + ")");
-
}
-
for (var excludeIndex:int = 0; excludeIndex <filterGroups.excludes.length; excludeIndex++) {
-
excludes.push("(" + filterGroups.excludes[excludeIndex].join(" AND ") + ")");
-
}
-
if (filters.length> 0) {
-
sql += "(" + filters.join(" OR ") + ")";
-
if (excludes.length> 0) {
-
sql += " AND NOT (" + excludes.join(" OR ") + ")";
-
}
-
} else if (excludes.length> 0) {
-
sql += "NOT (" + excludes.join(" AND ") + ")";
-
}
-
return sql;
-
}
-
-
protected function parseFilters(filter:Object):Array {
-
var sqlArray:Array = new Array();
-
for (var term:String in filter) {
-
var sql:String = "";
-
if (term.indexOf("__") == -1) {
-
var bindParameter:String = getBindParameterKey(term);
-
setBindParameter(bindParameter, filter[term]);
-
sql += term + " = " + bindParameter;
-
} else {
-
sql += parseTerm(term, filter[term]);
-
}
-
sqlArray.push(sql);
-
}
-
return sqlArray;
-
}
-
-
protected function parseTerm(term:String, value:Object):String {
-
var tokens:Array = term.split("__");
-
if (tokens.length != 2) {
-
throw new QuerySetError("Invalid number of query terms");
-
}
-
var col:String = tokens[0];
-
var term:String = tokens[1];
-
var sql:String = '';
-
var bindParameter:String = getBindParameterKey(col);
-
setBindParameter(bindParameter, value);
-
switch (term) {
-
case 'exact':
-
sql = col + " = " + bindParameter;
-
break;
-
case 'iexact':
-
sql = "LOWER(" + col + ") = LOWER(" + bindParameter + ")";
-
break;
-
case 'contains':
-
sql = col + " LIKE " + bindParameter;
-
break;
-
case 'icontains':
-
sql = col + " LIKE " + bindParameter;
-
break;
-
case 'gt':
-
sql = col + "> " + bindParameter;
-
break;
-
case 'gte':
-
sql = col + ">= " + bindParameter;
-
break;
-
case 'lt':
-
sql = col + " <" + bindParameter;
-
break;
-
case 'lte':
-
sql = col + ">= " + bindParameter;
-
break;
-
case 'in':
-
sql = col + " IN (" + bindParameter + ")";
-
break;
-
case 'startswith':
-
sql = col + " LIKE " + bindParameter + "%";
-
break;
-
case 'istartswith':
-
sql = col + " LIKE " + bindParameter + "%";
-
break;
-
case 'endswith':
-
sql = col + " LIKE %" + bindParameter;
-
break;
-
case 'iendswith':
-
sql = col + " LIKE %" + bindParameter;
-
break;
-
case 'isnull':
-
sql = col + " IS NULL";
-
break;
-
case 'notnull':
-
sql = col + " IS NOT NULL";
-
break;
-
default:
-
throw new QuerySetError('Invalid query term: ' + term);
-
break;
-
}
-
return sql;
-
}
-
-
protected function getBindParameterKey(bindParameter:String):String {
-
if (parameterCount[bindParameter]) {
-
parameterCount[bindParameter]++;
-
} else {
-
parameterCount[bindParameter] = 1;
-
}
-
return ":" + bindParameter + parameterCount[bindParameter].toString();
-
}
-
-
protected function setBindParameter(key:String, value:Object):void {
-
if (typeof(value) == 'Array') {
-
var a:Array = value as Array;
-
bindParameters[key] = a.join(', ');
-
}
-
bindParameters[key] = value;
-
}
-
}
-
}
-
-
/**
-
*
-
* var qs = new QS().filter({name__iexact: 'adsf', notnull__insider_id: '', gt__age: 18}).exclude({age: 21});
-
*
-
* ...WHERE (LOWER(name) = LOWER(:name1) AND insider_id IS NOT NULL AND age> :age1) AND NOT (age = :age2);
-
* bindParameters = {
-
* ':name1': 'asdf',
-
* ':age1': 18,
-
* ':age2': 21
-
* }
-
*
-
**/