| 1 |
8 |
ahitrov@rambler.ru |
package SQL::CommonFilters; |
| 2 |
|
|
|
| 3 |
|
|
use strict; |
| 4 |
|
|
use SQL::Common; |
| 5 |
|
|
use Contenido::Globals; |
| 6 |
|
|
|
| 7 |
|
|
########### FILTERS DESCRIPTION #################################################################################### |
| 8 |
|
|
sub _status_filter { |
| 9 |
|
|
my ($self, %opts)=@_; |
| 10 |
|
|
return undef unless ( exists($opts{status}) ); |
| 11 |
|
|
return &SQL::Common::_generic_int_filter('d.status', $opts{status}); |
| 12 |
|
|
} |
| 13 |
|
|
|
| 14 |
|
|
sub _class_filter { |
| 15 |
|
|
my ($self, %opts)=@_; |
| 16 |
|
|
return undef unless ( exists($opts{class}) ); |
| 17 |
|
|
return &SQL::Common::_generic_text_filter('d.class', $opts{class}); |
| 18 |
|
|
} |
| 19 |
|
|
|
| 20 |
|
|
sub _in_id_filter { |
| 21 |
|
|
my ($self, %opts)=@_; |
| 22 |
|
|
return undef unless ( exists($opts{in_id}) ); |
| 23 |
|
|
return &SQL::Common::_generic_int_filter('d.id', $opts{in_id}); |
| 24 |
|
|
} |
| 25 |
|
|
|
| 26 |
|
|
sub _id_filter { |
| 27 |
|
|
my ($self, %opts)=@_; |
| 28 |
|
|
return undef unless ( exists($opts{id}) ); |
| 29 |
|
|
return &SQL::Common::_generic_int_filter('d.id', $opts{id}); |
| 30 |
|
|
} |
| 31 |
|
|
|
| 32 |
|
|
sub _sfilter_filter { |
| 33 |
|
|
my ($self, %opts)=@_; |
| 34 |
|
|
return undef unless ( exists($opts{sfilter}) ); |
| 35 |
|
|
return &SQL::Common::_generic_intarray_filter('d.sections', $opts{sfilter}); |
| 36 |
|
|
} |
| 37 |
|
|
|
| 38 |
|
|
sub _name_filter { |
| 39 |
|
|
my ($self, %opts)=@_; |
| 40 |
|
|
return undef unless ( exists($opts{name}) ); |
| 41 |
|
|
return &SQL::Common::_generic_name_filter('d.name', $opts{name}, 0, \%opts); |
| 42 |
|
|
} |
| 43 |
|
|
|
| 44 |
|
|
|
| 45 |
|
|
sub _datetime_filter { |
| 46 |
|
|
my ($self, %opts)=@_; |
| 47 |
|
|
return undef unless ( exists($opts{datetime}) ); |
| 48 |
|
|
if ($opts{datetime} eq 'future') { |
| 49 |
|
|
return " ($opts{usedtime} >= CURRENT_TIMESTAMP) "; |
| 50 |
|
|
} elsif ($opts{datetime} eq 'past') { |
| 51 |
|
|
return " ($opts{usedtime} <= CURRENT_TIMESTAMP) "; |
| 52 |
|
|
} elsif ($opts{datetime} eq 'today') { |
| 53 |
|
|
return " ($opts{usedtime}>=CURRENT_DATE AND $opts{usedtime}<CURRENT_DATE+'1 day'::INTERVAL) "; |
| 54 |
|
|
} elsif (ref $opts{'datetime'} && ref $opts{'datetime'} eq 'HASH') { |
| 55 |
|
|
my ($type, $time) = %{$opts{'datetime'}}; |
| 56 |
|
|
if ($time =~ /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(?:\.\d+)?$/ && $type eq 'after') { |
| 57 |
|
|
return " ($opts{usedtime} >= '$time') "; |
| 58 |
|
|
} elsif ($time =~ /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}(?:\.\d+)?$/ && $type eq 'before') { |
| 59 |
|
|
return " ($opts{usedtime} <= '$time') "; |
| 60 |
|
|
} else { |
| 61 |
|
|
warn "Contenido Warning: Неверно задан фильтр datetime='$opts{datetime}' допустимые значения: 'future','past','today', {['after' || 'before'] => [timestamp]}\n"; |
| 62 |
|
|
return ' FALSE '; |
| 63 |
|
|
} |
| 64 |
|
|
return " ($opts{usedtime}>=CURRENT_DATE AND $opts{usedtime}<CURRENT_DATE+'1 day'::INTERVAL) "; |
| 65 |
|
|
|
| 66 |
|
|
} else { |
| 67 |
|
|
warn "Contenido Warning: Неверно задан фильтр datetime='$opts{datetime}' допустимые значения: 'future','past','today', {['after' || 'before'] => [timestamp]}\n"; |
| 68 |
|
|
return ' FALSE '; |
| 69 |
|
|
} |
| 70 |
|
|
} |
| 71 |
|
|
|
| 72 |
|
|
sub _date_equal_filter { |
| 73 |
|
|
my ($self, %opts)=@_; |
| 74 |
|
|
return undef unless ( exists($opts{date_equal}) ); |
| 75 |
|
|
|
| 76 |
|
|
# - запрос на совпадение даты / YYYY-MM-DD |
| 77 |
|
|
if ( $opts{date_equal} =~ /^\d{4}-\d{2}-\d{2}$/) { |
| 78 |
|
|
return " ($opts{usedtime}>=?::TIMESTAMP AND $opts{usedtime}<?::TIMESTAMP+'1 day'::INTERVAL) ", [$opts{date_equal},$opts{date_equal}]; |
| 79 |
|
|
} else { |
| 80 |
|
|
warn "Contenido Warning: Неверно задан формат даты '$opts{date_equal}'. Правильный формат - YYYY-MM-DD."; |
| 81 |
|
|
return ' FALSE '; |
| 82 |
|
|
} |
| 83 |
|
|
} |
| 84 |
|
|
|
| 85 |
|
|
sub _date_filter { |
| 86 |
|
|
my ($self, %opts)=@_; |
| 87 |
|
|
return undef unless ( exists($opts{date}) ); |
| 88 |
|
|
# - запрос на извлечение документов из интервала дат... |
| 89 |
|
|
if ( ref($opts{date}) eq 'ARRAY' and scalar(@{$opts{date}})==2 ) { |
| 90 |
|
|
#pure dates |
| 91 |
|
|
if ( ($opts{date}->[0] =~ /^\d{4}-\d{2}-\d{2}$/) and ($opts{date}->[1] =~ /^\d{4}-\d{2}-\d{2}$/) ) { |
| 92 |
|
|
return " ($opts{usedtime}>=?::TIMESTAMP AND $opts{usedtime}<?::TIMESTAMP+'1 day'::INTERVAL) ", [$opts{date}->[0],$opts{date}->[1]]; |
| 93 |
|
|
#datetimes |
| 94 |
|
|
} elsif ( ($opts{date}->[0] =~ /^\d{4}-\d{2}-\d{2}/) && ($opts{date}->[1] =~ /^\d{4}-\d{2}-\d{2}/) ) { |
| 95 |
|
|
return " ($opts{usedtime}>=? AND $opts{usedtime}<=?) ", [$opts{date}->[0],$opts{date}->[1]]; |
| 96 |
|
|
} else { |
| 97 |
|
|
warn "Contenido Warning: Неверно задан формат даты для параметра date. Это должен быть массив с двумя элементами типа YYYY-MM-DD или YYYY-MM-DD HH:MM:SS. ['$opts{date}->[0]', '$opts{date}->[1]']\n"; |
| 98 |
|
|
return ' FALSE '; |
| 99 |
|
|
} |
| 100 |
|
|
} else { |
| 101 |
|
|
warn "Contenido Warning: Неверно задан формат даты для параметра date. Это должен быть массив с двумя элементами типа YYYY-MM-DD или YYYY-MM-DD HH:MM:SS."; |
| 102 |
|
|
return ' FALSE '; |
| 103 |
|
|
} |
| 104 |
|
|
} |
| 105 |
|
|
|
| 106 |
|
|
sub _class_excludes_filter { |
| 107 |
|
|
my ($self, %opts)=@_; |
| 108 |
|
|
return undef unless ( exists($opts{class_excludes}) ); |
| 109 |
|
|
return &SQL::Common::_generic_text_filter('d.class', $opts{class_excludes}, 'NEGATION'); |
| 110 |
|
|
} |
| 111 |
|
|
|
| 112 |
|
|
sub _s_filter { |
| 113 |
|
|
my ($self, %opts) = @_; |
| 114 |
|
|
return undef unless ( exists($opts{s}) ); |
| 115 |
|
|
|
| 116 |
|
|
if ($opts{dive}) { |
| 117 |
|
|
my @all_childs = @{$opts{all_childs}}; |
| 118 |
|
|
# - если задан параметр include_parent, то включим в выборку корень... |
| 119 |
|
|
# По умолчанию выключен... |
| 120 |
|
|
push (@all_childs, $opts{s}) if ($opts{include_parent}); |
| 121 |
|
|
|
| 122 |
|
|
return &SQL::Common::_generic_intarray_filter('d.sections', \@all_childs, \%opts); |
| 123 |
|
|
} else { |
| 124 |
|
|
return &SQL::Common::_generic_intarray_filter('d.sections', $opts{s}, \%opts); |
| 125 |
|
|
} |
| 126 |
|
|
} |
| 127 |
|
|
|
| 128 |
|
|
|
| 129 |
|
|
sub _previous_days_filter { |
| 130 |
|
|
my ($self, %opts)=@_; |
| 131 |
|
|
return undef unless ( exists($opts{previous_days}) ); |
| 132 |
|
|
# - запрос на все данных из заданных последних дней... |
| 133 |
|
|
if ($opts{previous_days} =~ /^\d+$/) { |
| 134 |
|
|
return " $opts{usedtime} >= (CURRENT_DATE - ?::interval)::TIMESTAMP ", "$opts{previous_days} DAYS"; |
| 135 |
|
|
} else { |
| 136 |
|
|
warn "Contenido Warning: Неверно задан формат дней для параметра previous_days. Это должно быть число дней\n"; |
| 137 |
|
|
return ' FALSE '; |
| 138 |
|
|
} |
| 139 |
|
|
} |
| 140 |
|
|
|
| 141 |
|
|
sub _previous_time_filter { |
| 142 |
|
|
my ($self, %opts)=@_; |
| 143 |
|
|
return undef unless exists $opts{previous_time}; |
| 144 |
|
|
if ($opts{previous_time} =~ /\D/) { |
| 145 |
|
|
warn "Contenido Warning: Неверно задано кол-во для параметра previous_time.\n"; |
| 146 |
|
|
return ' FALSE '; |
| 147 |
|
|
} else { |
| 148 |
|
|
return "$opts{usedtime} >= (NOW() - ?::interval)::TIMESTAMP ", ($opts{previous_time} . ' ' . ($opts{previous_time_units} || 'HOURS')); |
| 149 |
|
|
} |
| 150 |
|
|
} |
| 151 |
|
|
|
| 152 |
|
|
sub _prev_to_filter { |
| 153 |
|
|
my ($self, %opts)=@_; |
| 154 |
|
|
return undef unless ( exists $opts{prevto} ); |
| 155 |
|
|
my ($wheres, $values) = ([],[]); |
| 156 |
|
|
my $field = exists $opts{use_id} ? 'id' : exists $opts{use_ctime} ? 'ctime' : exists $opts{use_mtime} ? 'mtime' : 'dtime'; |
| 157 |
|
|
push @$wheres, " d.$field < ? "; |
| 158 |
|
|
if ( ref $opts{prevto} ) { |
| 159 |
|
|
my $ctime = $opts{prevto}; |
| 160 |
|
|
push @$values, $ctime->ymd('-').' '.$ctime->hms.'.'.$ctime->nanosecond; |
| 161 |
|
|
} else { |
| 162 |
|
|
push @$values, $opts{prevto}; |
| 163 |
|
|
} |
| 164 |
|
|
return ($wheres, $values); |
| 165 |
|
|
} |
| 166 |
|
|
|
| 167 |
|
|
sub _next_to_filter { |
| 168 |
|
|
my ($self, %opts)=@_; |
| 169 |
|
|
return undef unless ( exists $opts{nextto} ); |
| 170 |
|
|
my ($wheres, $values) = ([],[]); |
| 171 |
|
|
my $field = exists $opts{use_id} ? 'id' : exists $opts{use_ctime} ? 'ctime' : exists $opts{use_mtime} ? 'mtime' : 'dtime'; |
| 172 |
|
|
push @$wheres, " d.$field > ? "; |
| 173 |
|
|
if ( ref $opts{nextto} ) { |
| 174 |
|
|
my $ctime = $opts{nextto}; |
| 175 |
|
|
push @$values, $ctime->ymd('-').' '.$ctime->hms.'.'.$ctime->nanosecond; |
| 176 |
|
|
} else { |
| 177 |
|
|
push @$values, $opts{nextto}; |
| 178 |
|
|
} |
| 179 |
|
|
return ($wheres, $values); |
| 180 |
|
|
} |
| 181 |
|
|
|
| 182 |
|
|
sub _excludes_filter { |
| 183 |
|
|
my ($self,%opts)=@_; |
| 184 |
|
|
return undef unless ( exists($opts{excludes}) ); |
| 185 |
|
|
return &SQL::Common::_generic_int_filter('d.id', $opts{excludes}, 'NEGATION'); |
| 186 |
|
|
} |
| 187 |
|
|
|
| 188 |
|
|
sub _auto_filter { |
| 189 |
|
|
my ( $self, %opts ) = @_; |
| 190 |
|
|
my @exclude = qw( order_by limit offset no_limit count ids light hash_by return_mode ); |
| 191 |
|
|
my $sql; |
| 192 |
|
|
|
| 193 |
|
|
my @wheres; |
| 194 |
|
|
my @binds; |
| 195 |
|
|
my @joins; |
| 196 |
|
|
|
| 197 |
|
|
my ( $struct, $query_table ); |
| 198 |
|
|
|
| 199 |
|
|
if ( $opts{join} ) { |
| 200 |
|
|
|
| 201 |
|
|
if ( !$opts{join}->can('class_table') || !$opts{join}->class_table()->can('db_table') ) { |
| 202 |
|
|
warn "Contenido Warning (_auto_filter): Не могу получить имя таблицы для \"склейки\"!\n"; |
| 203 |
|
|
return (undef); |
| 204 |
|
|
} |
| 205 |
|
|
$query_table = $opts{join}->class_table()->db_table(); |
| 206 |
|
|
$struct = $opts{join}->class_table()->required_hash(); |
| 207 |
|
|
|
| 208 |
|
|
if ( $opts{field} && !$struct->{ $opts{field} } ) { |
| 209 |
|
|
warn "Contenido Warning (_auto_filter): В таблице $query_table нет поля ".$opts{field}."!\n"; |
| 210 |
|
|
return (undef); |
| 211 |
|
|
} |
| 212 |
|
|
|
| 213 |
|
|
push @joins, ' join '.$query_table.' on '.$query_table.'.'.( $opts{field} ? $opts{field} : 'id' ).' = '.$opts{__join_table}.'.'.$opts{__join_field}.' '; |
| 214 |
|
|
|
| 215 |
|
|
} else { |
| 216 |
|
|
$struct = $self->required_hash(); |
| 217 |
|
|
$query_table = 'd'; |
| 218 |
|
|
} |
| 219 |
|
|
|
| 220 |
|
|
foreach my $param ( keys %opts ) { |
| 221 |
|
|
next if ( grep { $param eq $_ } @exclude ) || !$struct->{$param} || !exists($opts{$param}) || $struct->{$param}->{_no_autofilter}; |
| 222 |
|
|
next if $opts{$param} eq SQL::Common::NIL(); |
| 223 |
|
|
if ( uc($opts{$param}) eq 'NULL' || uc($opts{$param}) eq 'NOT NULL' || !defined($opts{$param}) ) { |
| 224 |
|
|
$opts{$param} = 'NULL' unless defined $opts{$param}; |
| 225 |
|
|
my ($where, $values) = &SQL::Common::_generic_null_filter($query_table.'.'.$param, $opts{$param}); |
| 226 |
|
|
push (@wheres, $where); |
| 227 |
|
|
push (@binds, $values) if (defined $values); |
| 228 |
|
|
next; |
| 229 |
|
|
} elsif ( $struct->{$param}->{db_type} eq 'integer' or $struct->{$param}->{type} eq 'checkbox') { |
| 230 |
|
|
my ($where, $values); |
| 231 |
|
|
if ( ref( $opts{$param} ) eq 'HASH') { |
| 232 |
|
|
if ( $opts{$param}->{join} ) { |
| 233 |
|
|
my ( $sub_wheres, $sub_binds, $joins ) = $self->_auto_filter( %{ $opts{$param} }, __join_table => $query_table, __join_field => $param ); |
| 234 |
|
|
push (@wheres, ref($sub_wheres) eq 'ARRAY' ? @{ $sub_wheres } : $sub_wheres ) if defined $sub_wheres; |
| 235 |
|
|
push (@binds, ref($sub_binds) eq 'ARRAY' ? @{ $sub_binds } : $sub_binds ) if defined $sub_binds; |
| 236 |
|
|
push (@joins, ref($joins) eq 'ARRAY' ? @{ $joins } : $joins ) if defined $joins; |
| 237 |
|
|
|
| 238 |
|
|
} else { |
| 239 |
|
|
foreach my $condition ( keys %{ $opts{$param} } ) { |
| 240 |
|
|
($where, $values) = &SQL::Common::_generic_composite_filter($query_table.'.'.$param, $condition, $opts{$param}->{$condition}); |
| 241 |
|
|
push (@wheres, $where); |
| 242 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 243 |
|
|
} |
| 244 |
|
|
} |
| 245 |
|
|
} else { |
| 246 |
|
|
if ( !ref($opts{$param}) && $opts{$param} !~ /^\-?\d+$/ ) { |
| 247 |
|
|
warn "Contenido Warning (_auto_filter): Неверно задано значение для типа integer! ($opts{$param})\n"; |
| 248 |
|
|
next; |
| 249 |
|
|
} |
| 250 |
|
|
($where, $values) = &SQL::Common::_generic_int_filter($query_table.'.'.$param, $opts{$param}); |
| 251 |
|
|
push (@wheres, $where); |
| 252 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 253 |
|
|
|
| 254 |
|
|
} |
| 255 |
|
|
} elsif ( $struct->{$param}->{db_type} eq 'integer[]' ) { |
| 256 |
|
|
my ($where, $values) = &SQL::Common::_generic_intarray_filter($query_table.'.'.$param, $opts{$param}); |
| 257 |
|
|
push (@wheres, ref $where ? @$where : $where); |
| 258 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 259 |
|
|
} elsif ( $struct->{$param}->{db_type} =~ /char/ || $struct->{$param}->{db_type} eq 'text' ) { |
| 260 |
|
|
my ($where, $values); |
| 261 |
|
|
if ( ref( $opts{$param} ) eq 'HASH') { |
| 262 |
|
|
foreach my $condition ( keys %{ $opts{$param} } ) { |
| 263 |
|
|
($where, $values) = &SQL::Common::_generic_composite_filter($query_table.'.'.$param, $condition, $opts{$param}->{$condition}, 'text'); |
| 264 |
|
|
push (@wheres, $where); |
| 265 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 266 |
|
|
} |
| 267 |
|
|
} elsif ($param eq 'name') { |
| 268 |
|
|
# Исключение: для параметра name используем специальный фильтр |
| 269 |
|
|
($where, $values) = &SQL::Common::_generic_name_filter($query_table.'.'.$param, $opts{$param}, undef, \%opts); |
| 270 |
|
|
push (@wheres, $where); |
| 271 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 272 |
|
|
} else { |
| 273 |
|
|
($where, $values) = &SQL::Common::_generic_text_filter($query_table.'.'.$param, $opts{$param}, $opts{"${param}_negative"}); |
| 274 |
|
|
push (@wheres, $where); |
| 275 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 276 |
|
|
} |
| 277 |
|
|
} elsif ( $struct->{$param}->{type} eq 'datetime' or $struct->{$param}->{type} eq 'date' ) { |
| 278 |
|
|
my ($where, $values); |
| 279 |
|
|
if ( ref( $opts{$param} ) eq 'HASH') { |
| 280 |
|
|
foreach my $condition ( keys %{ $opts{$param} } ) { |
| 281 |
|
|
($where, $values) = &SQL::Common::_composite_date_filter($query_table.'.'.$param, $condition, $opts{$param}->{$condition}); |
| 282 |
|
|
push (@wheres, $where); |
| 283 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 284 |
|
|
} |
| 285 |
|
|
} elsif ( $opts{$param} && !ref( $opts{$param} ) ) { |
| 286 |
|
|
($where, $values) = &SQL::Common::_generic_date_filter($query_table.'.'.$param, $opts{$param}); |
| 287 |
|
|
push (@wheres, $where); |
| 288 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 289 |
|
|
} else { |
| 290 |
|
|
warn "Contenido Warning (_auto_filter): Неверно задано значение для поля datetime, ожидается строка в формате 'YYYY-MM-DD[ HH24:MI]', дата в формате unixtime или ссылка на хэш!\n"; |
| 291 |
|
|
next; |
| 292 |
|
|
} |
| 293 |
|
|
} elsif ( $struct->{$param}->{db_type} eq 'real' ) { |
| 294 |
|
|
my ($where, $values); |
| 295 |
|
|
if ( !ref($opts{$param}) && $opts{$param} !~ /^\-?[\d\.]+$/ ) { |
| 296 |
|
|
warn "Contenido Warning (_auto_filter): Неверно задано значение для вещественного поля!\n"; |
| 297 |
|
|
next; |
| 298 |
|
|
} |
| 299 |
|
|
if ( ref( $opts{$param} ) eq 'HASH') { |
| 300 |
|
|
foreach my $condition ( keys %{ $opts{$param} } ) { |
| 301 |
|
|
($where, $values) = &SQL::Common::_generic_composite_filter($query_table.'.'.$param, $condition, $opts{$param}->{$condition}); |
| 302 |
|
|
push (@wheres, $where); |
| 303 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 304 |
|
|
} |
| 305 |
|
|
} else { |
| 306 |
|
|
($where, $values) = &SQL::Common::_generic_text_filter($query_table.'.'.$param, $opts{$param}); |
| 307 |
|
|
push (@wheres, $where); |
| 308 |
|
|
push (@binds, ref($values) ? @$values : $values) if (defined $values); |
| 309 |
|
|
} |
| 310 |
|
|
|
| 311 |
|
|
} |
| 312 |
|
|
} |
| 313 |
|
|
return (\@wheres, \@binds, \@joins); |
| 314 |
|
|
|
| 315 |
|
|
} |
| 316 |
|
|
|
| 317 |
|
|
sub _link_filter { |
| 318 |
|
|
my ($self,%opts)=@_; |
| 319 |
|
|
|
| 320 |
|
|
my @wheres=(); |
| 321 |
|
|
my @binds=(); |
| 322 |
|
|
|
| 323 |
|
|
# Связь определенного класса |
| 324 |
|
|
if (exists($opts{lclass})) { |
| 325 |
|
|
my ($where, $values) = SQL::Common::_generic_text_filter('l.class', $opts{lclass}); |
| 326 |
|
|
push (@wheres, $where); |
| 327 |
|
|
push (@binds, ref($values) ? @$values:$values) if (defined $values); |
| 328 |
|
|
} |
| 329 |
|
|
|
| 330 |
|
|
my $lclass = $opts{lclass} || 'Contenido::Link'; |
| 331 |
|
|
# my $link_table = $lclass->class_table->db_table(); |
| 332 |
|
|
my $link_table = $lclass->_get_table->db_table(); |
| 333 |
|
|
|
| 334 |
|
|
# Ограничение по статусу связи |
| 335 |
|
|
if ( exists $opts{lstatus} ) { |
| 336 |
|
|
my ($where, $values) = SQL::Common::_generic_int_filter('l.status', $opts{lstatus}); |
| 337 |
|
|
push (@wheres, $where); |
| 338 |
|
|
push (@binds, ref($values) ? @$values:$values) if (defined $values); |
| 339 |
|
|
} |
| 340 |
|
|
|
| 341 |
|
|
# Связь с определенным документ(ом/тами) по цели линка |
| 342 |
|
|
if ( exists $opts{ldest} ) { |
| 343 |
|
|
my ($where, $values) = SQL::Common::_generic_int_filter('l.dest_id', $opts{ldest}); |
| 344 |
|
|
push (@wheres, $where); |
| 345 |
|
|
push (@binds, ref($values) ? @$values:$values) if (defined $values); |
| 346 |
|
|
if ($self->_single_class) { |
| 347 |
|
|
return (\@wheres, \@binds, " join $link_table as l on l.source_id=d.id"); |
| 348 |
|
|
} else { |
| 349 |
|
|
return (\@wheres, \@binds, " join $link_table as l on l.source_id=d.id and l.source_class=d.class"); |
| 350 |
|
|
} |
| 351 |
|
|
} |
| 352 |
|
|
|
| 353 |
|
|
# Связь с определенным документ(ом/тами) по источнику линка |
| 354 |
|
|
if ( exists $opts{lsource} ) { |
| 355 |
|
|
my ($where, $values) = SQL::Common::_generic_int_filter('l.source_id', $opts{lsource}); |
| 356 |
|
|
push (@wheres, $where); |
| 357 |
|
|
push (@binds, ref($values) ? @$values:$values) if (defined $values); |
| 358 |
|
|
if ($self->_single_class) { |
| 359 |
|
|
return (\@wheres, \@binds, " join $link_table as l on l.dest_id=d.id"); |
| 360 |
|
|
} else { |
| 361 |
|
|
return (\@wheres, \@binds, " join $link_table as l on l.dest_id=d.id and l.dest_class=d.class"); |
| 362 |
|
|
} |
| 363 |
|
|
} |
| 364 |
|
|
|
| 365 |
|
|
return (undef); |
| 366 |
|
|
} |
| 367 |
|
|
|
| 368 |
|
|
1; |
| 369 |
|
|
|