}
sub castdate {
- my ($value, $gte, $lte) = @_;
+ my ($value, $gte, $lte, $between) = @_;
my $op = "=";
$op = ">=" if $gte;
$op = "<=" if $lte;
+ $op = "between" if $between;
# avoid transforming a date if the match value is NULL.
return {'=' => undef} if $op eq '=' and not $value;
};
# castdate not supported for acqlia fields: they're all type text
- my ($k, $v, $fuzzy, $between, $not) = breakdown_term($unit);
+ my ($k, $v, $fuzzy, $between, $not, $starts, $ends) = breakdown_term($unit);
my $point = $subquery->{"where"}->{"-and"};
my $term_clause;
if ($fuzzy and not ref $v) {
push @$point, {"attr_value" => {"ilike" => "%" . $v . "%"}};
+ } elsif ($starts and not ref $v) {
+ push @$point, {"attr_value" => {"ilike" => $v . "%"}};
+ } elsif ($ends and not ref $v) {
+ push @$point, {"attr_value" => {"ilike" => "%" . $v}};
} elsif ($between and could_be_range($v)) {
push @$point, {"attr_value" => {"between" => $v}};
} elsif (check_1d_max($v)) {
foreach my $unit (@$acqlia) {
# castdate not supported for acqlia fields: they're all type text
- my ($k, $v, $fuzzy, $between, $not) = breakdown_term($unit);
+ my ($k, $v, $fuzzy, $between, $not, $starts, $ends) = breakdown_term($unit);
my $term_clause;
if ($fuzzy and not ref $v) {
$term_clause = {
"attr_value" => {"ilike" => "%" . $v . "%"}
}
};
+ } elsif ($starts and not ref $v) {
+ $term_clause = {
+ "-and" => {
+ "definition" => $k,
+ "attr_value" => {"ilike" => $v . "%"}
+ }
+ };
+ } elsif ($ends and not ref $v) {
+ $term_clause = {
+ "-and" => {
+ "definition" => $k,
+ "attr_value" => {"ilike" => "%" . $v}
+ }
+ };
} elsif ($between and could_be_range($v)) {
$term_clause = {
"-and" => {
$term->{"__fuzzy"} ? 1 : 0,
$term->{"__between"} ? 1 : 0,
$term->{"__not"} ? 1 : 0,
+ $term->{"__starts"} ? 1 : 0,
+ $term->{"__ends"} ? 1 : 0,
$term->{"__castdate"} ? 1 : 0,
$term->{"__gte"} ? 1 : 0,
- $term->{"__lte"} ? 1 : 0
+ $term->{"__lte"} ? 1 : 0,
+ $term->{"__age"} ? 1 : 0,
);
}
$outer_clause->{$conj} = [] unless $outer_clause->{$conj};
foreach my $unit (@{$terms->{$class}}) {
my $special_clause;
- my ($k, $v, $fuzzy, $between, $not, $castdate, $gte, $lte) =
+ my ($k, $v, $fuzzy, $between, $not, $starts, $ends, $castdate, $gte, $lte, $age) =
breakdown_term($unit);
my $term_clause;
- if ($fuzzy and not ref $v) {
+ if ($age and not ref $v) { # $v is expected to be parsed as an interval
+ $v =~ s/^\s*//;
+
+ my $op = $gte ? '>=' : '<=';
+ $term_clause = {$k = {$op => {transform => 'age', params => ['now'], value => '-' . $v}}};
+
+ # !!! NOTE: we invert $not because we have to compare to a /negative/
+ # interval, due to json_query restiction on function parameter order for
+ # transformed fields, so we flip the comparison. Alternatively we could
+ # swap the GTE and LTE operators, but that would make the query harder
+ # to read and make diagnosing issues much more difficult.
+ $not = $not ? 0 : 1;
+
+ } elsif ($starts and not ref $v) {
+ $term_clause = {$k => {"ilike" => $v . "%"}};
+ } elsif ($ends and not ref $v) {
+ $term_clause = {$k => {"ilike" => "%" . $v}};
+ } elsif ($fuzzy and not ref $v) {
$term_clause = {$k => {"ilike" => "%" . $v . "%"}};
} elsif ($between and could_be_range($v)) {
- $term_clause = {$k => {"between" => $v}};
+ if ($castdate) {
+ $v = castdate($v, 0, 0, $between);
+ $term_clause = {$k => $v};
+ } else {
+ $term_clause = {$k => {between => $v}};
+ }
} elsif (check_1d_max($v)) {
if ($castdate) {
- $v = castdate($v, $gte, $lte) if $castdate;
+ $v = castdate($v, $gte, $lte);
} elsif ($gte or $lte) {
my $op = $gte ? '>=' : '<=';
$v = {$op => $v};