Changeset 1788 for trunk/LATMOS-Accounts/lib/LATMOS/Accounts
- Timestamp:
- 06/24/16 07:01:18 (8 years ago)
- Location:
- trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/Group.pm
r1786 r1788 87 87 multiple => 1, 88 88 delayed => 1, 89 iname => 'memberUID', 89 90 can_values => sub { $base->list_objects('user') }, 90 91 ro => sub { -
trunk/LATMOS-Accounts/lib/LATMOS/Accounts/Bases/Sql/objects.pm
r1783 r1788 736 736 my ($class, $base, @filter) = @_; 737 737 738 my %attrsql; 739 my %attrbind; 738 # Results groups by attr (OR filter) 739 # foo=1 foo=1 => foo = 1 or foo = 2 740 # foo=1 bar=1 => foo =1 and bar = 2 741 my $results = {}; 740 742 741 743 while (my $item = shift(@filter)) { 742 744 # attr=foo => no extra white space ! 743 745 # \W is false, it is possible to have two char 744 my ($attr, $ mode, $val) = $item =~ /^(\w+)(?:([^\w*]+)(.+))?$/ or next;745 if (!$ mode) {746 $ mode= '~';746 my ($attr, $attrref, $operator, $val) = $item =~ /^(\w+)(?:\.([\.\w]+))?(?:([^\w*]+)(.+))?$/ or next; 747 if (!$operator) { 748 $operator = '~'; 747 749 $val = shift(@filter); 748 750 } … … 753 755 defined($val) or $val = ''; 754 756 757 $base->log(LA_DEBUG, "Search for %s %s (ref %s) %s %s", $class->type, $attr, $attrref || '(none)', $operator || '', $val); 758 755 759 # Invalid filter due to impossible value: 756 if ($ mode ne '~' && !($modeeq '=' && $val eq 'NULL')) {760 if ($operator ne '~' && !($operator eq '=' && $val eq 'NULL')) { 757 761 if (!$attribute->checkinputformat($val)) { 758 762 $base->log(LA_ERR, "Invalid format value $val for attribute $attr"); … … 761 765 } 762 766 763 $val = $attribute->input($val) unless($mode eq '=' && $val eq 'NULL'); 767 if ($attrref) { 768 my $otype = $attribute->reference or do { 769 $base->log(LA_ERR, "Attribute $attr do not refer to another object"); 770 return; 771 }; 772 773 my @results = $base->search_objects($otype, "$attrref$operator$val"); 774 $base->log(LA_DEBUG, "Sub search %s res: %s", $otype, join(', ', @results)); 775 776 if (!@results) { 777 $results->{$attr} ||= {}; 778 next; 779 } 780 781 ($operator, $val) = ('=', join('||', @results)); 782 } 783 784 my @results = $class->_search_uniq_filter($base, $attr, $operator, $val); 785 786 $results->{$attr}{$_} = 1 foreach (@results) 787 } 788 789 # Merging filter result 790 my ($attrRef) = keys %{ $results } or return; 791 792 my %mresults = %{ $results->{$attrRef} }; 793 794 foreach my $attr (keys %{ $results }) { 795 my @values = keys %mresults; 796 foreach (@values) { 797 $results->{$attr}{$_} or delete($mresults{$_}); 798 } 799 } 800 801 return(sort keys %mresults); 802 } 803 804 805 sub _search_uniq_filter { 806 my ($class, $base, $attr, $operator, $value) = @_; 807 808 my @attrsql; 809 my @attrbind; 810 811 my $attribute = $base->attribute($class->type, $attr) or do { 812 $base->log(LA_ERR, "Unknown attribute $attr"); 813 return; 814 }; 815 816 my @values = split(/([\|\&]+)/, $value); 817 818 # We detect if we can do a very quick search: 819 my $forRef = $operator eq '=' && ! grep { $_ eq '*' or $_ eq '&&' or $_ eq 'NULL' } @values; 820 if ($forRef) { 821 # Improv perf 822 if ($attribute->{inline}) { 823 my $sql = sprintf( 824 q{select ikey from %s where %s = ANY (?)}, 825 $base->db->quote_identifier($class->_object_table), 826 $base->db->quote_identifier($attribute->iname), 827 ); 828 push(@attrsql, $sql); 829 } else { 830 my $sql = sprintf( 831 q{select okey from %s where attr = ? and "value" = ANY (?) }, 832 $base->db->quote_identifier($class->_object_table . '_attributes'), 833 ); 834 push(@attrbind, $attribute->iname); 835 push(@attrsql, $sql); 836 } 837 push(@attrbind, [ grep { $_ ne '||' } @values ]); 838 } else { 839 840 # No optimisation possible: 841 while (defined(my $val = shift(@values))) { 842 843 if ($val eq '&&') { 844 push(@attrsql, 'intersect'); 845 next; 846 } 847 if ($val eq '||') { 848 push(@attrsql, 'union'); 849 next; 850 } 851 852 $val = $attribute->input($val) unless($operator eq '=' && $val eq 'NULL'); 764 853 765 854 my $sql; … … 777 866 $base->db->quote_identifier($class->_object_table), 778 867 $base->db->quote_identifier($attribute->iname), 779 ($ modeeq '~' ? '::text' : ''),780 $ modeeq '=' && $val eq '*'868 ($operator eq '~' ? '::text' : ''), 869 $operator eq '=' && $val eq '*' 781 870 ? 'is not NULL' 782 : $ modeeq '=' && $val eq 'NULL'871 : $operator eq '=' && $val eq 'NULL' 783 872 ? 'is NULL' 784 : $ modeeq '~'873 : $operator eq '~' 785 874 ? 'ILIKE ?' 786 : "$ mode?"875 : "$operator ?" 787 876 ); 788 push(@ {$attrbind{$attr}}, $mode eq '~' ? '%' . $val . '%' : $val) unless($modeeq '=' && ($val eq '*' || $val eq 'NULL'));877 push(@attrbind, $operator eq '~' ? '%' . $val . '%' : $val) unless($operator eq '=' && ($val eq '*' || $val eq 'NULL')); 789 878 } else { 790 if ($ modeeq '=' && $val eq 'NULL') {879 if ($operator eq '=' && $val eq 'NULL') { 791 880 $sql = sprintf(q{ select ikey from %s where ikey 792 881 not in (select okey from %s where attr = ? and ("value" is NOT NULL and value != '')) }, … … 796 885 ), 797 886 ); 798 push(@ {$attrbind{$attr}}, $attribute->iname);887 push(@attrbind, $attribute->iname); 799 888 } else { 800 889 $sql = sprintf( … … 805 894 $val eq '*' 806 895 ? '' 807 : $ modeeq '~'896 : $operator eq '~' 808 897 ? q{and value::text ILIKE ?} 809 : qq{and value $ mode?}898 : qq{and value $operator ?} 810 899 811 900 ); 812 push(@ {$attrbind{$attr}}, $attribute->iname);813 push(@ {$attrbind{$attr}}, $modeeq '~' ? '%' . $val . '%' : $val) unless($val eq '*');901 push(@attrbind, $attribute->iname); 902 push(@attrbind, $operator eq '~' ? '%' . $val . '%' : $val) unless($val eq '*'); 814 903 } 815 904 } 816 905 817 push(@{ $attrsql{$attr} }, $sql); 818 } 906 push(@attrsql, $sql); 907 } 908 909 } # Perf 819 910 820 911 # building the query 821 my @sqlintersec;822 912 if (!$base->{wexported}) { 823 push(@ sqlintersec, sprintf(913 push(@attrsql, 'intersect', sprintf( 824 914 q{select ikey from %s where exported = true}, 825 915 $base->db->quote_identifier($class->_object_table) 826 916 ) 827 917 ); 828 }829 my @bind;830 foreach (keys %attrsql) {831 push(@sqlintersec, '(' . join(" union ", @{$attrsql{$_}}) . ")\n");832 push(@bind, @{$attrbind{$_} || []});833 918 } 834 919 my $sth = $base->db->prepare( … … 839 924 }, 840 925 $base->db->quote_identifier($class->_object_table), 841 @ sqlintersec842 ? "where ikey in (\n" . join(" \n intersect\n", @sqlintersec) . ")\n"926 @attrsql 927 ? "where ikey in (\n" . join(" ", @attrsql) . ")\n" 843 928 : '', 844 929 ) 845 930 ); 846 $sth->execute(@ bind);931 $sth->execute(@attrbind); 847 932 my @results; 848 933 while (my $res = $sth->fetchrow_hashref) {
Note: See TracChangeset
for help on using the changeset viewer.