Project

General

Profile

« Previous | Next » 

Revision 535

Added by Matt Jones about 24 years ago

Modified pathquery.dtd and QuerySpecification to allow some new constraints
on queries submitted to Metacat. Now, queries can contain an optional
set of <owner> tags that identify the users for which documents should be
returned, and a list of <site> tags constraining the site identifiers
(from the accesion number) of returned datasets. For example, for a
pathquery document that contained the XML fragement:
<owner>jones</owner>
<site>MARINE</site>
only documents owned by jones and with an accession number whose scope
was the string 'MARINE' (ie, global part of the ID) would be returned from
the query. This allows us to have site specific catalogs for the MARINE
network, the NRS network, the OBFS network, etc.

Modified the various XSL and HTML forms from the MARINE catalog to utilize
this parameter and only display documents with a scope of 'MARINE'.

Changed the accession number separator to '.' (it used to be ':'). This is
more in agrrement with other systems like Genbank. Because of the replication
mechanism that berkley is developing, we will probably need to mandate the use
of a single accession number format. Right now it will likely be:
scope.uniqueid.revisionid
where "scope" is the name of the site or group responsible for the accession
number domain, "uniqueid" is the unique identifier within that domain, and
"revision" id is the revision number for a particular document. The combined
accession number is, by definition, globally unique (no two documents can be
inserted with the same "scope.uniqueid.revisionid".

BugID: 169

View differences:

lib/pathquery.dtd
27 27
-->
28 28

  
29 29
<!-- Overall query container -->
30
<!ELEMENT pathquery (meta_file_id, querytitle, returndoctype*, returnfield*, 
31
                     querygroup)>
30
<!ELEMENT pathquery (meta_file_id*, querytitle*, returndoctype*, returnfield*, 
31
                     owner*, site*, querygroup)>
32 32

  
33 33
<!-- The version of this query specification -->
34
<!ATTLIST pathquery version CDATA #FIXED "1.0">
34
<!ATTLIST pathquery version CDATA #FIXED "1.1">
35 35

  
36 36
<!-- a unique identifier for this query document -->
37 37
<!ELEMENT meta_file_id (#PCDATA)>
......
42 42
<!-- optional doctype filter - only documents with this type are returned -->
43 43
<!ELEMENT returndoctype (#PCDATA)>
44 44

  
45
<!-- optional name of an xml node to be returned in the resultset -->
45 46
<!ELEMENT returnfield (#PCDATA)>
46 47

  
48
<!-- optional name of the owner of the documents to be returned -->
49
<!-- multiple owner fields are ORed together in the query -->
50
<!ELEMENT owner (#PCDATA)>
51

  
52
<!-- optional name of the site/server of the documents to be returned -->
53
<!-- multiple site fields are ORed together in the query -->
54
<!ELEMENT site (#PCDATA)>
55

  
47 56
<!-- A group of related query terms -->
48 57
<!ELEMENT querygroup ( (queryterm|querygroup)+ )>
49 58

  
lib/metacat.properties
15 15
defaultdatapath=C:\Temp\
16 16
executescript=test.bat
17 17
defaultGlobalName=NCEAS
18
accNumberSeparator=:
18
accNumberSeparator=.
19 19
saxparser=org.apache.xerces.parsers.SAXParser
20 20
servletpath=@servlet-path@
21 21
htmlpath=@html-path@
lib/marine/marine.xsl
58 58
             value="-//NCEAS//resource//EN" />
59 59
             <input type="hidden" name="returndoc"
60 60
              value="-//NCEAS//eml-dataset//EN" />
61
             <input type="hidden" name="site" value="MARINE" />
61 62
             <input border="0" type="image" 
62 63
                    src="@image-path@/marine/browsebutton.jpg"
63 64
                    alt="browse the database"
......
98 99
             value="-//NCEAS//resource//EN" />
99 100
            <input type="hidden" name="returndoc"
100 101
             value="-//NCEAS//eml-dataset//EN" />
102
            <input type="hidden" name="site" value="MARINE" />
101 103
    	     </form>
102 104
         </td>
103 105
    	 </tr>  
......
298 300
             value="-//NCEAS//resource//EN" />
299 301
      <input type="hidden" name="returndoc"
300 302
             value="-//NCEAS//eml-dataset//EN" />
303
      <input type="hidden" name="site" value="MARINE" />
301 304
      <input type="submit" value="Search" />
302 305
      <input type="reset" value="Clear Form" />
303 306
        
......
346 349
          <td>
347 350
            <form action="@html-path@/servlet/marine" method="POST">
348 351
              <xsl:attribute name="name">
349
                <xsl:value-of select="translate(./docid,':','')"/>
352
                <xsl:value-of select="translate(./docid,'.','')"/>
350 353
              </xsl:attribute>
351 354
            <!-- abstractpath tells the servlet where the abstract is in the 
352 355
                 document.  The % sign is used because the path could be
......
369 372

  
370 373
            <font size="2">
371 374
            <a>
372
              <xsl:attribute name="href">javascript:submitform('getdocument',document.<xsl:value-of select="translate(./docid, ':', '')"/>)</xsl:attribute>
375
              <xsl:attribute name="href">javascript:submitform('getdocument',document.<xsl:value-of select="translate(./docid, '.', '')"/>)</xsl:attribute>
373 376
               Dataset Information
374 377
            </a><br />
375 378
            <a>
376
              <xsl:attribute name="href">javascript:submitform('getabstract',document.<xsl:value-of select="translate(./docid,':','')"/>)</xsl:attribute>
379
              <xsl:attribute name="href">javascript:submitform('getabstract',document.<xsl:value-of select="translate(./docid,'.','')"/>)</xsl:attribute>
377 380
              View Abstract
378 381
            </a><br />
379 382
            <a>
380
              <xsl:attribute name="href">javascript:submitform('getdatadoc',document.<xsl:value-of select="translate(./docid,':','')"/>)</xsl:attribute>
383
              <xsl:attribute name="href">javascript:submitform('getdatadoc',document.<xsl:value-of select="translate(./docid,'.','')"/>)</xsl:attribute>
381 384
               Download Data and Metadata
382 385
            </a><br />
383 386
            </font>
lib/marine.html
14 14
  "returnfield=resource/dataset/title&" +
15 15
  "returnfield=resource/dataset/keywordInfo/keyword&" +
16 16
  "returndoc=-//NCEAS//resource//EN&" +
17
  "returndoc=-//NCEAS//eml-dataset//EN";
17
  "returndoc=-//NCEAS//eml-dataset//EN&" +
18
  "site=MARINE";
18 19
</script>
19 20

  
20 21
<center><img src="@image-path@/marine/logo-line.gif" alt="NCEAS logo"></center>
......
29 30
returnfield=resource/dataset/originator/organizationName&
30 31
returnfield=resource/dataset/title&
31 32
returnfield=resource/dataset/keywordInfo/keyword&
32
returndoc=-//NCEAS//resource//EN&returndoc=-//NCEAS//eml-dataset//EN">   
33
returndoc=-//NCEAS//resource//EN&returndoc=-//NCEAS//eml-dataset//EN&
34
site=MARINE">   
33 35
 here</a> to enter the MARINE database.  To disable this message in the future please
34 36
 enable JavaScript on your browser.
35 37
</noscript>
......
42 44
returnfield=resource/dataset/originator/organizationName&
43 45
returnfield=resource/dataset/title&
44 46
returnfield=resource/dataset/keywordInfo/keyword&
45
returndoc=-//NCEAS//resource//EN&returndoc=-//NCEAS//eml-dataset//EN">   
47
returndoc=-//NCEAS//resource//EN&returndoc=-//NCEAS//eml-dataset//EN&
48
site=MARINE">   
46 49
 here.</a> if you are not automatically redirected.
47 50

  
48 51
</body>
src/edu/ucsb/nceas/metacat/QuerySpecification.java
43 43
  private String querytitle;
44 44
  private Vector doctypeList;
45 45
  private Vector returnFieldList;
46
  private Vector ownerList;
47
  private Vector siteList;
46 48
  private QueryGroup query = null;
47 49

  
48 50
  private Stack elementStack;
......
50 52
  private String currentValue;
51 53
  private String currentPathexpr;
52 54
  private String parserName = null;
55
  private String accNumberSeparator = null;
53 56

  
54 57
  /**
55 58
   * construct an instance of the QuerySpecification class 
......
59 62
   * @param parserName the fully qualified name of a Java Class implementing
60 63
   *                  the org.xml.sax.XMLReader interface
61 64
   */
62
  public QuerySpecification( Reader queryspec, String parserName ) 
63
         throws IOException {
65
  public QuerySpecification( Reader queryspec, String parserName,
66
         String accNumberSeparator ) throws IOException {
64 67
    super();
65 68
    
66 69
    // Initialize the class variables
......
68 71
    elementStack = new Stack();
69 72
    queryStack   = new Stack();
70 73
    returnFieldList = new Vector();
74
    ownerList = new Vector();
75
    siteList = new Vector();
71 76
    this.parserName = parserName;
77
    this.accNumberSeparator = accNumberSeparator;
72 78

  
73 79
    // Initialize the parser and read the queryspec
74 80
    XMLReader parser = initializeParser();
......
91 97
   * @param parserName the fully qualified name of a Java Class implementing
92 98
   *                  the org.xml.sax.Parser interface
93 99
   */
94
  public QuerySpecification( String queryspec, String parserName ) 
95
         throws IOException {
96
    this(new StringReader(queryspec), parserName);
100
  public QuerySpecification( String queryspec, String parserName,
101
         String accNumberSeparator) throws IOException {
102
    this(new StringReader(queryspec), parserName, accNumberSeparator);
97 103
  }
98 104

  
99 105
  /** Main routine for testing */
......
110 116
         MetaCatUtil util = new MetaCatUtil();
111 117
         FileReader xml = new FileReader(new File(xmlfile));
112 118
         QuerySpecification qspec = 
113
                 new QuerySpecification(xml, util.getOption("saxparser"));
119
                 new QuerySpecification(xml, util.getOption("saxparser"),
120
                                        util.getOption("accNumberSeparator"));
114 121
         System.out.println(qspec.printSQL());
115 122

  
116 123
       } catch (IOException e) {
......
253 260
    } else if (currentTag.equals("returnfield")) {
254 261
      returnFieldList.add(inputString);
255 262
      containsExtendedSQL = true;
263
    } else if (currentTag.equals("owner")) {
264
      ownerList.add(inputString);
265
    } else if (currentTag.equals("site")) {
266
      siteList.add(inputString);
256 267
    }
257 268
  }
258 269

  
......
273 284
    self.append(") ");
274 285
 
275 286
    // Add SQL to filter for doctypes requested in the query
287
    // This is an implicit OR for the list of doctypes
276 288
    if (!doctypeList.isEmpty()) {
277 289
      boolean firstdoctype = true;
278 290
      self.append(" AND ("); 
......
289 301
      self.append(") ");
290 302
    }
291 303
    
304
    // Add SQL to filter for owners requested in the query
305
    // This is an implicit OR for the list of owners
306
    if (!ownerList.isEmpty()) {
307
      boolean first = true;
308
      self.append(" AND ("); 
309
      Enumeration en = ownerList.elements();
310
      while (en.hasMoreElements()) {
311
        String current = (String)en.nextElement();
312
        if (first) {
313
           first = false;
314
           self.append(" user_owner = '" + current + "'"); 
315
        } else {
316
          self.append(" OR user_owner = '" + current + "'"); 
317
        }
318
      }
319
      self.append(") ");
320
    }
321

  
322
    // Add SQL to filter for sites requested in the query
323
    // This is an implicit OR for the list of sites
324
    if (!siteList.isEmpty()) {
325
      boolean first = true;
326
      self.append(" AND ("); 
327
      Enumeration en = siteList.elements();
328
      while (en.hasMoreElements()) {
329
        String current = (String)en.nextElement();
330
        if (first) {
331
           first = false;
332
           self.append(" SUBSTR(docid, 1, INSTR(docid, '" +
333
               accNumberSeparator + "')-1) = '" + current + "'"); 
334
        } else {
335
          self.append(" OR SUBSTR(docid, 1, INSTR(docid, '" +
336
               accNumberSeparator + "')-1) = '" + current + "'"); 
337
        }
338
      }
339
      self.append(") ");
340
    }
341

  
292 342
    return self.toString();
293 343
  }
294 344
  
......
640 690
     * This should become a way to get the XML serialization of the query.
641 691
     */
642 692
    public String toString() {
643
      StringBuffer self = new StringBuffer();
644 693

  
645
      self.append("    Query Term iscasesensitive=" + casesensitive + "\n");
646
      self.append("               searchmode=" + searchmode + "\n");
647
      self.append("               value=" + value + "\n");
648
      if (pathexpr != null) {
649
        self.append("               pathexpr=" + pathexpr + "\n");
650
      }
651

  
652
      return self.toString();
694
      return this.printSQL();
653 695
    }
654 696
  }
655 697
}
656

  
657
/**
658
 * '$Log$
659
 * 'Revision 1.16  2000/09/26 22:06:52  berkley
660
 * 'Added backtrack functionality.  Backtracking works by passing a returndoc parameter.  There can be more than one.  If a document that is hit by a query is not of type returndoc then it searches the database for a related file of type returndoc.  If one is found it is displayed, if no relation is found, the original is displayed.
661
 * '
662
 * 'Support was also added for an index of relations.  the table xml_relation handles the all of the relation indexing.
663
 * '
664
 * 'Revision 1.15  2000/09/15 19:52:12  berkley
665
 * 'Added functionality for package specifications.  metacatservlet now contains a new action called getrelateddocument that handles retrieving related documents using the metacatURL specification (metacatURL.java).  DBQuery contains new code in runQuery that embeds relation tags in the returned hashtable describing the documents related to each docid.  querySpecification contains a new method which prints the sql that does the relation query.
666
 * '
667
 * 'Revision 1.14  2000/08/31 21:20:39  berkley
668
 * 'changed xslf for new returnfield scheme.  the returnfields are now returned as <param name="<returnfield>"> tags.
669
 * 'hThe sql for the returnfield query was redone to fix a previous problem with slow queries
670
 * '
671
 * 'Revision 1.13  2000/08/23 22:55:38  berkley
672
 * 'changed the field names to be case-sensitive in the returnfields
673
 * '
674
 * 'Revision 1.12  2000/08/23 17:29:05  berkley
675
 * 'added support for the returnfield parameter
676
 * '-QuerySpecification now sets a flag (containsExtendedSQL) when there are returnfield items in the pathquery document.
677
 * 'the accessor method containsExtendedSQL() can be called by other classes to check for extended return parameters
678
 * '-getReturnFields returns a Vector of the names of each specified return field.
679
 * '-printExtendedSQL returns a string of the extra SQL statements required for the query.
680
 * '
681
 * '-a calling class should first check containsExtendedSQL to make sure that there are extra fields being returned, then call printExtendedSQL to
682
 * 'insert the extra SQL into the query.  (Note that this is how DBQuery implements this.)
683
 * '
684
 * 'Revision 1.11  2000/08/14 20:53:34  jones
685
 * 'Added "release" keyword to all metacat source files so that the release
686
 * 'number will be evident in software distributions.
687
 * '
688
 * 'Revision 1.10  2000/06/26 10:35:05  jones
689
 * 'Merged in substantial changes to DBWriter and associated classes and to
690
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
691
 * 'functions.  The command line tools and the parameters for the
692
 * 'servlet have changed substantially.
693
 * '
694
 * 'Revision 1.9.2.3  2000/06/25 23:38:17  jones
695
 * 'Added RCSfile keyword
696
 * '
697
 * 'Revision 1.9.2.2  2000/06/25 23:34:18  jones
698
 * 'Changed documentation formatting, added log entries at bottom of source files
699
 * ''
700
 */
src/edu/ucsb/nceas/metacat/DBQuery.java
39 39
  static final int WRITE = 2;
40 40
  static final int READ = 4;
41 41

  
42
  private Connection	conn = null;
43
  private String	parserName = null;
42
  private Connection  conn = null;
43
  private String  parserName = null;
44 44
  private MetaCatUtil util = new MetaCatUtil();
45 45
  /**
46 46
   * the main routine used to test the DBQuery utility.
......
132 132
  public Hashtable findDocuments(Reader xmlquery, String user, String group,
133 133
                                 String[] returndoc)
134 134
  {
135
      Hashtable	 docListResult = new Hashtable();
135
      Hashtable   docListResult = new Hashtable();
136 136
      PreparedStatement pstmt;
137 137
      String docid = null;
138 138
      String docname = null;
......
157 157
      try {
158 158
        // Get the XML query and covert it into a SQL statment
159 159
        QuerySpecification qspec = new QuerySpecification(xmlquery, 
160
                                   parserName);
160
                                   parserName, 
161
                                   util.getOption("accNumberSeparator"));
161 162
        //System.out.println(qspec.printSQL());
162 163
        pstmt = conn.prepareStatement( qspec.printSQL() );
163 164

  
......
419 420
    if(params.containsKey("meta_file_id"))
420 421
    {
421 422
      query.append( ((String[])params.get("meta_file_id"))[0]);
422
    	query.append("</meta_file_id>");
423
      query.append("</meta_file_id>");
423 424
    }
424 425
    else
425 426
    {
......
430 431
    if(params.containsKey("querytitle"))
431 432
    {
432 433
      query.append(((String[])params.get("querytitle"))[0]);
433
    	query.append("</querytitle>");
434
      query.append("</querytitle>");
434 435
    }
435 436
    else
436 437
    {
437
    	query.append("unspecified</querytitle>");
438
      query.append("unspecified</querytitle>");
438 439
    }
439 440
    
440 441
    if(params.containsKey("doctype"))
......
456 457
      }
457 458
    }
458 459
    
460
    if(params.containsKey("owner"))
461
    {
462
      String[] owner = ((String[])params.get("owner"));
463
      for(int i=0; i<owner.length; i++)
464
      {
465
        query.append("<owner>").append(owner[i]);
466
        query.append("</owner>");
467
      }
468
    }
469
    
470
    if(params.containsKey("site"))
471
    {
472
      String[] site = ((String[])params.get("site"));
473
      for(int i=0; i<site.length; i++)
474
      {
475
        query.append("<site>").append(site[i]);
476
        query.append("</site>");
477
      }
478
    }
479
    
459 480
    //if you don't limit the query by doctype, then it just creates
460 481
    //an empty returndoctype tag.
461 482
    if (!doctype.equals("any") && 
......
474 495
    if(params.containsKey("operator"))
475 496
    {
476 497
      query.append("<querygroup operator=\"" + 
477
    		        ((String[])params.get("operator"))[0] + "\">");
498
                ((String[])params.get("operator"))[0] + "\">");
478 499
    }
479 500
    else
480 501
    { //the default operator is UNION
481 502
      query.append("<querygroup operator=\"UNION\">"); 
482 503
    }
483
    		
504
        
484 505
    if(params.containsKey("casesensitive"))
485 506
    {
486 507
      casesensitive = ((String[])params.get("casesensitive"))[0]; 
......
498 519
    {
499 520
      searchmode = "contains"; 
500 521
    }
501
    		
522
        
502 523
    //anyfield is a special case because it does a 
503 524
    //free text search.  It does not have a <pathexpr>
504 525
    //tag.  This allows for a free text search within the structured
......
513 534
         {
514 535
           query.append("<queryterm casesensitive=\"" + casesensitive + 
515 536
                        "\" " + "searchmode=\"" + searchmode + "\"><value>" +
516
    			              anyfield[i] +
517
    			              "</value></queryterm>"); 
537
                        anyfield[i] +
538
                        "</value></queryterm>"); 
518 539
         }
519 540
       }
520 541
    }
521
    		
542
        
522 543
    //this while loop finds the rest of the parameters
523 544
    //and attempts to query for the field specified
524 545
    //by the parameter.
......
527 548
    while(keys.hasMoreElements() && elements.hasMoreElements())
528 549
    {
529 550
      nextkey = keys.nextElement();
530
    	nextelement = elements.nextElement();
551
      nextelement = elements.nextElement();
531 552

  
532
    	//make sure we aren't querying for any of these
533
    	//parameters since the are already in the query
553
      //make sure we aren't querying for any of these
554
      //parameters since the are already in the query
534 555
      //in one form or another.
535
    	if(!nextkey.toString().equals("doctype") && 
536
    		 !nextkey.toString().equals("action")  &&
537
    		 !nextkey.toString().equals("qformat") && 
538
    		 !nextkey.toString().equals("anyfield") &&
556
      if(!nextkey.toString().equals("doctype") && 
557
         !nextkey.toString().equals("action")  &&
558
         !nextkey.toString().equals("qformat") && 
559
         !nextkey.toString().equals("anyfield") &&
539 560
         !nextkey.toString().equals("returnfield") &&
540
    		 !nextkey.toString().equals("operator") )
541
    	{
561
         !nextkey.toString().equals("owner") &&
562
         !nextkey.toString().equals("site") &&
563
         !nextkey.toString().equals("operator") )
564
      {
542 565
        //allow for more than value per field name
543 566
        for(int i=0; i<((String[])nextelement).length; i++)
544 567
        {
545 568
          if(!((String[])nextelement)[i].equals(""))
546 569
          {
547 570
            query.append("<queryterm casesensitive=\"" + casesensitive +"\" " + 
548
    				             "searchmode=\"" + searchmode + "\">" +
549
    		                 "<value>" +
571
                         "searchmode=\"" + searchmode + "\">" +
572
                         "<value>" +
550 573
                         //add the query value
551
    		                 ((String[])nextelement)[i] +
552
    		                 "</value><pathexpr>" +
553
    		                 //add the path to query by 
574
                         ((String[])nextelement)[i] +
575
                         "</value><pathexpr>" +
576
                         //add the path to query by 
554 577
                         nextkey.toString() + 
555 578
                         "</pathexpr></queryterm>");
556 579
          }
557 580
        }
558
    	}
581
      }
559 582
    }
560 583
    query.append("</querygroup></pathquery>");
561 584
    //append on the end of the xml and return the result as a string
......
719 742
  }
720 743
   
721 744
}
722

  
723
/**
724
 * '$Log$
725
 * 'Revision 1.24  2000/10/03 22:48:41  berkley
726
 * 'added functionality to return the doctype of a relation in a relationdoctype tag.  This information is now returned automatically in the resultset under the path resultset/relation/relationdoctype.
727
 * '
728
 * 'Revision 1.23  2000/09/27 21:37:05  berkley
729
 * 'removed system.out.printlns
730
 * '
731
 * 'Revision 1.22  2000/09/27 20:11:17  berkley
732
 * 'added support for urls of the form "metacat://server.xyz.com?docid=XXX:yy"
733
 * '
734
 * 'Revision 1.21  2000/09/26 22:06:51  berkley
735
 * 'Added backtrack functionality.  Backtracking works by passing a returndoc parameter.  There can be more than one.  If a document that is hit by a query is not of type returndoc then it searches the database for a related file of type returndoc.  If one is found it is displayed, if no relation is found, the original is displayed.
736
 * '
737
 * 'Support was also added for an index of relations.  the table xml_relation handles the all of the relation indexing.
738
 * '
739
 * 'Revision 1.20  2000/09/15 19:52:11  berkley
740
 * 'Added functionality for package specifications.  metacatservlet now contains a new action called getrelateddocument that handles retrieving related documents using the metacatURL specification (metacatURL.java).  DBQuery contains new code in runQuery that embeds relation tags in the returned hashtable describing the documents related to each docid.  querySpecification contains a new method which prints the sql that does the relation query.
741
 * '
742
 * 'Revision 1.19  2000/09/12 17:37:07  bojilova
743
 * 'added check from "read" permission on "query" and "squery" actions
744
 * 'for connected user or for "public" connection
745
 * '
746
 * 'Revision 1.18  2000/09/05 20:50:56  berkley
747
 * 'Added a method called getNodeContent which retrieves the content of a node in a document.  If there are more than one nodes with the same name returned, it returns an array with all of the data.
748
 * '
749
 * 'Revision 1.17  2000/08/31 21:20:39  berkley
750
 * 'changed xslf for new returnfield scheme.  the returnfields are now returned as <param name="<returnfield>"> tags.
751
 * 'hThe sql for the returnfield query was redone to fix a previous problem with slow queries
752
 * '
753
 * 'Revision 1.16  2000/08/23 22:55:25  berkley
754
 * 'changed the field names to be case-sensitive in the returnfields
755
 * '
756
 * 'Revision 1.15  2000/08/23 17:22:07  berkley
757
 * 'added support for the returnfield parameter
758
 * '-added the dynamic parameters to the returned hash table of documents
759
 * '
760
 * 'Revision 1.14  2000/08/17 16:02:34  berkley
761
 * 'Made changes to createSQuery to allow for multiple parameters of the same name.  Also changed the param list to include only "Hashtable params" without a "String doctype" since the doctype is already contained in the params.
762
 * '
763
 * 'Revision 1.13  2000/08/14 21:26:12  berkley
764
 * 'Added createSQuery() to handle structured queries of an arbitrary number of parameters.  Also modified createQuery() to handle a null query in a graceful manner.
765
 * '
766
 * 'Revision 1.12  2000/08/14 20:53:33  jones
767
 * 'Added "release" keyword to all metacat source files so that the release
768
 * 'number will be evident in software distributions.
769
 * '
770
 * 'Revision 1.11  2000/08/11 18:26:07  berkley
771
 * 'added createSQuery
772
 * '
773
 * 'Revision 1.10  2000/07/26 20:40:41  higgins
774
 * 'no message
775
 * '
776
 * 'Revision 1.9  2000/06/26 10:35:04  jones
777
 * 'Merged in substantial changes to DBWriter and associated classes and to
778
 * 'the MetaCatServlet in order to accomodate the new UPDATE and DELETE
779
 * 'functions.  The command line tools and the parameters for the
780
 * 'servlet have changed substantially.
781
 * '
782
 * 'Revision 1.8.2.2  2000/06/25 23:38:16  jones
783
 * 'Added RCSfile keyword
784
 * '
785
 * 'Revision 1.8.2.1  2000/06/25 23:34:17  jones
786
 * 'Changed documentation formatting, added log entries at bottom of source files
787
 * ''
788
 */

Also available in: Unified diff