Project

General

Profile

« Previous | Next » 

Revision 3235

Added by sledge about 17 years ago

Limited use of predicates in XPath return fields

View differences:

src/edu/ucsb/nceas/metacat/QuerySpecification.java
61 61
    /** flag determining whether extended query terms are present */
62 62
    private boolean containsExtendedSQL = false;
63 63

  
64
    /** flag determining whether predicates are present */
65
    private boolean containsPredicates = false;
66

  
64 67
    /** Identifier for this query document */
65 68
    private String meta_file_id;
66 69

  
......
107 110

  
108 111
    public static final String ATTRIBUTESYMBOL = "@";
109 112

  
113
    public static final char PREDICATE_START = '[';
114

  
115
    public static final char PREDICATE_END = ']';
116

  
110 117
    private boolean hasAttributeReturnField = false;
111 118

  
112 119
    private Hashtable attributeReturnList = new Hashtable();
......
626 633
        }
627 634

  
628 635
        //rest textBuffer
629
        textBuffer = null;
630 636
        textBuffer = new StringBuffer();
631 637

  
632 638
    }
......
647 653
    /**
648 654
     * Method to transfer string to return field
649 655
     */
650
    public void handleReturnField(String inputString)
656
    /* public void handleReturnField(String inputString)
651 657
    {
652 658
        // make sure if return fields has an attribute or not
653 659
        if (inputString.indexOf(ATTRIBUTESYMBOL) == -1) {
......
703 709
          }
704 710
        }
705 711
    }
712
     */
713
    public void handleReturnField(String inputString)
714
    {
715
        int attributePos = inputString.indexOf(ATTRIBUTESYMBOL);
716
        int predicateStart = -1;
717
        int predicateEnd;
718
        boolean hasPredicate = false;
706 719

  
720
        while (true)
721
        {
722
            predicateStart = inputString.indexOf(PREDICATE_START, predicateStart + 1);
723

  
724
            if (attributePos == -1)
725
                break;
726

  
727
            if (predicateStart == -1)
728
                break;
729

  
730
            hasPredicate = true;
731

  
732
            if (attributePos < predicateStart)
733
                break;
734

  
735
            predicateEnd = inputString.indexOf(PREDICATE_END, predicateStart);
736

  
737
            if (predicateEnd == -1)
738
            {
739
                logMetacat.warn("handleReturnField(): ");
740
                logMetacat.warn("    Invalid path: " + inputString);
741
                return;
742
            }
743

  
744
            while (attributePos < predicateEnd)
745
            {
746
                attributePos = inputString.indexOf(ATTRIBUTESYMBOL, attributePos + 1);
747

  
748
                if (attributePos == -1)
749
                    break;
750
            }
751
        }
752

  
753
        if (hasPredicate)
754
            containsPredicates = true;
755

  
756
        containsExtendedSQL = true;
757

  
758
        // make sure if return fields has an attribute or not
759
        if (attributePos == -1)
760
        {
761
            // no attribute value will be returned
762
            logMetacat.info("QuerySpecification.handleReturnField(): " );
763
            logMetacat.info("  there are no attributes in the XPATH statement" );
764
            returnFieldList.add(inputString);
765
            return;
766
        }
767

  
768
        // case where the return field is solely an attribute
769
        logMetacat.info("QuerySpecification.handleReturnField(): " );
770
        logMetacat.info("  Found an attribute in the XPATH statement." );
771
        String returnPath = inputString.substring(0,
772
                attributePos == 0 ? attributePos : attributePos - 1);
773
        String attributeName = inputString.substring(attributePos + 1).trim();
774
        Vector pathInfo = new Vector();
775
        // the vector has the information about return path and
776
        // attributename
777
        pathInfo.addElement(returnPath);
778
        pathInfo.addElement(attributeName);
779
        // put the vector into a hash table. The reseaon why don't put
780
        // return path or attributename as a key is because they are not
781
        // unique
782
        attributeReturnList.put(new Integer(countAttributeReturnField),
783
                pathInfo);
784
        countAttributeReturnField++;
785
        hasAttributeReturnField = true;
786
    }
787

  
707 788
    /**
708 789
     * create a SQL serialization of the query that this instance represents
709 790
     */
......
859 940
    public String printExtendedSQL(String doclist,
860 941
            Hashtable unaccessableNodePair, boolean useXMLIndex)
861 942
    {
862
        if (useXMLIndex) {
943
        if (useXMLIndex && !containsPredicates)
944
        {
863 945
            return printExtendedSQL(doclist, unaccessableNodePair);
864
        } else {
946
        }
947
        else
948
        {
865 949
            StringBuffer self = new StringBuffer();
866 950

  
867 951
            boolean firstfield = true;
868 952
            //put the returnfields into the query
869 953
            //the for loop allows for multiple fields
870
            for (int i = 0; i < returnFieldList.size(); i++) {
871
                if (firstfield) {
954
            for (int i = 0; i < returnFieldList.size(); i++)
955
            {
956
                if (firstfield)
957
                {
872 958
                    firstfield = false;
873
                } else {
959
                }
960
                else
961
                {
874 962
                    self.append(" UNION ");
875 963
                }
876 964
                String path  = (String) returnFieldList.elementAt(i);
877 965
                self.append("select xml_nodes.docid, ");
878
                self.append("'"+ path  + "' as path, xml_nodes.nodedata, ");
966
                self.append("'"+ path.replaceAll("'", "''") + "' as path, xml_nodes.nodedata, ");
879 967
                self.append("xml_nodes.parentnodeid ");
880 968
                self.append("from xml_nodes, xml_documents ");
881 969
                self.append("where parentnodeid IN ");
......
1072 1160
     */
1073 1161
    public String printAttributeQuery(String doclist, boolean useXMLIndex)
1074 1162
    {
1075
        if (useXMLIndex) {
1163
        if (useXMLIndex && !containsPredicates) {
1076 1164
            return printAttributeQuery(doclist);
1077 1165
        } else {
1078 1166
            StringBuffer self = new StringBuffer();
......
1090 1178
                    self.append(" UNION ");
1091 1179
                }
1092 1180
                self.append("select xml_nodes.docid, '");
1093
                self.append(returnPath);
1181
                self.append(returnPath.replaceAll("'", "''"));
1094 1182
                self.append("' as path, xml_nodes.nodedata, xml_nodes.nodename ");
1095 1183
                self.append("from xml_nodes, xml_documents ");
1096 1184
                self.append("where parentnodeid IN ");
src/edu/ucsb/nceas/metacat/QueryTerm.java
30 30
package edu.ucsb.nceas.metacat;
31 31

  
32 32
import java.util.Vector;
33
import org.apache.log4j.Logger;
33 34

  
34 35
/** a utility class that represents a single term in a query */
35 36
public class QueryTerm
36 37
{
38
    private static Logger log = Logger.getLogger(QueryTerm.class);
37 39

  
38 40
    private boolean casesensitive = false;
39 41

  
......
286 288
        }
287 289
    }
288 290

  
289
    /*
291
    /**
290 292
     * Constraint the query with @pathexp without using the XML Index, but
291 293
     * nested SQL statements instead. The query migth be slower.
292
     */
293 294
    public static String useNestedStatements(String pathexpr)
294 295
    {
295 296
      System.out.println("pathexpr: " + pathexpr);
......
310 311
        for (i = 0; i < nodes.size() - 1; i++) {
311 312
            nestedStmts.append("(SELECT nodeid FROM xml_nodes"
312 313
                    + " WHERE nodename LIKE '" + (String) nodes.elementAt(i)
313
                    + "'" + " AND parentnodeid IN ");
314
                    + "' AND parentnodeid IN ");
314 315
        }
315 316
        // for the last statement: it is without " AND parentnodeid IN "
316 317
        nestedStmts.append("(SELECT nodeid FROM xml_nodes"
......
322 323

  
323 324
        return nestedStmts.toString();
324 325
    }
326
     */
327
    public static String useNestedStatements(String pathexpr)
328
    {
329
        log.info("useNestedStatements()");
330
        log.info("pathexpr: " + pathexpr);
331
        StringBuffer nestedStmts = new StringBuffer();
332
        String path = pathexpr.trim();
325 333

  
334
        if (path.indexOf('/') == 0)
335
        {
336
            nestedStmts.append("AND parentnodeid = rootnodeid ");
337
            path = path.substring(1).trim();
338
        }
339

  
340
        do
341
        {
342
            int inx = path.indexOf('/');
343
            int predicateStart = -1;
344
            int predicateEnd;
345
            String node;
346
            Vector predicates = new Vector();
347

  
348
            // extract predicates
349
            predicateStart = path.indexOf(QuerySpecification.PREDICATE_START, predicateStart + 1);
350

  
351
            // any predicates in this node?
352
            if (inx != -1 && (predicateStart == -1 || predicateStart > inx))
353
            {
354
                // no
355
                node = path.substring(0, inx).trim();
356
                path = path.substring(inx + 1).trim();
357
            }
358
            else if (predicateStart == -1)
359
            {
360
                // no and it's the last node
361
                node = path;
362
                path = "";
363
            }
364
            else
365
            {
366
                // yes
367
                node = path.substring(0, predicateStart).trim();
368
                path = path.substring(predicateStart);
369
                predicateStart = 0;
370

  
371
                while (predicateStart == 0)
372
                {
373
                    predicateEnd = path.indexOf(QuerySpecification.PREDICATE_END,
374
                            predicateStart);
375

  
376
                    if (predicateEnd == -1)
377
                    {
378
                        log.warn("useNestedStatements(): ");
379
                        log.warn("    Invalid path: " + pathexpr);
380
                        return "";
381
                    }
382

  
383
                    predicates.add(path.substring(1, predicateEnd).trim());
384
                    path = path.substring(predicateEnd + 1).trim();
385
                    inx = path.indexOf('/');
386
                    predicateStart = path.indexOf(QuerySpecification.PREDICATE_START);
387
                }
388

  
389
                if (inx == 0)
390
                    path = path.substring(1).trim();
391
                else if (!path.equals(""))
392
                {
393
                    log.warn("useNestedStatements(): ");
394
                    log.warn("    Invalid path: " + pathexpr);
395
                    return "";
396
                }
397
            }
398

  
399
            nestedStmts.insert(0, "' ").insert(0, node).insert(0,
400
                    "(SELECT nodeid FROM xml_nodes WHERE nodename LIKE '");
401

  
402
            // for the last statement: it is without " AND parentnodeid IN "
403
            if (!path.equals(""))
404
                nestedStmts.insert(0, "AND parentnodeid IN ");
405

  
406
            if (predicates.size() > 0)
407
            {
408
                for (int n = 0; n < predicates.size(); n++)
409
                {
410
                    String predSQL = predicate2SQL((String) predicates.get(n));
411

  
412
                    if (predSQL.equals(""))
413
                        return "";
414

  
415
                    nestedStmts.append(predSQL).append(' ');
416
                }
417
            }
418

  
419
            nestedStmts.append(") ");
420
        }
421
        while (!path.equals(""));
422

  
423
        return nestedStmts.toString();
424
    }
425

  
326 426
    /**
427
     * 
428
     */
429
    public static String predicate2SQL(String predicate)
430
    {
431
        String path = predicate.trim();
432
        int equals = path.indexOf('=');
433
        String literal = null;
434

  
435
        if (equals != -1)
436
        {
437
            literal = path.substring(equals + 1).trim();
438
            path = path.substring(0, equals).trim();
439
            int sQuote = literal.indexOf('\'');
440
            int dQuote = literal.indexOf('"');
441

  
442
            if (sQuote == -1 && dQuote == -1)
443
            {
444
                log.warn("predicate2SQL(): ");
445
                log.warn("    Invalid or unsupported predicate: " + predicate);
446
                return "";
447
            }
448

  
449
            if (sQuote == -1 &&
450
                (dQuote != 0 ||
451
                 literal.indexOf('"', dQuote + 1) != literal.length() - 1))
452
            {
453
                log.warn("predicate2SQL(): ");
454
                log.warn("    Invalid or unsupported predicate: " + predicate);
455
                return "";
456
            }
457

  
458
            if (sQuote != 0 ||
459
                literal.indexOf('\'', sQuote + 1) != literal.length() - 1)
460
            {
461
                log.warn("predicate2SQL(): ");
462
                log.warn("    Invalid or unsupported predicate: " + predicate);
463
                return "";
464
            }
465
        }
466

  
467
        StringBuffer sql = new StringBuffer();
468
        int attribute = path.indexOf('@');
469

  
470
        if (attribute == -1)
471
        {
472
            if (literal != null)
473
            {
474
                sql.append("AND nodeid IN (SELECT parentnodeid FROM xml_nodes WHERE nodetype = 'TEXT' AND nodedata LIKE ")
475
                    .append(literal).append(")");
476
            }
477
        }
478
        else
479
        {
480
            sql.append(
481
                    "AND nodeid IN (SELECT parentnodeid FROM xml_nodes WHERE nodetype = 'ATTRIBUTE' AND nodename LIKE '")
482
                    .append(path.substring(attribute + 1).trim()).append("' ");
483

  
484
            if (literal != null)
485
            {
486
                sql.append("AND nodedata LIKE ").append(literal);
487
            }
488

  
489
            sql.append(")");
490
            path = path.substring(0, attribute).trim();
491

  
492
            if (path.endsWith("/"))
493
                path = path.substring(0, path.length() - 1).trim();
494
            else
495
            {
496
                if (!path.equals(""))
497
                {
498
                    log.warn("predicate2SQL(): ");
499
                    log.warn("    Invalid or unsupported predicate: " + predicate);
500
                    return "";
501
                }
502
            }
503
        }
504

  
505
        while (!path.equals(""))
506
        {
507
            int ndx = path.lastIndexOf('/');
508
            int predicateEnd = -1;
509
            int predicateStart;
510
            String node;
511

  
512
            if (ndx != -1)
513
            {
514
                node = path.substring(ndx + 1).trim();
515
                path = path.substring(0, ndx).trim();
516
            }
517
            else
518
            {
519
                node = path;
520
                path = "";
521
            }
522

  
523
            if (!node.equals(""))
524
                sql.insert(0, "' ").insert(0, node)
525
                    .insert(0, "(SELECT parentnodeid FROM xml_nodes WHERE nodename LIKE '").append(") ");
526
            else if (!path.equals(""))
527
            {
528
                log.warn("predicate2SQL(): ");
529
                log.warn("    Invalid or unsupported predicate: " + predicate);
530
                return "";
531
            }
532

  
533
            if (path.equals(""))
534
            {
535
                sql.insert(0,
536
                        node.equals("") ? "AND rootnodeid IN " : "AND nodeid IN ");
537
            }
538
            else
539
            {
540
                sql.append("AND nodeid IN ");
541
            }
542
        }
543

  
544
        return sql.toString();
545
    }
546

  
547
    /**
327 548
     * create a String description of the query that this instance represents.
328 549
     * This should become a way to get the XML serialization of the query.
329 550
     */

Also available in: Unified diff