1 package DBIx::Class::SQLMaker::DateOps;
4 Class::Accessor::Grouped
6 __PACKAGE__->mk_group_accessors (simple => qw/datetime_parser/);
7 use Carp::Clan qw/^DBIx::Class|^SQL::Abstract|^Try::Tiny/;
8 use Sub::Name 'subname';
10 sub _where_op_CONVERT_DATETIME {
12 my ($op, $rhs) = splice @_, -2;
13 croak "-$op takes a DateTime only" unless ref $rhs && $rhs->isa('DateTime');
15 # in case we are called as a top level special op (no '=')
18 $rhs = $self->datetime_parser->format_datetime($rhs);
21 ($lhs || $self->{_nested_func_lhs} || undef),
27 $self->_convert($self->_quote($lhs)) . ' = ' . $self->_convert('?'),
37 sub _unsupported_date_extraction {
38 "date part extraction not supported for part \"$_[1]\" with database \"$_[2]\""
41 sub _unsupported_date_adding {
42 "date part adding not supported for part \"$_[1]\" with database \"$_[2]\""
45 sub _unsupported_date_diff {
46 "date diff not supported for part \"$_[1]\" with database \"$_[2]\""
49 sub _datetime_sql { die 'date part extraction not implemented for this database' }
51 sub _datetime_diff_sql { die 'date diffing not implemented for this database' }
52 sub _datetime_add_sql { die 'date adding not implemented for this database' }
54 sub _where_op_GET_DATETIME {
69 croak 'args to -dt_get must be an arrayref' unless ref $vals eq 'ARRAY';
70 croak 'first arg to -dt_get must be a scalar' unless !ref $vals->[0];
72 my $part = $vals->[0];
75 my ($sql, @bind) = $self->_SWITCH_refkind($val, {
77 return ($self->_convert('?'), $self->_bindtype($k, $val) );
83 my ($sql, @bind) = @$$val;
84 $self->_assert_bindval_matches_bindtype(@bind);
88 my $method = $self->_METHOD_FOR_refkind("_where_hashpair", $val);
89 $self->$method('', $val);
93 return $self->_datetime_sql($part, $sql), @bind;
96 for my $part (qw(month day year hour minute second)) {
98 my $name = '_where_op_GET_DATETIME_' . uc($part);
99 *{$name} = subname "DBIx::Class::SQLMaker::DateOps::$name", sub {
101 my ($op, $rhs) = splice @_, -2;
105 return $self->_where_op_GET_DATETIME($op, $lhs, [$part, $rhs])
109 sub _where_op_DATETIME_NOW {
124 croak "args to -$op must be an arrayref" unless ref $vals eq 'ARRAY';
125 if (!exists $vals->[0]) {
126 return $self->_datetime_now_sql()
127 } elsif ($vals->[0] eq 'system') {
129 return $self->_where_op_CONVERT_DATETIME('dt', DateTime->now);
131 croak "first arg to -$op must be a 'system' or non-existant"
135 sub _reorder_add_datetime_vars {
136 my ($self, $amount, $date) = @_;
138 return ($amount, $date);
141 sub _where_op_ADD_DATETIME {
156 croak "args to -$op must be an arrayref" unless ref $vals eq 'ARRAY';
157 croak "first arg to -$op must be a scalar" unless !ref $vals->[0];
158 croak "-$op must have two more arguments" unless scalar @$vals == 3;
160 my ($part, @rest) = @$vals;
162 my $placeholder = $self->_convert('?');
164 my (@all_sql, @all_bind);
165 foreach my $val ($self->_reorder_add_datetime_vars(@rest)) {
166 my ($sql, @bind) = $self->_SWITCH_refkind($val, {
168 return ($placeholder, $self->_bindtype($k, $val) );
174 my ($sql, @bind) = @$$val;
175 $self->_assert_bindval_matches_bindtype(@bind);
176 return ($sql, @bind);
179 my $method = $self->_METHOD_FOR_refkind("_where_hashpair", $val);
180 $self->$method('', $val);
184 push @all_bind, @bind;
187 return $self->_datetime_add_sql($part, $all_sql[0], $all_sql[1]), @all_bind
190 sub _where_op_DIFF_DATETIME {
205 croak 'args to -dt_diff must be an arrayref' unless ref $vals eq 'ARRAY';
206 croak 'first arg to -dt_diff must be a scalar' unless !ref $vals->[0];
207 croak '-dt_diff must have two more arguments' unless scalar @$vals == 3;
209 my ($part, @val) = @$vals;
210 my $placeholder = $self->_convert('?');
212 my (@all_sql, @all_bind);
213 foreach my $val (@val) {
214 my ($sql, @bind) = $self->_SWITCH_refkind($val, {
216 return ($placeholder, $self->_bindtype($k, $val) );
222 my ($sql, @bind) = @$$val;
223 $self->_assert_bindval_matches_bindtype(@bind);
224 return ($sql, @bind);
227 my $method = $self->_METHOD_FOR_refkind("_where_hashpair", $val);
228 $self->$method('', $val);
232 push @all_bind, @bind;
235 return $self->_datetime_diff_sql($part, $all_sql[0], $all_sql[1]), @all_bind