Line data Source code
1 : //# Copyright (C) 2004
2 : //# Associated Universities, Inc. Washington DC, USA.
3 : //#
4 : //# This library is free software; you can redistribute it and/or modify it
5 : //# under the terms of the GNU Library General Public License as published by
6 : //# the Free Software Foundation; either version 2 of the License, or (at your
7 : //# option) any later version.
8 : //#
9 : //# This library is distributed in the hope that it will be useful, but WITHOUT
10 : //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 : //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 : //# License for more details.
13 : //#
14 : //# You should have received a copy of the GNU Library General Public License
15 : //# along with this library; if not, write to the Free Software Foundation,
16 : //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
17 : //#
18 : //# Correspondence concerning AIPS++ should be addressed as follows:
19 : //# Internet email: aips2-request@nrao.edu.
20 : //# Postal address: AIPS++ Project Office
21 : //# National Radio Astronomy Observatory
22 : //# 520 Edgemont Road
23 : //# Charlottesville, VA 22903-2475 USA
24 : #include "SearcherSQLite.h"
25 :
26 :
27 : #include <spectrallines/Splatalogue/SQLiteSearch/DatabaseConnector.h>
28 : #include <sqlite3.h>
29 : #include <iostream>
30 : #include <sstream>
31 :
32 :
33 : using namespace std;
34 :
35 : namespace casa {
36 : const std::string SearcherSQLite::TABLE_SPECIES = "species";
37 : const std::string SearcherSQLite::TABLE_MAIN = "main";
38 :
39 : const std::string SearcherSQLite::SPECIES_ID_COLUMN = "species_id"; //Type 1
40 : const std::string SearcherSQLite::FREQUENCY_COLUMN = "orderedfreq"; //Type 2
41 : const std::string SearcherSQLite::TEMPERATURE_COLUMN ="upper_state_energy_K";
42 : const std::string SearcherSQLite::SPECIES_COLUMN = "s_name"; //Type 3
43 : const std::string SearcherSQLite::SMU2_COLUMN = "sijmu2";
44 : const std::string SearcherSQLite::LOGA_COLUMN = "aij";
45 : const std::string SearcherSQLite::EL_COLUMN = "lower_state_energy";
46 : const std::string SearcherSQLite::EU_COLUMN = "upper_state_energy";
47 : const std::string SearcherSQLite::RESOLVED_QNS_COLUMN = "resolved_QNs"; //Type 3
48 : const std::string SearcherSQLite::INTENSITY_COLUMN = "intintensity"; //Type 5
49 : const std::string SearcherSQLite::CHEMICAL_NAME_COLUMN = "chemical_name";
50 :
51 : std::vector<string> SearcherSQLite::resultColumns(END_COL);
52 :
53 : const std::string SearcherSQLite::FILTER_KNOWN_AST_COLUMN = "known_ast_molecules";
54 : const std::string SearcherSQLite::FILTER_PLANET_COLUMN = "planet";
55 : const std::string SearcherSQLite::FILTER_HOTCORE_COLUMN = "ism_hotcore";
56 : const std::string SearcherSQLite::FILTER_DIFFUSECLOUD_COLUMN = "ism_diffusecloud";
57 : const std::string SearcherSQLite::FILTER_DARKCLOUD_COLUMN = "ism_darkcloud";
58 : const std::string SearcherSQLite::FILTER_COMET_COLUMN = "comet";
59 : const std::string SearcherSQLite::FILTER_EXTRAGALACTIC_COLUMN = "extragalactic";
60 : const std::string SearcherSQLite::FILTER_AGB_PPN_PN_COLUMN = "AGB_PPN_PN";
61 : const std::string SearcherSQLite::FILTER_TOP20_COLUMN = "Top20";
62 :
63 : std::vector<string> SearcherSQLite::filterNames( END_FILTERS );
64 :
65 : const std::string SearcherSQLite::AND = " AND ";
66 : const std::string SearcherSQLite::OPEN_PAREN = "(";
67 : const std::string SearcherSQLite::CLOSE_PAREN = ")";
68 : const std::string SearcherSQLite::SINGLE_QUOTE = "'";
69 : const std::string SearcherSQLite::COMMA = ", ";
70 : const std::string SearcherSQLite::PERIOD = ".";
71 : const std::string SearcherSQLite::EQUALS = " = ";
72 : const std::string SearcherSQLite::IN = " IN ";
73 : const std::string SearcherSQLite::SELECT = "SELECT ";
74 : const std::string SearcherSQLite::FROM = " FROM ";
75 : const std::string SearcherSQLite::BETWEEN = " BETWEEN ";
76 : const std::string SearcherSQLite::LIKE = " LIKE ";
77 : const std::string SearcherSQLite::OR = " OR ";
78 :
79 : const int SearcherSQLite::DEFAULT_VALUE = -1;
80 :
81 0 : SearcherSQLite::SearcherSQLite( const string& databasePath):
82 : filters(END_FILTERS),
83 0 : rowLimit(25){
84 0 : db = DatabaseConnector::getDatabase(databasePath);
85 0 : if ( db != NULL ){
86 : /*string errorMsg;
87 : string mainTableInfo = this->tableInfo( TABLE_MAIN, errorMsg );
88 : cout << "Main table: "<<mainTableInfo << endl;
89 : string speciesTableInfo = this->tableInfo( TABLE_SPECIES, errorMsg );
90 : cout << "Species table: "<<speciesTableInfo << endl;
91 : */
92 :
93 0 : resultColumns[SPECIES_ID_COL] = TABLE_MAIN + PERIOD + SPECIES_ID_COLUMN;
94 0 : resultColumns[SPECIES_NAME_COL] = SPECIES_COLUMN;
95 0 : resultColumns[CHEMICAL_NAME_COL] = CHEMICAL_NAME_COLUMN;
96 0 : resultColumns[FREQUENCY_COL] = FREQUENCY_COLUMN;
97 0 : resultColumns[TEMPERATURE_COL]= TEMPERATURE_COLUMN;
98 0 : resultColumns[RESOLVED_QNS_COL] = RESOLVED_QNS_COLUMN;
99 0 : resultColumns[INTENSITY_COL] = INTENSITY_COLUMN;
100 0 : resultColumns[SMU2_COL] = SMU2_COLUMN;
101 0 : resultColumns[LOGA_COL] = LOGA_COLUMN;
102 0 : resultColumns[EL_COL] = EL_COLUMN;
103 0 : resultColumns[EU_COL] = EU_COLUMN;
104 :
105 0 : filterNames[FILTER_TOP_20] = FILTER_TOP20_COLUMN;
106 0 : filterNames[FILTER_PLANETARY_ATMOSPHERE] = FILTER_PLANET_COLUMN;
107 0 : filterNames[FILTER_HOT_CORES] = FILTER_HOTCORE_COLUMN;
108 0 : filterNames[FILTER_DARK_CLOUDS] = FILTER_DARKCLOUD_COLUMN;
109 0 : filterNames[FILTER_DIFFUSE_CLOUDS] = FILTER_DIFFUSECLOUD_COLUMN;
110 0 : filterNames[FILTER_COMETS]=FILTER_COMET_COLUMN;
111 0 : filterNames[FILTER_AGB_PPN_PN] = FILTER_AGB_PPN_PN_COLUMN;
112 0 : filterNames[FILTER_EXTRAGALACTIC] = FILTER_EXTRAGALACTIC_COLUMN;
113 : }
114 : else {
115 0 : cout << "Could not open database from path "<<databasePath.c_str()<<endl;
116 : }
117 0 : reset();
118 0 : }
119 :
120 0 : bool SearcherSQLite::isConnected() const {
121 0 : bool connected = false;
122 0 : if ( db != NULL ){
123 0 : connected = true;
124 : }
125 0 : return connected;
126 : }
127 :
128 0 : void SearcherSQLite::setSearchResultLimit( int limit ){
129 0 : rowLimit = limit;
130 0 : }
131 :
132 :
133 : //*********************************************************************
134 : // Search Parameters
135 : //*********************************************************************
136 :
137 0 : void SearcherSQLite::reset(){
138 0 : chemicalNames.clear();
139 0 : speciesNames.clear();
140 0 : qns.clear();
141 0 : for ( int i = 0; i < static_cast<int>(filters.size()); i++ ){
142 0 : filters[i] = false;
143 : }
144 0 : minValueFreq = DEFAULT_VALUE;
145 0 : maxValueFreq = DEFAULT_VALUE;
146 0 : minValueIntensity = DEFAULT_VALUE;
147 0 : maxValueIntensity = DEFAULT_VALUE;
148 0 : minValueSmu2 = DEFAULT_VALUE;
149 0 : maxValueSmu2 = DEFAULT_VALUE;
150 0 : minValueLoga = DEFAULT_VALUE;
151 0 : maxValueLoga = DEFAULT_VALUE;
152 0 : minValueEl = DEFAULT_VALUE;
153 0 : maxValueEl = DEFAULT_VALUE;
154 0 : minValueEu = DEFAULT_VALUE;
155 0 : maxValueEu = DEFAULT_VALUE;
156 0 : }
157 :
158 0 : void SearcherSQLite::setChemicalNames( const vector<string>& chemNames ){
159 0 : chemicalNames = chemNames;
160 0 : }
161 :
162 0 : void SearcherSQLite::setSpeciesNames( const vector<string>& species ){
163 0 : speciesNames = species;
164 0 : }
165 :
166 0 : void SearcherSQLite::setFrequencyRange( double minVal, double maxVal ){
167 0 : if ( minVal < maxVal ){
168 0 : minValueFreq = minVal;
169 0 : maxValueFreq = maxVal;
170 : }
171 : else {
172 0 : minValueFreq = maxVal;
173 0 : maxValueFreq = minVal;
174 : }
175 0 : }
176 :
177 0 : void SearcherSQLite::setIntensityRange( double minValue, double maxValue ){
178 0 : if ( minValue < maxValue ){
179 0 : minValueIntensity = minValue;
180 0 : maxValueIntensity = maxValue;
181 : }
182 : else {
183 0 : minValueIntensity = maxValue;
184 0 : maxValueIntensity = minValue;
185 : }
186 0 : }
187 :
188 0 : void SearcherSQLite::setSmu2Range( double minValue, double maxValue ){
189 0 : if ( minValue < maxValue ){
190 0 : minValueSmu2 = minValue;
191 0 : maxValueSmu2 = maxValue;
192 : }
193 : else {
194 0 : minValueSmu2 = maxValue;
195 0 : maxValueSmu2 = minValue;
196 : }
197 0 : }
198 :
199 0 : void SearcherSQLite::setLogaRange( double minValue, double maxValue ){
200 0 : if ( minValue < maxValue ){
201 0 : minValueLoga = minValue;
202 0 : maxValueLoga = maxValue;
203 : }
204 : else {
205 0 : minValueLoga = maxValue;
206 0 : maxValueLoga = minValue;
207 : }
208 0 : }
209 :
210 0 : void SearcherSQLite::setElRange( double minValue, double maxValue ){
211 0 : if ( minValue < maxValue ){
212 0 : minValueEl = minValue;
213 0 : maxValueEl = maxValue;
214 : }
215 : else {
216 0 : minValueEl = maxValue;
217 0 : maxValueEl = minValue;
218 : }
219 0 : }
220 :
221 0 : void SearcherSQLite::setEuRange( double minValue, double maxValue ){
222 0 : if ( minValue < maxValue ){
223 0 : minValueEu = minValue;
224 0 : maxValueEu = maxValue;
225 : }
226 : else {
227 0 : minValueEu = maxValue;
228 0 : maxValueEu = minValue;
229 : }
230 0 : }
231 :
232 0 : void SearcherSQLite::setQNS( const vector<string>& qns ){
233 0 : this->qns = qns;
234 0 : }
235 :
236 : //*********************************************************************
237 : // Filters
238 : //*********************************************************************
239 :
240 0 : void SearcherSQLite::setFilterTop20( bool filter ){
241 0 : filters[FILTER_TOP_20] = filter;
242 0 : }
243 0 : void SearcherSQLite::setFilterPlanetaryAtmosphere( bool filter ){
244 0 : filters[FILTER_PLANETARY_ATMOSPHERE] = filter;
245 0 : }
246 0 : void SearcherSQLite::setFilterHotCores( bool filter ){
247 0 : filters[FILTER_HOT_CORES] = filter;
248 0 : }
249 0 : void SearcherSQLite::setFilterDarkClouds( bool filter ){
250 0 : filters[FILTER_DARK_CLOUDS] = filter;
251 0 : }
252 0 : void SearcherSQLite::setFilterDiffuseClouds( bool filter ){
253 0 : filters[FILTER_DIFFUSE_CLOUDS] = filter;
254 0 : }
255 0 : void SearcherSQLite::setFilterComets( bool filter ){
256 0 : filters[FILTER_COMETS] = filter;
257 0 : }
258 0 : void SearcherSQLite::setFilterAgbPpnPn( bool filter ){
259 0 : filters[FILTER_AGB_PPN_PN] = filter;
260 0 : }
261 0 : void SearcherSQLite::setFilterExtragalactic( bool filter ){
262 0 : filters[FILTER_EXTRAGALACTIC] = filter;
263 0 : }
264 :
265 :
266 : //**********************************************************************
267 : // Database Information
268 : //**********************************************************************
269 :
270 0 : string SearcherSQLite::tableInfo( const string& tableName, string& errorMsg ) const{
271 0 : string query;
272 0 : query.append( SELECT );
273 0 : query.append( "*");
274 0 : query.append( FROM );
275 0 : query.append( tableName );
276 0 : query.append(" LIMIT 1" );
277 0 : sqlite3_stmt* statement = NULL;
278 0 : bool successfulQuery = executeQuery( statement, query, errorMsg );
279 0 : string tableInfo;
280 0 : if ( successfulQuery ){
281 : //Returns one row for each column in the table
282 0 : int columnCount = sqlite3_column_count( statement );
283 0 : while( sqlite3_step( statement ) == SQLITE_ROW ){
284 0 : for ( int j = 0; j < columnCount; j++ ){
285 0 : const char* columnName = sqlite3_column_name( statement, j );
286 0 : int columnType = sqlite3_column_type( statement, j );
287 0 : string rowInfo( columnName );
288 0 : rowInfo.append( " ");
289 0 : rowInfo.append( numToString(columnType) );
290 0 : rowInfo.append( "\n");
291 0 : tableInfo.append( rowInfo );
292 : }
293 : }
294 : }
295 : else {
296 0 : errorMsg = sqlite3_errmsg( db );
297 : //cout << "Error obtaining table information "<<errorMsg<< endl;
298 : }
299 0 : return tableInfo;
300 : }
301 :
302 0 : string SearcherSQLite::getCreatedDate() const {
303 0 : return DatabaseConnector::getCreatedDate();
304 : }
305 :
306 :
307 :
308 : //************************************************************************
309 : // Querying the Database
310 : //************************************************************************
311 :
312 0 : void SearcherSQLite::stopSearch(){
313 0 : sqlite3_interrupt( db );
314 0 : }
315 :
316 0 : long SearcherSQLite::doSearchCount( string& errorMsg ){
317 0 : string query = prepareQuery( true, 0 );
318 : sqlite3_stmt* statement;
319 0 : long resultCount = 0;
320 0 : bool success = executeQuery( statement, query, errorMsg );
321 0 : if ( success ){
322 0 : int result = sqlite3_step( statement );
323 0 : if( result == SQLITE_ROW ){
324 0 : resultCount = sqlite3_column_int( statement, 0 );
325 : }
326 : }
327 : else {
328 0 : errorMsg = sqlite3_errmsg( db );
329 0 : cout << "Error was " << errorMsg << endl;
330 : }
331 : //cout << "Result count="<<resultCount<<endl;
332 0 : sqlite3_finalize(statement);
333 0 : return resultCount;
334 : }
335 :
336 0 : vector<SplatResult> SearcherSQLite::doSearch( string& errorMsg, int offset ){
337 0 : string query = prepareQuery( false, offset );
338 : sqlite3_stmt* statement;
339 0 : vector<SplatResult> results;
340 0 : bool success = executeQuery( statement, query, errorMsg );
341 0 : if ( success ){
342 0 : while( sqlite3_step( statement ) == SQLITE_ROW ){
343 :
344 0 : int speciesId = sqlite3_column_int( statement, SPECIES_ID_COL);
345 0 : string chemicalName = reinterpret_cast<const char*>(sqlite3_column_text( statement, CHEMICAL_NAME_COL ));
346 0 : string speciesName = reinterpret_cast<const char*>(sqlite3_column_text( statement, SPECIES_NAME_COL ));
347 0 : double frequency = sqlite3_column_double( statement, FREQUENCY_COL );
348 0 : double temperature = sqlite3_column_double( statement, TEMPERATURE_COL );
349 0 : double smu2 = sqlite3_column_double( statement, SMU2_COL );
350 0 : double loga = sqlite3_column_double( statement, LOGA_COL );
351 0 : double el = sqlite3_column_double( statement, EL_COL );
352 0 : double eu = sqlite3_column_double( statement, EU_COL );
353 0 : string resolvedQNs = reinterpret_cast<const char*>(sqlite3_column_text( statement, RESOLVED_QNS_COL ));
354 0 : double intensity = sqlite3_column_double( statement, INTENSITY_COL );
355 0 : pair<double,string> freqPair( frequency, "MHz");
356 0 : pair<double,string> tempPair( temperature, "K");
357 0 : pair<double,string> elPair( el, "cm-1" );
358 0 : pair<double,string> euPair( eu, "cm-1" );
359 : SplatResult result( speciesId, speciesName, chemicalName, resolvedQNs,
360 0 : freqPair, tempPair, smu2, elPair, euPair, loga, intensity );
361 0 : results.push_back( result );
362 : //cout << result.toLine();
363 : }
364 : }
365 : else {
366 0 : errorMsg = sqlite3_errmsg( db );
367 : //cout << "Error was " << errorMsg << endl;
368 : }
369 0 : sqlite3_finalize(statement);
370 0 : return results;
371 : }
372 :
373 0 : bool SearcherSQLite:: executeQuery( sqlite3_stmt*& statement, const string& query,
374 : string& errorMsg ) const {
375 0 : bool success = true;
376 0 : int status = sqlite3_prepare( db, query.c_str(), -1, &statement, NULL);
377 0 : if ( status != SQLITE_OK ){
378 0 : success = false;
379 0 : errorMsg = sqlite3_errmsg( db );
380 : }
381 0 : return success;
382 : }
383 :
384 0 : string SearcherSQLite::prepareQuery( bool countOnly, int offset ) const {
385 0 : std::string query;
386 0 : query.append( SELECT );
387 0 : if ( countOnly ){
388 0 : query.append( "Count()");
389 : }
390 : else {
391 0 : int resultColumnCount = resultColumns.size();
392 0 : for ( int i = 0; i < resultColumnCount; i++ ){
393 0 : query.append( resultColumns[i]);
394 0 : if ( i != resultColumnCount - 1 ){
395 0 : query.append( COMMA );
396 : }
397 : }
398 : }
399 0 : query.append( FROM );
400 0 : query.append( TABLE_MAIN );
401 0 : query.append( COMMA );
402 0 : query.append( TABLE_SPECIES );
403 0 : query.append( " WHERE ");
404 :
405 : //Join the two tables together based on the species id
406 0 : query.append( TABLE_MAIN );
407 0 : query.append( PERIOD );
408 0 : query.append( SPECIES_ID_COLUMN );
409 0 : query.append( " == " );
410 0 : query.append( TABLE_SPECIES );
411 0 : query.append( PERIOD );
412 0 : query.append( SPECIES_ID_COLUMN );
413 :
414 : //Frequency
415 0 : if ( minValueFreq >= 0 && maxValueFreq >= 0 && minValueFreq <= maxValueFreq ){
416 0 : query.append( getBetweenClause( FREQUENCY_COLUMN, minValueFreq, maxValueFreq ) );
417 : }
418 :
419 :
420 :
421 : //Species
422 0 : if (speciesNames.size() > 0) {
423 : //query.append( getInClause( SPECIES_COLUMN, speciesNames ) );
424 0 : query.append( getLikeClause( SPECIES_COLUMN, speciesNames) );
425 : }
426 :
427 : //Chemical Names
428 0 : if (chemicalNames.size() > 0) {
429 0 : query.append( getInClause( CHEMICAL_NAME_COLUMN, chemicalNames ));
430 : }
431 :
432 : //Resolved Quantum Numbers
433 0 : if (qns.size() > 0) {
434 0 : query.append( getInClause( RESOLVED_QNS_COLUMN, qns ));
435 : }
436 :
437 : //Intensity
438 0 : if (minValueIntensity < maxValueIntensity) {
439 0 : query.append( getBetweenClause( INTENSITY_COLUMN, minValueIntensity, maxValueIntensity));
440 : }
441 :
442 : //SMU2
443 0 : if ( minValueSmu2 < maxValueSmu2 ) {
444 0 : query.append( getBetweenClause( SMU2_COLUMN, minValueSmu2, maxValueSmu2));
445 : }
446 :
447 : //LOGA
448 0 : if ( minValueLoga < maxValueLoga ) {
449 0 : query.append( getBetweenClause( LOGA_COLUMN, minValueLoga, maxValueLoga ) );
450 : }
451 :
452 : //EL
453 0 : if ( minValueEl < maxValueEl ) {
454 0 : query.append( getBetweenClause( EL_COLUMN, minValueEl, maxValueEl ));
455 : }
456 :
457 : //EU
458 0 : if ( minValueEu < maxValueEu ) {
459 0 : query.append( getBetweenClause( EU_COLUMN, minValueEu, maxValueEu ));
460 : }
461 :
462 : //Astronomical Filters
463 0 : for ( int i = 0; i < static_cast<int>(filters.size()); i++ ){
464 0 : if ( filters[i] ){
465 0 : query.append( AND );
466 0 : query.append( filterNames[i]);
467 0 : query.append( EQUALS );
468 0 : query.append( getTrue());
469 : }
470 : }
471 :
472 :
473 0 : if ( !countOnly ){
474 0 : if ( rowLimit > 0 ){
475 0 : query.append( " LIMIT ");
476 0 : query.append( numToString(rowLimit) );
477 0 : if ( offset > 0 ){
478 0 : query.append( " OFFSET ");
479 0 : query.append( numToString(offset) );
480 : }
481 : }
482 : }
483 : //cout << "Query: "<<query.c_str()<<endl;
484 0 : return query;
485 : }
486 :
487 :
488 :
489 : //******************************************************************
490 : // Utility
491 : //******************************************************************
492 0 : string SearcherSQLite::numToString( double number ) const {
493 0 : string result;
494 0 : ostringstream convert;
495 0 : convert << number;
496 0 : result = convert.str();
497 0 : return result;
498 : }
499 :
500 :
501 0 : std::string numToString( float val ){
502 0 : std::stringstream stream;
503 0 : std::string str;
504 0 : stream << val;
505 0 : str = stream.str();
506 0 : return str;
507 : }
508 :
509 :
510 0 : std::string SearcherSQLite::getTrue() const {
511 0 : return "1";
512 : }
513 :
514 0 : string SearcherSQLite::getBetweenClause( const string& columnName,
515 : double low, double high) const {
516 0 : string betweenClause;
517 0 : betweenClause.append( AND );
518 0 : betweenClause.append( OPEN_PAREN );
519 0 : betweenClause.append( columnName );
520 0 : betweenClause.append( BETWEEN );
521 0 : betweenClause.append( numToString( low ) );
522 0 : betweenClause.append( AND );
523 0 : betweenClause.append( numToString( high ) );
524 0 : betweenClause.append( CLOSE_PAREN );
525 0 : return betweenClause;
526 : }
527 :
528 :
529 :
530 0 : string SearcherSQLite::getInClause( const string& columnName, const vector<string>& values ) const {
531 0 : string inClause;
532 0 : inClause.append( AND );
533 0 : inClause.append( OPEN_PAREN );
534 0 : inClause.append( columnName );
535 0 : inClause.append( IN );
536 0 : inClause.append( OPEN_PAREN );
537 0 : int valueCount = values.size();
538 0 : for (int i=0; i<valueCount; i++) {
539 0 : inClause.append( SINGLE_QUOTE );
540 0 : inClause.append( values[i] );
541 0 : inClause.append( SINGLE_QUOTE );
542 0 : if (i != valueCount - 1) {
543 0 : inClause.append( ", ");
544 : }
545 : }
546 0 : inClause.append( CLOSE_PAREN );
547 0 : inClause.append( CLOSE_PAREN );
548 0 : return inClause;
549 : }
550 :
551 :
552 0 : string SearcherSQLite::getLikeClause( const string& columnName, const vector<string>& values ) const {
553 0 : string likeClause;
554 0 : likeClause.append( AND );
555 0 : likeClause.append( OPEN_PAREN );
556 :
557 : //This was written so that for users searching by chemical formula,
558 : //they could enter 'CO' and return entries such as 'CO v=0' and
559 : //'CO v=1', which are in the species column.
560 0 : int valueCount = values.size();
561 0 : for (int i=0; i<valueCount; i++) {
562 0 : likeClause.append( columnName );
563 0 : likeClause.append( LIKE );
564 0 : likeClause.append( SINGLE_QUOTE );
565 0 : likeClause.append( values[i]);
566 0 : likeClause.append( SINGLE_QUOTE );
567 :
568 0 : likeClause.append( OR );
569 0 : likeClause.append( columnName );
570 0 : likeClause.append( LIKE );
571 0 : likeClause.append( SINGLE_QUOTE );
572 0 : likeClause.append( values[i] + " %");
573 0 : likeClause.append( SINGLE_QUOTE );
574 : }
575 0 : likeClause.append( CLOSE_PAREN );
576 0 : return likeClause;
577 : }
578 :
579 :
580 0 : SearcherSQLite::~SearcherSQLite() {
581 : // TODO Auto-generated destructor stub
582 0 : }
583 :
584 : }
|