~ubuntu-branches/ubuntu/oneiric/tracker/oneiric

« back to all changes in this revision

Viewing changes to src/libtracker-data/tracker-sparql-query.vala

  • Committer: Package Import Robot
  • Author(s): Michael Biebl
  • Date: 2011-08-26 00:26:14 UTC
  • mfrom: (4.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20110826002614-4qjfs9jhh5gs4p13
Tags: 0.10.24-1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
167
167
                        base.subquery (query, parent_context);
168
168
                }
169
169
        }
 
170
 
 
171
        class Solution {
 
172
                public HashTable<string,int> hash;
 
173
                public GenericArray<string> values;
 
174
                public int solution_index;
 
175
 
 
176
                public Solution () {
 
177
                        this.hash = new HashTable<string,int> (str_hash, str_equal);
 
178
                        this.values = new GenericArray<string> ();
 
179
                }
 
180
 
 
181
                public string? lookup (string variable_name) {
 
182
                        int variable_index;
 
183
                        if (!hash.lookup_extended (variable_name, null, out variable_index)) {
 
184
                                return null;
 
185
                        }
 
186
                        return values[solution_index * hash.size () + variable_index];
 
187
                }
 
188
        }
170
189
}
171
190
 
172
191
public class Tracker.Sparql.Query : Object {
494
513
                                } else {
495
514
                                        throw new Sparql.Error.TYPE ("`%s' is not a valid boolean".printf (binding.literal));
496
515
                                }
 
516
                        } else if (binding.data_type == PropertyType.DATE) {
 
517
                                stmt.bind_int (i, string_to_date (binding.literal + "T00:00:00Z", null));
497
518
                        } else if (binding.data_type == PropertyType.DATETIME) {
498
519
                                stmt.bind_int (i, string_to_date (binding.literal, null));
499
520
                        } else if (binding.data_type == PropertyType.INTEGER) {
656
677
 
657
678
                var after_where = get_location ();
658
679
 
 
680
                var solution = new Solution ();
 
681
 
659
682
                // build SQL
660
683
                sql.append ("SELECT ");
661
 
                bool first = true;
 
684
                int var_idx = 0;
662
685
                foreach (var variable in context.var_set.get_keys ()) {
663
 
                        if (!first) {
 
686
                        if (var_idx > 0) {
664
687
                                sql.append (", ");
665
 
                        } else {
666
 
                                first = false;
667
688
                        }
668
689
 
669
690
                        if (variable.binding == null) {
670
691
                                throw get_error ("use of undefined variable `%s'".printf (variable.name));
671
692
                        }
672
693
                        Expression.append_expression_as_string (sql, variable.sql_expression, variable.binding.data_type);
 
694
 
 
695
                        solution.hash.insert (variable.name, var_idx++);
673
696
                }
674
697
 
675
 
                if (first) {
 
698
                if (var_idx == 0) {
676
699
                        sql.append ("1");
677
700
                }
678
701
 
686
709
                this.delete_statements = delete_statements;
687
710
                this.update_statements = update_statements;
688
711
 
 
712
                int n_solutions = 0;
 
713
                while (cursor.next ()) {
 
714
                        // get values of all variables to be bound
 
715
                        for (var_idx = 0; var_idx < solution.hash.size (); var_idx++) {
 
716
                                solution.values.add (cursor.get_string (var_idx));
 
717
                        }
 
718
                        n_solutions++;
 
719
                }
 
720
 
 
721
                cursor = null;
 
722
 
689
723
                // iterate over all solutions
690
 
                while (cursor.next ()) {
 
724
                for (int i = 0; i < n_solutions; i++) {
691
725
                        // blank nodes in construct templates are per solution
692
726
 
693
727
                        uuid_generate (base_uuid);
694
728
                        blank_nodes = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
695
729
 
696
 
                        // get values of all variables to be bound
697
 
                        var var_value_map = new HashTable<string,string>.full (str_hash, str_equal, g_free, g_free);
698
 
                        int var_idx = 0;
699
 
                        foreach (var variable in context.var_set.get_keys ()) {
700
 
                                var_value_map.insert (variable.name, cursor.get_string (var_idx++));
701
 
                        }
702
 
 
703
730
                        set_location (template_location);
704
731
 
 
732
                        solution.solution_index = i;
 
733
 
705
734
                        // iterate over each triple in the template
706
 
                        parse_construct_triples_block (var_value_map);
 
735
                        parse_construct_triples_block (solution);
707
736
 
708
737
                        if (blank && update_blank_nodes != null) {
709
738
                                update_blank_nodes.add_value (blank_nodes);
712
741
                        Data.update_buffer_might_flush ();
713
742
                }
714
743
 
 
744
                solution = null;
 
745
 
715
746
                if (!data) {
716
747
                        // reset location to the end of the update
717
748
                        set_location (after_where);
749
780
                }
750
781
        }
751
782
 
752
 
        void parse_construct_triples_block (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
 
783
        void parse_construct_triples_block (Solution var_value_map) throws Sparql.Error, DateError {
753
784
                expect (SparqlTokenType.OPEN_BRACE);
754
785
 
755
786
                while (current () != SparqlTokenType.CLOSE_BRACE) {
 
787
                        bool is_null = false;
 
788
 
756
789
                        if (accept (SparqlTokenType.GRAPH)) {
757
790
                                var old_graph = current_graph;
758
 
                                current_graph = parse_construct_var_or_term (var_value_map);
 
791
                                current_graph = parse_construct_var_or_term (var_value_map, out is_null);
 
792
 
 
793
                                if (is_null) {
 
794
                                        throw get_error ("'null' not supported for graph");
 
795
                                }
759
796
 
760
797
                                expect (SparqlTokenType.OPEN_BRACE);
761
798
 
762
799
                                while (current () != SparqlTokenType.CLOSE_BRACE) {
763
 
                                        current_subject = parse_construct_var_or_term (var_value_map);
 
800
                                        current_subject = parse_construct_var_or_term (var_value_map, out is_null);
 
801
 
 
802
                                        if (is_null) {
 
803
                                                throw get_error ("'null' not supported for subject");
 
804
                                        }
 
805
 
764
806
                                        parse_construct_property_list_not_empty (var_value_map);
765
807
                                        if (!accept (SparqlTokenType.DOT)) {
766
808
                                                // no triples following
774
816
 
775
817
                                accept (SparqlTokenType.DOT);
776
818
                        } else {
777
 
                                current_subject = parse_construct_var_or_term (var_value_map);
 
819
                                current_subject = parse_construct_var_or_term (var_value_map, out is_null);
 
820
 
 
821
                                if (is_null) {
 
822
                                        throw get_error ("'null' not supported for subject");
 
823
                                }
 
824
 
778
825
                                parse_construct_property_list_not_empty (var_value_map);
779
826
                                if (!accept (SparqlTokenType.DOT) && current () != SparqlTokenType.GRAPH) {
780
827
                                        // neither GRAPH nor triples following
788
835
 
789
836
        bool anon_blank_node_open = false;
790
837
 
791
 
        string? parse_construct_var_or_term (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
 
838
        string? parse_construct_var_or_term (Solution var_value_map, out bool is_null) throws Sparql.Error, DateError {
792
839
                string result = "";
 
840
                is_null = false;
793
841
                if (current () == SparqlTokenType.VAR) {
794
842
                        next ();
795
843
                        result = var_value_map.lookup (get_last_string ().substring (1));
823
871
                } else if (current () == SparqlTokenType.INTEGER) {
824
872
                        next ();
825
873
                        result = get_last_string ();
 
874
                } else if (current () == SparqlTokenType.NULL) {
 
875
                        next ();
 
876
                        result = "null";
 
877
                        is_null = true;
826
878
                } else if (current () == SparqlTokenType.DECIMAL) {
827
879
                        next ();
828
880
                        result = get_last_string ();
870
922
                return result;
871
923
        }
872
924
 
873
 
        void parse_construct_property_list_not_empty (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
 
925
        void parse_construct_property_list_not_empty (Solution var_value_map) throws Sparql.Error, DateError {
874
926
                while (true) {
875
927
                        var old_predicate = current_predicate;
876
928
 
907
959
                }
908
960
        }
909
961
 
910
 
        void parse_construct_object_list (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
 
962
        void parse_construct_object_list (Solution var_value_map) throws Sparql.Error, DateError {
911
963
                while (true) {
912
964
                        parse_construct_object (var_value_map);
913
965
                        if (accept (SparqlTokenType.COMMA)) {
917
969
                }
918
970
        }
919
971
 
920
 
        void parse_construct_object (HashTable<string,string> var_value_map) throws Sparql.Error, DateError {
921
 
                string object = parse_construct_var_or_term (var_value_map);
 
972
        void parse_construct_object (Solution var_value_map) throws Sparql.Error, DateError {
 
973
                bool is_null = false;
 
974
                string object = parse_construct_var_or_term (var_value_map, out is_null);
922
975
                if (current_subject == null || current_predicate == null || object == null) {
923
976
                        // the SPARQL specification says that triples containing unbound variables
924
977
                        // should be excluded from the output RDF graph of CONSTRUCT
927
980
                try {
928
981
                        if (update_statements) {
929
982
                                // update triple in database
930
 
                                Data.update_statement (current_graph, current_subject, current_predicate, object);
 
983
                                Data.update_statement (current_graph, current_subject, current_predicate, is_null ? null : object);
931
984
                        } else if (delete_statements) {
932
985
                                // delete triple from database
 
986
                                if (is_null) {
 
987
                                        throw get_error ("'null' not supported in this mode");
 
988
                                }
933
989
                                Data.delete_statement (current_graph, current_subject, current_predicate, object);
934
990
                        } else {
935
991
                                // insert triple into database
 
992
                                if (is_null) {
 
993
                                        throw get_error ("'null' not supported in this mode");
 
994
                                }
936
995
                                Data.insert_statement (current_graph, current_subject, current_predicate, object);
937
996
                        }
938
997
                } catch (Sparql.Error e) {