now expressions with database fields on both sides of the operator are compiled into Closures and hence are valid

This commit is contained in:
Wiesner András 2024-09-26 12:15:14 +02:00
parent d78b636212
commit 5b2cc0b8f4

View File

@ -1,5 +1,14 @@
<?php
class FieldName {
public string $fieldName;
public function __construct(string $fieldName)
{
$this->fieldName = $fieldName;
}
}
class ExpressionBuilder
{
// Automatic typecast.
@ -11,13 +20,15 @@ class ExpressionBuilder
} else { // is it a float?
return (double)$rval;
}
} else { // it's a string
} else if (str_starts_with($rval, '"') && str_ends_with($rval, '"')){ // it's a string
return substr($rval, 1, strlen($rval) - 2); // strip leading and trailing quotes
} else { // it must be a column name
return new FieldName($rval);
}
}
// Divide expression into operands and operators.
static function splitCriterion(string $crstr): array
static function splitCriterion(string $crstr): array|Closure
{
preg_match("/([<>=!]+|LIKE|NOT LIKE|IN|NOT IN|CONTAINS|NOT CONTAINS|BETWEEN|NOT BETWEEN|EXISTS)/", $crstr, $matches, PREG_OFFSET_CAPTURE);
@ -44,7 +55,38 @@ class ExpressionBuilder
$right = self::automaticTypecast($right);
}
return [$left, $op, $right];
// handle "default" criteria and closures
if (is_a($right, FieldName::class)) { // field name
return function($a) use ($left, $right, $op): bool {
$X = &$a[$left];
$Y = &$a[$right->fieldName];
switch ($op) {
case "=": {
return $X == $Y;
}
case "!=": {
return $X != $Y;
}
case "<": {
return $X < $Y;
}
case ">": {
return $X > $Y;
}
case "<=": {
return $X <= $Y;
}
case ">=": {
return $X >= $Y;
}
default: {
return false;
}
}
};
} else { // default critera
return [$left, $op, $right];
}
}
// Build SleekDB query expression. Processes encapsulated expressions recursively as well.