00001
00002 #include "drms.h"
00003 #include "drms_priv.h"
00004 #include "drms_names.h"
00005
00006
00007
00008
00009
00010 static int parse_name(char **in, char *out, int maxlen);
00011 static RecordSet_Filter_t *parse_record_set_filter(DRMS_Record_t *template,
00012 char **in,
00013 int *allvers);
00014 static RecordQuery_t *parse_record_query(char **in);
00015 static RecordList_t *parse_record_list(DRMS_Record_t *template, char **in);
00016 static PrimekeyRangeSet_t *parse_primekey_set(DRMS_Keyword_t *keyword,
00017 char **in);
00018 static PrimekeyRangeSet_t *parse_slottedkey_set(DRMS_Keyword_t *slotkey,
00019 char **in);
00020 static IndexRangeSet_t *parse_index_set(char **in);
00021 static ValueRangeSet_t *parse_value_set(DRMS_Keyword_t *keyword, char **in);
00022 static int is_duration(const char *in);
00023 static int parse_duration(char **in, double *duration, double width);
00024
00025 static int syntax_error;
00026 static int prime_keynum=0;
00027 static int recnum_filter;
00028
00029
00030 #define SKIPWS(p) while(*p && isspace(*p)) { ++p;}
00031
00032 RecordSet_t *parse_record_set(DRMS_Env_t *env, char **in)
00033 {
00034 int status;
00035 char *p = *in;
00036 RecordSet_t *rs;
00037 int allvers = 0;
00038
00039 #ifdef DEBUG
00040 printf("enter parse_record_set\n");
00041 #endif
00042
00043 prime_keynum = 0;
00044 syntax_error = 0;
00045 recnum_filter = 0;
00046
00047 rs = malloc(sizeof(RecordSet_t));
00048 XASSERT(rs);
00049 memset(rs,0,sizeof(RecordSet_t));
00050
00051 SKIPWS(p);
00052 if (!parse_name(&p, rs->seriesname, DRMS_MAXSERIESNAMELEN))
00053 {
00054
00055
00056
00057 #ifdef DEBUG
00058 printf("got seriesname='%s'\n",rs->seriesname);
00059 #endif
00060 SKIPWS(p);
00061 if (*p==0)
00062 {
00063 rs->template = NULL;
00064 rs->recordset_spec = NULL;
00065 return rs;
00066 }
00067 else if (*p != '[')
00068 {
00069 fprintf(stderr,"Syntax error in record_set: Series name must be "
00070 "followed by '[', found '%c'\n",*p);
00071 ++syntax_error;
00072 goto empty;
00073 }
00074
00075
00076
00077
00078 if ((rs->template = drms_template_record(env,rs->seriesname,&status)) == NULL)
00079 {
00080 fprintf(stderr,"Couldn't get template record for series '%s'."
00081 "drms_template_record return status=%d\n",
00082 rs->seriesname, status);
00083 goto empty;
00084 }
00085 rs->recordset_spec = parse_record_set_filter(rs->template, &p, &allvers);
00086
00087 if (syntax_error)
00088 goto empty;
00089
00090 rs->allvers = allvers;
00091
00092 *in = p;
00093 #ifdef DEBUG
00094 printf("exit parse_record_set\n");
00095 #endif
00096 return rs;
00097 }
00098 empty:
00099 free(rs);
00100 return NULL;
00101 }
00102
00103
00104 static int parse_name(char **in, char *out, int maxlen)
00105 {
00106 int len;
00107 char *p=*in;
00108 #ifdef DEBUG
00109 printf("enter parse_name\n");
00110 #endif
00111 len = 0;
00112 *out = 0;
00113
00114 if (*p==0 || !isalpha(*p))
00115 {
00116 return 1;
00117 #ifdef DEBUG
00118 printf("exit parse_name\n");
00119 #endif
00120 }
00121 *out++ = *p++;
00122 ++len;
00123 while (len < maxlen && *p && (isalnum(*p) || *p == '_' || *p == '.')) {
00124 *out++ = *p++;
00125 ++len;
00126 }
00127 if (len == maxlen) {
00128 fprintf (stderr,"name '%.*s' is too long.\n",len,*in);
00129 syntax_error++;
00130 #ifdef DEBUG
00131 printf ("exit parse_name\n");
00132 #endif
00133 return 1;
00134 }
00135 else if (len) *out = 0;
00136 *in = p;
00137 #ifdef DEBUG
00138 printf("got name='%s'\nexit parse_name\n",out);
00139 #endif
00140
00141 return 0;
00142 }
00143
00144 static RecordSet_Filter_t *parse_record_set_filter(DRMS_Record_t *template,
00145 char **in,
00146 int *allvers)
00147 {
00148 RecordSet_Filter_t *head=NULL, *rsp=NULL;
00149 char *p = *in;
00150
00151 if (allvers)
00152 {
00153 *allvers = 0;
00154 }
00155
00156 #ifdef DEBUG
00157 printf("enter parse_record_set_filter\n");
00158 #endif
00159 if (*p!='[')
00160 {
00161 fprintf(stderr,"Syntax error: Record_set_filter should "
00162 "start with '[', found '%s'\n", p);
00163 syntax_error++;
00164 goto error1;
00165 }
00166 while (*p && *p=='[')
00167 {
00168 ++p;
00169 if (*p==']')
00170 {
00171 prime_keynum++;
00172 p++;
00173 continue;
00174 }
00175 if (rsp)
00176 {
00177 rsp->next = malloc(sizeof(RecordSet_Filter_t));
00178 XASSERT(rsp->next);
00179 rsp = rsp->next;
00180 memset(rsp,0,sizeof(RecordSet_Filter_t));
00181 }
00182 else
00183 {
00184 rsp = malloc(sizeof(RecordSet_Filter_t));
00185 XASSERT(rsp);
00186 head = rsp;
00187 memset(rsp,0,sizeof(RecordSet_Filter_t));
00188 }
00189
00190
00191
00192
00193 if (*p=='?' || *p=='!')
00194 {
00195 if (*p == '!' && allvers)
00196 {
00197 *allvers = 1;
00198 }
00199
00200 rsp->type = RECORDQUERY;
00201 if ((rsp->record_query = parse_record_query(&p))==NULL &&
00202 syntax_error)
00203 goto error;
00204 }
00205 else
00206 {
00207 rsp->type = RECORDLIST;
00208 if ((rsp->record_list = parse_record_list(template,&p))==NULL &&
00209 syntax_error)
00210 goto error;
00211 }
00212 while (*p == ' ')
00213 p++;
00214
00215
00216 if (*p != ']')
00217 {
00218 fprintf(stderr,"Syntax error: Record_set_filter should "
00219 "end in ']', found '%c' then '%s'\n", *(p-1), p);
00220 syntax_error++;
00221 goto error;
00222 }
00223 else
00224 {
00225 ++p;
00226 }
00227 }
00228 *in = p;
00229 #ifdef DEBUG
00230 printf("exit parse_record_set\n");
00231 #endif
00232 return head;
00233
00234 error:
00235 while(head)
00236 { rsp = head->next; free(head); head = rsp; }
00237 error1:
00238 return NULL;
00239 }
00240
00241
00242
00243 static RecordQuery_t *parse_record_query(char **in)
00244 {
00245 int len;
00246 RecordQuery_t *query;
00247 char *p = *in, *out;
00248
00249 #ifdef DEBUG
00250 printf("enter parse_record_query\n");
00251 #endif
00252 char endchar = *p;
00253
00254 if (*p =='?' || *p == '!')
00255 {
00256
00257 char *bquote = NULL;
00258 char *equote = NULL;
00259
00260 p++;
00261 query = malloc(sizeof(RecordQuery_t));
00262 XASSERT(query);
00263 memset(query,0,sizeof(RecordQuery_t));
00264 out = query->where;
00265 len = 0;
00266
00267
00268 while(len<DRMS_MAXQUERYLEN && *p)
00269 {
00270 if (*p == '"' || *p == '\'')
00271 {
00272 char endq = *p;
00273
00274 DRMS_Type_Value_t val;
00275
00276 memset(&val, 0, sizeof(DRMS_Type_Value_t));
00277
00278
00279
00280 int rlen = drms_sscanf_str(p, NULL, &val);
00281 int ilen = 0;
00282
00283 if (rlen == -1)
00284 {
00285
00286 fprintf(stderr, "End quote '%c' missing.\n", endq);
00287 goto error;
00288 }
00289
00290 bquote = out;
00291 equote = bquote + rlen - 1;
00292
00293 while (ilen < rlen)
00294 {
00295 *out++ = *p++;
00296 ilen++;
00297 }
00298
00299
00300
00301
00302 if (*bquote == '"' && *equote == '"')
00303 {
00304 *bquote = *equote = '\'';
00305 }
00306 }
00307
00308 else if (*p == '$' && *(p+1) == '(')
00309 {
00310
00311
00312
00313
00314
00315
00316 char *rparen = strchr(p+2, ')');
00317 if (!rparen || rparen - p > 40)
00318 {
00319 fprintf(stderr,"Time conversion error starting at %s\n",p+2);
00320 goto error;
00321 }
00322 else
00323 {
00324 char temptime[100];
00325
00326 TIME t;
00327 int consumed;
00328 strncpy(temptime,p+2,rparen-p-2);
00329 consumed = sscan_time_ext(temptime, &t);
00330 if (time_is_invalid(t))
00331 fprintf(stderr,"Warning in parse_record_query: invalid time from %s\n",temptime);
00332 #ifdef DEBUG
00333 fprintf(stderr,"XXXXX in parse_record_query, convert time %s uses %d chars, gives %f\n",temptime, consumed,t);
00334 #endif
00335 p = rparen + 1;
00336 out += sprintf(out, "%16.6f", t);
00337 }
00338 }
00339 else if (*p == endchar)
00340 {
00341
00342 if (*(p + 1) == ']')
00343 {
00344 break;
00345 }
00346 else
00347 {
00348
00349
00350 fprintf(stderr, "Expecting filter to end in '%c]', but '%c]' found;\n", endchar, *(p + 1));
00351 goto error;
00352 }
00353 }
00354 else
00355 {
00356
00357 *out++ = *p++;
00358 }
00359 }
00360
00361 if (*p++ == endchar)
00362 {
00363 *out-- = '\0';
00364
00365 while(out>=query->where && isspace(*out)) { *out-- = '\0'; };
00366 *in = p;
00367 }
00368 else
00369 {
00370 fprintf(stderr,"Embedded SQL query should end with '%c', query is:%s.\n", endchar, *in);
00371 free(query);
00372 goto error;
00373 }
00374 }
00375 else
00376 {
00377 fprintf(stderr,"Embedded SQL query should start with '%c', found '%c', then '%s'.\n", endchar, *p, ++p);
00378 goto error;
00379 }
00380 #ifdef DEBUG
00381 printf("got query='%s'\nexit parse_record_query\n",query->where);
00382 #endif
00383 return query;
00384
00385 error:
00386 ++syntax_error;
00387 return NULL;
00388 }
00389
00390 static DRMS_Keyword_t *GetSlottedKey(DRMS_Record_t *template, DRMS_Keyword_t *indx)
00391 {
00392 DRMS_Keyword_t *ret = NULL;
00393 char *kname = strdup(indx->info->name);
00394
00395 if (kname)
00396 {
00397 char *underscore = strstr(kname, kSlotAncKey_Index);
00398
00399 if (underscore && drms_keyword_isindex(indx))
00400 {
00401 *underscore = '\0';
00402 ret = (DRMS_Keyword_t *)hcon_lookup_lower(&(template->keywords), kname);
00403 }
00404
00405 free(kname);
00406 }
00407
00408 return ret;
00409 }
00410
00411 static RecordList_t *parse_record_list(DRMS_Record_t *template, char **in) {
00412 int err,i,keynum;
00413 RecordList_t *rl;
00414 char *p = *in;
00415 char pk[DRMS_MAXKEYNAMELEN];
00416 char strbuf[DRMS_MAXQUERYLEN];
00417 DRMS_SeriesInfo_t *si;
00418 DRMS_Keyword_t *nprimekey = NULL;
00419 int explKW = 0;
00420
00421 #ifdef DEBUG
00422 printf ("enter parse_record_list\n");
00423 #endif
00424
00425 rl = malloc(sizeof(RecordList_t));
00426 XASSERT(rl);
00427 if (*p==':') {
00428 recnum_filter = 1;
00429 ++p;
00430 rl->type = RECNUMSET;
00431 if ((rl->recnum_rangeset = parse_index_set(&p)) == NULL && syntax_error)
00432 goto error;
00433 } else {
00434 if (template->seriesinfo->pidx_num <= 0) {
00435 fprintf (stderr, "Error: Primary key query issued for series with no "
00436 "primary keys, query is '%s'\n", p);
00437 goto error;
00438 }
00439
00440 rl->type = PRIMEKEYSET;
00441 si = template->seriesinfo;
00442
00443 SKIPWS(p);
00444
00445
00446 err = parse_name (&p, strbuf, sizeof(strbuf));
00447
00448 if (!err)
00449 {
00450 SKIPWS(p);
00451 }
00452
00453 if (*p == '=' && !err) {
00454
00455 if (strlen(strbuf) > DRMS_MAXKEYNAMELEN)
00456 {
00457 fprintf(stderr,
00458 "Error: Keyword name expected but '%s' exceeds maximum name length.\n",
00459 strbuf);
00460 goto error;
00461 }
00462
00463 snprintf(pk, sizeof(pk), "%s", strbuf);
00464 explKW = 1;
00465 ++p;
00466 SKIPWS(p);
00467 keynum = -1;
00468
00469
00470 for (i=0; i<si->pidx_num; i++) {
00471 if (!strcasecmp (pk, si->pidx_keywords[i]->info->name)) {
00472 keynum = i;
00473 break;
00474 }
00475 }
00476 if (keynum == -1) {
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 nprimekey = hcon_lookup_lower(&(template->keywords), pk);
00494
00495 if (nprimekey == NULL)
00496 {
00497 fprintf(stderr,
00498 "Error: '%s' is not a keyword of series '%s'.\n",
00499 pk,
00500 si->seriesname);
00501 ++syntax_error;
00502 goto error;
00503 }
00504
00505 if (!drms_keyword_isslotted(nprimekey))
00506 {
00507
00508 fprintf(stderr,"Error: '%s' is not a primary index for series '%s'.\n",
00509 pk,si->seriesname);
00510 ++syntax_error;
00511 goto error;
00512 }
00513 }
00514 } else {
00515
00516
00517 keynum = prime_keynum++;
00518 if (keynum >= si->pidx_num) {
00519 fprintf(stderr, "Error: More primary keys are implied than exist (%d) "
00520 "for series %s\n", si->pidx_num, si->seriesname);
00521 goto error;
00522 }
00523 p = *in;
00524
00525
00526 }
00527
00528
00529 if (nprimekey != NULL)
00530 {
00531
00532 rl->primekey_rangeset = parse_slottedkey_set (nprimekey, &p);
00533 }
00534 else if (!explKW && drms_keyword_isindex(si->pidx_keywords[keynum]))
00535 {
00536
00537 DRMS_Keyword_t *slottedkey = GetSlottedKey(template, si->pidx_keywords[keynum]);
00538 rl->primekey_rangeset = parse_slottedkey_set (slottedkey, &p);
00539 }
00540 else
00541 {
00542
00543
00544 rl->primekey_rangeset = parse_primekey_set (si->pidx_keywords[keynum], &p);
00545 }
00546
00547 if (rl->primekey_rangeset == NULL) {
00548 fprintf (stderr, "Syntax error: Expected index list at '%s'\n", *in);
00549 ++syntax_error;
00550 goto error;
00551 }
00552 }
00553 *in = p;
00554 #ifdef DEBUG
00555 printf("got type = %d\nexit parse_record_set\n", rl->type);
00556 #endif
00557 return rl;
00558
00559 error:
00560 free (rl);
00561 return NULL;
00562 }
00563
00564 static PrimekeyRangeSet_t *parse_primekey_set(DRMS_Keyword_t *keyword,
00565 char **in)
00566 {
00567 PrimekeyRangeSet_t *pks;
00568 char *p=*in;
00569
00570 #ifdef DEBUG
00571 printf("enter parse_primekey_set\n");
00572 #endif
00573
00574 pks = malloc(sizeof( PrimekeyRangeSet_t));
00575 XASSERT(pks);
00576 pks->keyword = keyword;
00577 if (*p=='#')
00578 {
00579 pks->type = INDEX_RANGE;
00580 if ((pks->index_rangeset = parse_index_set(&p))==NULL &&
00581 syntax_error)
00582 goto error;
00583 }
00584 else
00585 {
00586 pks->type = VALUE_RANGE;
00587 if ((pks->value_rangeset = parse_value_set(keyword,&p))==NULL &&
00588 syntax_error)
00589 goto error;
00590 }
00591 *in=p;
00592
00593 #ifdef DEBUG
00594 printf("exit parse_primekey_set\n");
00595 #endif
00596 return pks;
00597
00598 error:
00599 free(pks);
00600 return NULL;
00601 }
00602
00603
00604
00605
00606 static PrimekeyRangeSet_t *parse_slottedkey_set(DRMS_Keyword_t *slotkey,
00607 char **in)
00608 {
00609 PrimekeyRangeSet_t *ret = NULL;
00610 ValueRangeSet_t *onerange = NULL;
00611
00612 if (drms_keyword_isslotted(slotkey))
00613 {
00614 ret = parse_primekey_set(slotkey, in);
00615
00616
00617
00618 if (ret->type == VALUE_RANGE &&
00619 ret->value_rangeset->type != FIRST_VALUE &&
00620 ret->value_rangeset->type != LAST_VALUE)
00621 {
00622 for (onerange = ret->value_rangeset; onerange != NULL; onerange = onerange->next)
00623 {
00624 DRMS_Value_t valin = {slotkey->info->type, onerange->start};
00625 DRMS_Value_t valout;
00626 DRMS_Value_t rangestart = valin;
00627
00628 drms_keyword_slotval2indexval(slotkey, &valin, &valout, NULL);
00629 onerange->start = valout.value;
00630
00631
00632 if (onerange->type == START_END)
00633 {
00634 valin.type = slotkey->info->type;
00635 valin.value = onerange->x;
00636 drms_keyword_slotval2indexval(slotkey, &valin, &valout, NULL);
00637 onerange->x = valout.value;
00638 }
00639 else if (onerange->type == START_DURATION)
00640 {
00641 valin.type = slotkey->info->type;
00642 valin.value = onerange->x;
00643 drms_keyword_slotval2indexval(slotkey,
00644 &valin,
00645 &valout,
00646 &rangestart);
00647 onerange->x = valout.value;
00648 }
00649 else if (onerange->type != SINGLE_VALUE)
00650 {
00651 fprintf(stderr,
00652 "Invalid range set type '%d'.\n",
00653 onerange->type);
00654 }
00655 }
00656 }
00657
00658
00659
00660 ret->keyword = drms_keyword_indexfromslot(slotkey);
00661 }
00662
00663 return ret;
00664 }
00665
00666 static IndexRangeSet_t *parse_index_set(char **in)
00667 {
00668 char *end,*p=*in;
00669 IndexRangeSet_t *head=NULL,*ir=NULL;
00670 #ifdef DEBUG
00671 printf("enter parse_index_set\n");
00672 #endif
00673
00674 do {
00675 if (ir)
00676 {
00677 ir->next = malloc(sizeof( IndexRangeSet_t));
00678 XASSERT(ir->next);
00679 ir = ir->next;
00680 memset(ir,0,sizeof( IndexRangeSet_t));
00681 }
00682 else {
00683 ir = malloc(sizeof( IndexRangeSet_t));
00684 XASSERT(ir);
00685 head = ir;
00686 memset(ir,0,sizeof( IndexRangeSet_t));
00687 }
00688 if (*p++ != '#')
00689 {
00690 fprintf(stderr,"Syntax Error: Index set must start with '#', found '%c', then '%s'.\n", *(p-1), p);
00691 ++syntax_error;
00692 goto error;
00693 }
00694
00695 if (*p=='^') {
00696 ir->type = FIRST_VALUE;
00697 p++;
00698 }
00699 else if (*p == '$') {
00700 ir->type = LAST_VALUE;
00701 p++;
00702 }
00703
00704 if (ir->type != FIRST_VALUE &&
00705 ir->type != LAST_VALUE) {
00706
00707 if (*p == '-') {
00708 ir->type = RANGE_END;
00709 } else {
00710
00711 ir->start = strtoll(p,&end,10);
00712 if (end==p)
00713 {
00714 fprintf(stderr,"Syntax Error: Expected integer start in index range, found '%s'.\n", p);
00715 ++syntax_error;
00716 goto error;
00717 }
00718 else
00719 p = end;
00720
00721 if (*p=='-')
00722 ir->type = START_END;
00723 else if (*p=='/')
00724 ir->type = START_DURATION;
00725 else
00726 ir->type = SINGLE_VALUE;
00727 }
00728
00729 if (ir->type != SINGLE_VALUE)
00730 {
00731 ++p;
00732
00733 if (ir->type != START_DURATION)
00734 {
00735 if (*p++!='#')
00736 {
00737 fprintf(stderr,"Syntax Error: Index set must start with '#', found '%c', then '%s'.\n", *(p-1), p);
00738 ++syntax_error;
00739 goto error;
00740 }
00741 }
00742
00743
00744 ir->x = strtoll(p,&end,10);
00745 if (end==p)
00746 {
00747 if (ir->type == START_DURATION) {
00748 fprintf(stderr,"Syntax Error: Expected integer for end or"
00749 " duration in index range., found '%s'\n", p);
00750 ++syntax_error;
00751 goto error;
00752 } else if (ir->type == RANGE_END) {
00753 ir->type = RANGE_ALL;
00754 } else {
00755 ir->type = RANGE_START;
00756 }
00757 }
00758 else
00759 p = end;
00760
00761 if (*p=='@')
00762 {
00763 ++p;
00764 ir->skip = strtoll(p,&end,10);
00765 if (end==p)
00766 {
00767 fprintf(stderr,"Syntax Error: Expected integer skip in index range, found '%s'.\n", p);
00768 ++syntax_error;
00769 goto error;
00770 }
00771 else
00772 p = end;
00773 }
00774 else
00775 ir->skip = 1;
00776 }
00777 #ifdef DEBUG
00778 printf("got type=%d, start=%lld, x=%lld, skip=%lld, p=%s\nexit parse_index_set\n",
00779 ir->type, ir->start, ir->x, ir->skip,p);
00780 #endif
00781 }
00782 } while(*p++ == ',');
00783 *in=p-1;
00784
00785 #ifdef DEBUG
00786 printf("exit parse_index_set\n");
00787 #endif
00788 return head;
00789
00790 error:
00791 while(head)
00792 { ir = head->next; free(head); head = ir; }
00793 return NULL;
00794 }
00795
00796 #ifdef OLDWAY_NEVER_USE
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 static char *AdjTimeZone(const char *timestr, DRMS_Keyword_t *keyword, int *len)
00825 {
00826
00827
00828 char *ret = NULL;
00829 int *year = NULL;
00830 int *month = NULL;
00831 int *dofm = NULL;
00832 int *hour = NULL;
00833 int *minute = NULL;
00834 double *second = NULL;
00835 double *juliday = NULL;
00836 char *zone = NULL;
00837
00838 char *lasts;
00839 char *tokenstr = strdup(timestr);
00840 *len = 0;
00841
00842 if (tokenstr)
00843 {
00844 if (parsetimestr(tokenstr, &year, &month, &dofm, NULL, &hour, &minute,
00845 &second, &zone, &juliday, len))
00846 {
00847 if (!zone)
00848 {
00849
00850
00851 ret = malloc(256);
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 if (juliday)
00863 {
00864 snprintf(ret, 256, "JD_%f_%s", *juliday, keyword->info->unit);
00865 }
00866 else
00867 {
00868 int hh = 0;
00869 int mm = 0;
00870 double sec = 0.0;
00871
00872 XASSERT(year != NULL && month != NULL && dofm != NULL);
00873
00874 if (hour)
00875 {
00876 hh = *hour;
00877 }
00878
00879 if (minute)
00880 {
00881 mm = *minute;
00882 }
00883
00884 if (second)
00885 {
00886 sec = *second;
00887 }
00888
00889 snprintf(ret, 256, "%d.%d.%d_%d:%d:%f_%s",
00890 *year, *month, *dofm, hh, mm, sec, keyword->info->unit);
00891 }
00892
00893 }
00894 }
00895 else
00896 {
00897 *len = 0;
00898 }
00899
00900 free(tokenstr);
00901 }
00902
00903 if (year)
00904 {
00905 free(year);
00906 }
00907
00908 if (month)
00909 {
00910 free(month);
00911 }
00912
00913 if (dofm)
00914 {
00915 free(dofm);
00916 }
00917
00918 if (hour)
00919 {
00920 free(hour);
00921 }
00922
00923 if (minute)
00924 {
00925 free(minute);
00926 }
00927
00928 if (second)
00929 {
00930 free(second);
00931 }
00932
00933 if (zone)
00934 {
00935 free(zone);
00936 }
00937
00938 if (juliday)
00939 {
00940 free(juliday);
00941 }
00942
00943 return ret;
00944 }
00945 #endif
00946
00947 static ValueRangeSet_t *parse_value_set(DRMS_Keyword_t *keyword,
00948 char **in)
00949 {
00950 int n;
00951 char *p=*in;
00952 ValueRangeSet_t *vr=NULL,*head=NULL;
00953 DRMS_Type_t datatype = drms_keyword_gettype(keyword);
00954 int gotstart;
00955 int stat;
00956 DRMS_Value_t vholder;
00957
00958 double step;
00959 int isslotted = 0;
00960
00961 isslotted = drms_keyword_isslotted(keyword);
00962
00963 if (isslotted)
00964 {
00965 step = drms_keyword_getslotstep(keyword, NULL, &stat);
00966
00967 if (stat != DRMS_SUCCESS)
00968 {
00969 goto error;
00970 }
00971 }
00972 else
00973 {
00974 step = 1.0;
00975 }
00976
00977 #ifdef DEBUG
00978 printf("enter parse_value_set\n");
00979 #endif
00980 do {
00981 gotstart = 0;
00982
00983 if (vr)
00984 {
00985 vr->next = malloc(sizeof( ValueRangeSet_t));
00986 XASSERT(vr->next);
00987 vr = vr->next;
00988 memset(vr,0,sizeof( ValueRangeSet_t));
00989 }
00990 else {
00991 vr = malloc(sizeof( ValueRangeSet_t));
00992 XASSERT(vr);
00993 head = vr;
00994 memset(vr,0,sizeof( ValueRangeSet_t));
00995 }
00996
00997 if (*p=='^') {
00998 vr->type = FIRST_VALUE;
00999 p++;
01000 }
01001 else if (*p == '$') {
01002 vr->type = LAST_VALUE;
01003 p++;
01004 }
01005
01006 if (vr->type != FIRST_VALUE &&
01007 vr->type != LAST_VALUE) {
01008
01009
01010
01011
01012
01013 if ((datatype == DRMS_TYPE_TIME ||
01014 datatype == DRMS_TYPE_FLOAT ||
01015 datatype == DRMS_TYPE_DOUBLE) &&
01016 drms_keyword_isslotted(keyword) &&
01017 is_duration(p))
01018 {
01019
01020
01021 double offset;
01022 double base;
01023
01024 if (!parse_duration(&p, &offset, step))
01025 {
01026
01027
01028 base = drms_keyword_getslotbase(keyword, &stat);
01029 if (stat == DRMS_SUCCESS)
01030 {
01031 DRMS_Type_Value_t sum;
01032 sum.double_val = base + offset;
01033 drms_convert(datatype, &(vr->start), DRMS_TYPE_DOUBLE, &sum);
01034 gotstart = 1;
01035 }
01036 }
01037 }
01038
01039 if (!gotstart)
01040 {
01041 int adv = -1;
01042 if (datatype == DRMS_TYPE_TIME)
01043 {
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 adv = sscan_time_ext(p, &(vholder.value.time_val));
01055
01056
01057
01058
01059
01060
01061 while (*(p + adv) == ' ')
01062 {
01063 adv++;
01064 }
01065
01066 if (*(p + adv) != ']' && *(p + adv) != '-' && *(p + adv) != '/')
01067 {
01068
01069 char *tmp = strdup(p);
01070 char *dash = NULL;
01071
01072 if (tmp)
01073 {
01074 dash = strchr(tmp, '-');
01075 if (dash)
01076 {
01077 *dash = '\0';
01078 adv = sscan_time_ext(tmp, &(vholder.value.time_val));
01079 }
01080
01081 free(tmp);
01082 }
01083 }
01084
01085 if (adv > 0)
01086 {
01087 p += adv;
01088 }
01089 else
01090 {
01091 fprintf(stderr,"Syntax Error: Expected either time duraton "
01092 "or start value of type %s in "
01093 "value range, found '%s'.\n", drms_type2str(datatype), p);
01094 goto error;
01095 }
01096 }
01097 else
01098 {
01099 if ((n = drms_sscanf2(p, ",]", 1, datatype, &vholder)) == 0 || n == -1)
01100 {
01101 fprintf(stderr,"Syntax Error: Expected either time duraton "
01102 "or start value of type %s in "
01103 "value range, found '%s'.\n", drms_type2str(datatype), p);
01104 goto error;
01105 }
01106
01107 p += n;
01108 }
01109
01110 vr->start = vholder.value;
01111 memset(&(vholder.value), 0, sizeof(DRMS_Type_Value_t));
01112 }
01113
01114 if (*p=='-')
01115 {
01116 vr->type = START_END;
01117 ++p;
01118 }
01119 else if (*p=='/')
01120 {
01121 vr->type = START_DURATION;
01122 ++p;
01123 }
01124 else
01125 vr->type = SINGLE_VALUE;
01126
01127
01128 if (vr->type != SINGLE_VALUE)
01129 {
01130
01131 while (*p == ' ')
01132 {
01133 ++p;
01134 };
01135
01136
01137 if (datatype==DRMS_TYPE_TIME)
01138 {
01139 double dval = 0.0;
01140 DRMS_Type_Value_t dvalval;
01141
01142
01143 if (vr->type == START_END)
01144 {
01145 int adv = -1;
01146 adv = sscan_time_ext(p, NULL);
01147
01148 if ((n = drms_sscanf2(p, ",]", 0, datatype, &vholder)) == 0)
01149 {
01150 fprintf(stderr,"Syntax Error: Expected end value of"
01151 " type %s in value range, found '%s'.\n",drms_type2str(datatype), p);
01152 goto error;
01153 }
01154 else if (adv > 0)
01155 {
01156 p += adv;
01157 }
01158 else
01159 {
01160 p += n;
01161 }
01162 vr->x = vholder.value;
01163 memset(&(vholder.value), 0, sizeof(DRMS_Type_Value_t));
01164 }
01165 else
01166 {
01167
01168 if (parse_duration(&p,&dval,step))
01169 {
01170 fprintf(stderr,"Syntax Error: Expected time or float duration "
01171 " in value range, found '%s'.\n", p);
01172 goto error;
01173 }
01174
01175 dvalval.double_val = dval;
01176 drms_convert(datatype, &(vr->x), DRMS_TYPE_DOUBLE, &dvalval);
01177
01178 }
01179
01180 if (*p=='@')
01181 {
01182 ++p;
01183 vr->has_skip = 1;
01184
01185 if (parse_duration(&p,&dval,step))
01186 {
01187 fprintf(stderr,"Syntax Error: Expected skip (time duration)"
01188 " in value range, found '%s'.\n", p);
01189 goto error;
01190 }
01191
01192
01193
01194
01195 if (isslotted)
01196 {
01197 double exact = dval / step;
01198 double rounded = round(dval / step);
01199
01200 if (fabs(exact - rounded) > 1.0e-11 * (fabs(exact) + fabs(rounded)))
01201 {
01202 fprintf(stderr, "NOTE: the skip value '%f' is not a multiple of step size; rounding to nearest step-size multiple '%f'\n", dval, rounded * step);
01203 }
01204
01205 dvalval.double_val = rounded;
01206 drms_convert(DRMS_TYPE_LONGLONG, &(vr->skip), DRMS_TYPE_DOUBLE, &dvalval);
01207 }
01208 else
01209 {
01210
01211 dvalval.double_val = dval;
01212 drms_convert(datatype, &(vr->skip), DRMS_TYPE_DOUBLE, &dvalval);
01213 }
01214 }
01215 else
01216 vr->has_skip = 0;
01217 }
01218 else
01219 {
01220 double dval = 0.0;
01221 DRMS_Type_Value_t dvalval;
01222
01223 if (vr->type == START_DURATION &&
01224 keyword->info->recscope == kRecScopeType_SLOT &&
01225 is_duration(p))
01226 {
01227
01228
01229
01230 if (parse_duration(&p, &dval, step))
01231 {
01232 fprintf(stderr,"Syntax Error: Expected skip (time duration)"
01233 " in value range, found '%s'.\n", p);
01234 goto error;
01235 }
01236
01237 dvalval.double_val = dval;
01238 drms_convert(datatype, &(vr->x), DRMS_TYPE_DOUBLE, &dvalval);
01239 }
01240 else
01241 {
01242 if ((n = drms_sscanf2(p, ",]", 0, datatype, &vholder)) == 0)
01243 {
01244 fprintf(stderr,"Syntax Error: Expected end or duration value of"
01245 " type %s in value range, found '%s'.\n",drms_type2str(datatype), p);
01246 goto error;
01247 }
01248 else
01249 {
01250 vr->x = vholder.value;
01251 memset(&(vholder.value), 0, sizeof(DRMS_Type_Value_t));
01252 p+=n;
01253 }
01254 }
01255
01256 if (*p=='@')
01257 {
01258 ++p;
01259 vr->has_skip = 1;
01260
01261
01262 if (keyword->info->recscope == kRecScopeType_SLOT && is_duration(p))
01263 {
01264 if (parse_duration(&p, &dval, step))
01265 {
01266 fprintf(stderr,"Syntax Error: Expected skip (time duration)"
01267 " in value range, found '%s'.\n", p);
01268 goto error;
01269 }
01270
01271
01272
01273
01274 if (isslotted)
01275 {
01276 double exact = dval / step;
01277 double rounded = round(dval / step);
01278
01279 if (fabs(exact - rounded) > 1.0e-11 * (fabs(exact) + fabs(rounded)))
01280 {
01281 fprintf(stderr, "NOTE: the skip value '%f' is not a multiple of step size; rounding to nearest step-size multiple '%f'\n", dval, rounded * step);
01282 }
01283
01284 dvalval.double_val = rounded;
01285 drms_convert(DRMS_TYPE_LONGLONG, &(vr->skip), DRMS_TYPE_DOUBLE, &dvalval);
01286 }
01287 else
01288 {
01289
01290 dvalval.double_val = dval;
01291 drms_convert(datatype, &(vr->skip), DRMS_TYPE_DOUBLE, &dvalval);
01292 }
01293 }
01294 else
01295 {
01296 if ((n = drms_sscanf2(p, ",]", 0, datatype, &vholder)) == 0)
01297 {
01298 fprintf(stderr,"Syntax Error: Expected skip value of type %s in"
01299 " value range, found '%s'.\n",drms_type2str(datatype), p);
01300 goto error;
01301 }
01302
01303 vr->skip = vholder.value;
01304 memset(&(vholder.value), 0, sizeof(DRMS_Type_Value_t));
01305 p+=n;
01306 }
01307 }
01308 else
01309 vr->has_skip = 0;
01310 }
01311 #ifdef DEBUG
01312 printf("got type=%d ",vr->type);
01313 printf("got datatype=");
01314 printf("%s",drms_type2str(datatype));
01315 printf(", start=");
01316 drms_printfval(datatype, &vr->start);
01317 printf(" ,x=");
01318 drms_printfval(datatype, &vr->x);
01319 if (vr->has_skip)
01320 {
01321 printf(", skip=");
01322 drms_printfval(datatype, &vr->ski);
01323 }
01324 printf("\n");
01325 #endif
01326 }
01327 }
01328 } while(*p++ == ',');
01329
01330 *in=p-1;
01331 #ifdef DEBUG
01332 printf("exit parse_value_set\n");
01333 #endif
01334 return head;
01335
01336 error:
01337 printf("ERROR\n");
01338 while(head)
01339 { vr = head->next; free(head); head = vr; }
01340 return NULL;
01341 }
01342
01343
01344 static int is_duration(const char *in)
01345 {
01346 char *end = NULL;
01347 const char *p = in;
01348 double dval;
01349 int ret = 0;
01350
01351 dval = (int)strtod(p,&end);
01352 if ( (IsZero(dval) && end==p) ||
01353 ((IsPosHugeVal(dval) || IsNegHugeVal(dval)) && errno==ERANGE))
01354 {
01355 ret = 0;
01356 }
01357 else
01358 {
01359 p = end;
01360
01361 switch(*p++)
01362 {
01363 case 's':
01364 case 'm':
01365 case 'h':
01366 case 'd':
01367 case 'u':
01368 ret = 1;
01369 break;
01370 default:
01371 break;
01372 }
01373 }
01374
01375 return ret;
01376 }
01377
01378
01379 static int parse_duration(char **in, double *duration, double width)
01380 {
01381 char *end, *p = *in;
01382 double dval;
01383
01384 dval = strtod(p,&end);
01385 if ( (IsZero(dval) && end==p) ||
01386 ((IsPosHugeVal(dval) || IsNegHugeVal(dval)) && errno==ERANGE))
01387 {
01388 fprintf(stderr,"Syntax Error: Expected finite floating point value at "
01389 "beginning of time duration, found '%s'.\n", p);
01390 ++syntax_error;
01391 goto error;
01392 }
01393 else
01394 p = end;
01395 switch(*p++)
01396 {
01397 case 's':
01398 *duration = 1.0*dval;
01399 break;
01400 case 'm':
01401 *duration = 60.0*dval;
01402 break;
01403 case 'h':
01404 *duration = 3600.0*dval;
01405 break;
01406 case 'd':
01407 *duration = 86400.0*dval;
01408 break;
01409 case 'u':
01410
01411
01412 *duration = width*dval;
01413 break;
01414 default:
01415 fprintf(stderr,"Syntax Error: Time duration unit must be one of 's', "
01416 "'m', 'h', 'd', 'u', found '%c', '%s'.\n", *(p-1), p);
01417 ++syntax_error;
01418 goto error;
01419 }
01420 *in = p;
01421 return 0;
01422 error:
01423 return 1;
01424 }
01425
01426 int drms_names_parseduration(char **in, double *duration, double width)
01427 {
01428 char *tmp = strdup(*in);
01429 int ret = 1;
01430
01431 if (tmp)
01432 {
01433 char *tmp2 = tmp;
01434 ret = parse_duration(&tmp2, duration, width);
01435 free(tmp);
01436 }
01437
01438 return ret;
01439 }
01440
01441 int drms_names_parsedegreedelta(char **deltastr, DRMS_SlotKeyUnit_t *unit, double *delta)
01442 {
01443 char *end, *p = *deltastr;
01444 double dval;
01445 char *unitstr = NULL;
01446
01447 dval = (int)strtod(p,&end);
01448 if ( (IsZero(dval) && end==p) ||
01449 ((IsPosHugeVal(dval) || IsNegHugeVal(dval)) && errno==ERANGE))
01450 {
01451 fprintf(stderr,"Syntax Error: Expected finite floating point value at "
01452 "beginning of time duration, found '%s'.\n", p);
01453 ++syntax_error;
01454 goto error;
01455 }
01456 else
01457 p = end;
01458
01459 unitstr = p;
01460
01461 if (strncasecmp(unitstr, "d", 1) == 0)
01462 {
01463 *delta = dval;
01464 if (unit)
01465 {
01466 *unit = kSlotKeyUnit_Degrees;
01467 }
01468 p++;
01469 }
01470 else if (strncasecmp(unitstr, "m", 1) == 0)
01471 {
01472 *delta = 60.0 * dval;
01473 if (unit)
01474 {
01475 *unit = kSlotKeyUnit_Arcminutes;
01476 }
01477 p++;
01478 }
01479 else if (strncasecmp(unitstr, "s", 1) == 0)
01480 {
01481 *delta = 3600.0 * dval;
01482 *unit = kSlotKeyUnit_Arcseconds;
01483 p++;
01484 }
01485 else if (strncasecmp(unitstr, "ms", 2) == 0)
01486 {
01487 *delta = 3600000.0 * dval;
01488 *unit = kSlotKeyUnit_MAS;
01489 p++;
01490 p++;
01491 }
01492 else if (strncasecmp(unitstr, "r", 1) == 0)
01493 {
01494 *delta = ((M_PI) / 648000) * dval;
01495 if (unit)
01496 {
01497 *unit = kSlotKeyUnit_Radians;
01498 }
01499 p++;
01500 }
01501 else if (strncasecmp(unitstr, "ur", 2) == 0)
01502 {
01503 *delta = ((M_PI) / 648000) * 1000000.0 * dval;
01504 if (unit)
01505 {
01506 *unit = kSlotKeyUnit_MicroRadians;
01507 }
01508 p++;
01509 p++;
01510 }
01511 else
01512 {
01513 fprintf(stderr,"Syntax Error: Degree delta unit must be one of 'd', "
01514 "'m', 's', 'ms', 'r', 'ur', found '%s'.\n", unitstr);
01515 ++syntax_error;
01516 goto error;
01517 }
01518
01519 *deltastr = p;
01520 return 0;
01521 error:
01522 return 1;
01523 }
01524
01525
01526
01527 static int sql_record_set_filter(RecordSet_Filter_t *rs, char *seriesname, char **query, int sizeq, char **pkwhere, int sizep, char **npkwhere, int sizen, HContainer_t *pkwhereNFL);
01528 static int sql_record_query(RecordQuery_t *rs, char **query, int sizeq);
01529 static int sql_record_list(RecordList_t *rs, char *seriesname, char **query, int sizeq);
01530 static int sql_recnum_set(IndexRangeSet_t *rs, char *seriesname, char **query, int sizeq);
01531 static int sql_primekey_set(PrimekeyRangeSet_t *rs, char *seriesname,char **query, int sizeq);
01532 static int sql_primekey_index_set(IndexRangeSet_t *rs, DRMS_Keyword_t *keyword,
01533 char *seriesname, char **query);
01534 static int sql_primekey_value_set(ValueRangeSet_t *rs, DRMS_Keyword_t *keyword,
01535 char *seriesname, char **query);
01536
01537
01538
01539 static int sql_record_set(RecordSet_t *rs,
01540 char *seriesname,
01541 char *query,
01542 int sizeq,
01543 char *pkwhere,
01544 int sizep,
01545 char *npkwhere,
01546 int sizen,
01547 HContainer_t *pkwhereNFL)
01548 {
01549 char *p=query;
01550
01551 #ifdef DEBUG
01552 printf("Enter sql_record_set\n");
01553 #endif
01554
01555
01556
01557
01558 #ifdef DEBUG
01559 printf("Exit sql_record_set\n");
01560 #endif
01561 if (rs->recordset_spec)
01562 {
01563
01564 return sql_record_set_filter(rs->recordset_spec, seriesname, &p, sizeq, &pkwhere, sizep, &npkwhere, sizen, pkwhereNFL);
01565 }
01566 else
01567 {
01568 *p = 0;
01569 *pkwhere = '\0';
01570 *npkwhere = '\0';
01571 return 0;
01572 }
01573 }
01574
01575 static int sql_record_set_filter(RecordSet_Filter_t *rs, char *seriesname, char **query, int sizeq, char **pkwhere, int sizep, char **npkwhere, int sizen, HContainer_t *pkwhereNFL)
01576 {
01577 #ifdef DEBUG
01578 printf("Enter sql_record_set_filter\n");
01579 #endif
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593 char whereclz[DRMS_MAXQUERYLEN] = {0};
01594 char pkwherebuf[DRMS_MAXQUERYLEN] = {0};
01595 char npkwherebuf[DRMS_MAXQUERYLEN] = {0};
01596 char wherebuf[DRMS_MAXQUERYLEN];
01597 char *bogus = NULL;
01598 int isfirstlast = 0;
01599
01600 do {
01601 memset(wherebuf, sizeof(wherebuf), 0);
01602 bogus = wherebuf;
01603
01604
01605 snprintf(wherebuf, sizeof(wherebuf), "( ");
01606 bogus +=2;
01607
01608 switch(rs->type)
01609 {
01610 case RECORDQUERY:
01611 sql_record_query(rs->record_query, &bogus, sizeof(wherebuf) - 2);
01612 break;
01613 case RECORDLIST:
01614 sql_record_list(rs->record_list, seriesname, &bogus, sizeof(wherebuf) - 2);
01615 break;
01616 default:
01617 fprintf(stderr,"Wrong type (%d) in sql_record_set_filter.\n",
01618 rs->type);
01619 return 1;
01620 }
01621
01622 isfirstlast = (rs->type == RECORDLIST &&
01623 rs->record_list->type == PRIMEKEYSET &&
01624 ((rs->record_list->primekey_rangeset->type == INDEX_RANGE &&
01625 (rs->record_list->primekey_rangeset->index_rangeset->type == FIRST_VALUE ||
01626 rs->record_list->primekey_rangeset->index_rangeset->type == LAST_VALUE)) ||
01627 (rs->record_list->primekey_rangeset->type == VALUE_RANGE &&
01628 (rs->record_list->primekey_rangeset->value_rangeset->type == FIRST_VALUE ||
01629 rs->record_list->primekey_rangeset->value_rangeset->type == LAST_VALUE)
01630 )));
01631
01632
01633
01634
01635
01636
01637 if (*whereclz && strlen(wherebuf) && isfirstlast)
01638 {
01639
01640 char *pin = &(wherebuf[strlen(wherebuf) - 1]);
01641 char savebuf[DRMS_MAXQUERYLEN] = {0};
01642
01643 while (*pin == ')' || *pin == ' ')
01644 {
01645 pin--;
01646 }
01647
01648 pin++;
01649 snprintf(savebuf, sizeof(savebuf), "%s", pin);
01650 *pin = '\0';
01651
01652 base_strlcat(pin, " WHERE ( ", sizeof(wherebuf) - (pin - wherebuf));
01653
01654
01655 base_strlcat(pin, whereclz, sizeof(wherebuf) - (pin - wherebuf));
01656
01657 base_strlcat(pin, " )", sizeof(wherebuf) - (pin - wherebuf));
01658
01659
01660 base_strlcat(wherebuf, savebuf, sizeof(wherebuf));
01661
01662
01663 base_strlcat(wherebuf, " )", sizeof(wherebuf));
01664
01665
01666 base_strlcat(whereclz, " AND ", sizeof(whereclz));
01667 base_strlcat(whereclz, wherebuf, sizeof(whereclz));
01668
01669
01670 if (*pkwherebuf)
01671 {
01672 *pin = '\0';
01673 base_strlcat(pin, " WHERE ( ", sizeof(wherebuf) - (pin - wherebuf));
01674 base_strlcat(pin, pkwherebuf, sizeof(wherebuf) - (pin - wherebuf));
01675 base_strlcat(pin, " )", sizeof(wherebuf) - (pin - wherebuf));
01676 base_strlcat(wherebuf, savebuf, sizeof(wherebuf));
01677 base_strlcat(wherebuf, " )", sizeof(wherebuf));
01678 base_strlcat(pkwherebuf, " AND ", sizeof(pkwherebuf));
01679 base_strlcat(pkwherebuf, wherebuf, sizeof(pkwherebuf));
01680 }
01681
01682
01683
01684 }
01685 else
01686 {
01687
01688 base_strlcat(wherebuf, " )", sizeof(wherebuf));
01689
01690 if (*whereclz)
01691 {
01692
01693 base_strlcat(whereclz, " AND ", sizeof(whereclz));
01694 }
01695
01696 base_strlcat(whereclz, wherebuf, sizeof(whereclz));
01697
01698
01699
01700 if (rs->type == RECORDLIST && rs->record_list->type == PRIMEKEYSET)
01701 {
01702
01703 if (*pkwherebuf)
01704 {
01705 base_strlcat(pkwherebuf, " AND ", sizeof(pkwherebuf));
01706 }
01707
01708 base_strlcat(pkwherebuf, wherebuf, sizeof(pkwherebuf));
01709
01710
01711
01712
01713 if (!isfirstlast)
01714 {
01715 char *dup = strdup(wherebuf);
01716 if (dup)
01717 {
01718 hcon_insert_lower(pkwhereNFL, rs->record_list->primekey_rangeset->keyword->info->name, &dup);
01719 }
01720 else
01721 {
01722
01723 }
01724 }
01725 }
01726 else
01727 {
01728 if (*npkwherebuf)
01729 {
01730 base_strlcat(npkwherebuf, " AND ", sizeof(npkwherebuf));
01731 }
01732
01733 base_strlcat(npkwherebuf, wherebuf, sizeof(npkwherebuf));
01734 }
01735 }
01736
01737 rs = rs->next;
01738 } while (rs);
01739 #ifdef DEBUG
01740 printf("Added '%s'\nExit sql_record_set_filter\n",*query);
01741 #endif
01742
01743
01744
01745 sprintf(*query, whereclz);
01746 *query += strlen(whereclz);
01747
01748 snprintf(*pkwhere, sizep, "%s", pkwherebuf);
01749 snprintf(*npkwhere, sizen, "%s", npkwherebuf);
01750
01751 return 0;
01752 }
01753
01754
01755 static int sql_record_query(RecordQuery_t *rs, char **query, int sizeq)
01756 {
01757 char *p=*query;
01758 #ifdef DEBUG
01759 printf("Enter sql_record_query\n");
01760 #endif
01761 p += sprintf(p,"%s ",rs->where);
01762 #ifdef DEBUG
01763 printf("Added '%s '\nExit sql_record_query\n",*query);
01764 #endif
01765 *query=p;
01766 return 0;
01767 }
01768
01769 static int sql_record_list(RecordList_t *rs, char *seriesname, char **query, int sizeq)
01770 {
01771 char *p=*query;
01772 #ifdef DEBUG
01773 printf("Enter sql_record_list\n");
01774 #endif
01775
01776 switch(rs->type)
01777 {
01778 case RECNUMSET:
01779 sql_recnum_set(rs->recnum_rangeset, seriesname, &p, sizeq);
01780 break;
01781 case PRIMEKEYSET:
01782 sql_primekey_set(rs->primekey_rangeset, seriesname, &p, sizeq);
01783 break;
01784 default:
01785 fprintf(stderr,"Wrong type (%d) in sql_record_list.\n",
01786 rs->type);
01787 return 1;
01788 }
01789
01790 #ifdef DEBUG
01791 printf("Added '%s'\nExit sql_record_list\n",*query);
01792 #endif
01793 *query=p;
01794 return 0;
01795 }
01796
01797 static int sql_recnum_set(IndexRangeSet_t *rs, char *seriesname, char **query, int sizeq)
01798 {
01799 char *p=*query;
01800 size_t bufSz = DRMS_MAXQUERYLEN;
01801 char *buf = calloc(1, bufSz);
01802 char numBuf[64];
01803
01804 XASSERT(buf);
01805
01806 #ifdef DEBUG
01807 printf("Enter sql_recnum_set\n");
01808 #endif
01809
01810
01811
01812 IndexRangeSet_t *pRS = rs;
01813 int doRecnumIn = 1;
01814
01815 while (pRS)
01816 {
01817 if (pRS->type != FIRST_VALUE && pRS->type != LAST_VALUE && pRS->type != SINGLE_VALUE)
01818 {
01819 doRecnumIn = 0;
01820 break;
01821 }
01822
01823 pRS = pRS->next;
01824 }
01825
01826 if (doRecnumIn && rs)
01827 {
01828 buf = base_strcatalloc(buf, "recnum in (", &bufSz); XASSERT(buf);
01829 while (rs)
01830 {
01831 if (rs->type == FIRST_VALUE)
01832 {
01833
01834 buf = base_strcatalloc(buf, "(select min(recnum) from ", &bufSz); XASSERT(buf);
01835 buf = base_strcatalloc(buf, seriesname, &bufSz); XASSERT(buf);
01836 buf = base_strcatalloc(buf, ")", &bufSz); XASSERT(buf);
01837 }
01838 else if (rs->type == LAST_VALUE)
01839 {
01840
01841 buf = base_strcatalloc(buf, "(select max(recnum) from ", &bufSz); XASSERT(buf);
01842 buf = base_strcatalloc(buf, seriesname, &bufSz); XASSERT(buf);
01843 buf = base_strcatalloc(buf, ")", &bufSz); XASSERT(buf);
01844 }
01845 else if (rs->type == SINGLE_VALUE)
01846 {
01847
01848 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01849 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01850 }
01851
01852 if (rs->next)
01853 {
01854
01855 buf = base_strcatalloc(buf, ", ", &bufSz); XASSERT(buf);
01856 }
01857
01858 rs = rs->next;
01859 }
01860
01861 buf = base_strcatalloc(buf, ")", &bufSz); XASSERT(buf);
01862 }
01863 else if (rs)
01864 {
01865 do
01866 {
01867
01868 buf = base_strcatalloc(buf, "( ", &bufSz); XASSERT(buf);
01869
01870 if (rs->type == FIRST_VALUE)
01871 {
01872
01873 buf = base_strcatalloc(buf, "recnum=(select min(recnum) from ", &bufSz); XASSERT(buf);
01874 buf = base_strcatalloc(buf, seriesname, &bufSz); XASSERT(buf);
01875 buf = base_strcatalloc(buf, ")", &bufSz); XASSERT(buf);
01876 }
01877 else if (rs->type == LAST_VALUE)
01878 {
01879
01880 buf = base_strcatalloc(buf, "recnum=(select max(recnum) from ", &bufSz); XASSERT(buf);
01881 buf = base_strcatalloc(buf, seriesname, &bufSz); XASSERT(buf);
01882 buf = base_strcatalloc(buf, ")", &bufSz); XASSERT(buf);
01883 }
01884 else if (rs->type == SINGLE_VALUE)
01885 {
01886
01887 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01888 buf = base_strcatalloc(buf, "recnum=", &bufSz); XASSERT(buf);
01889 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01890 }
01891 else
01892 {
01893 if (rs->type == RANGE_ALL)
01894 {
01895
01896 buf = base_strcatalloc(buf, "1 = 1 ", &bufSz); XASSERT(buf);
01897 }
01898 else if (rs->type == RANGE_START)
01899 {
01900
01901 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01902 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01903 buf = base_strcatalloc(buf, "<=recnum ", &bufSz); XASSERT(buf);
01904 }
01905 else if (rs->type == RANGE_END)
01906 {
01907
01908 buf = base_strcatalloc(buf, "recnum<=", &bufSz); XASSERT(buf);
01909 snprintf(numBuf, sizeof(numBuf), "%lld", rs->x);
01910 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01911 }
01912 else if (rs->type == START_END)
01913 {
01914
01915 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01916 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01917 buf = base_strcatalloc(buf, "<=recnum AND recnum<=", &bufSz); XASSERT(buf);
01918 snprintf(numBuf, sizeof(numBuf), "%lld", rs->x);
01919 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01920 }
01921 else if (rs->type == START_DURATION)
01922 {
01923
01924 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01925 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01926 buf = base_strcatalloc(buf, "<=recnum AND recnum<", &bufSz); XASSERT(buf);
01927 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start+rs->x);
01928 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01929 }
01930
01931 if (rs->skip!=1)
01932 {
01933 if (rs->type == RANGE_END || rs->type == RANGE_ALL)
01934 {
01935
01936 buf = base_strcatalloc(buf, " AND (recnum-(select min(recnum) from ", &bufSz); XASSERT(buf);
01937 buf = base_strcatalloc(buf, seriesname, &bufSz); XASSERT(buf);
01938 buf = base_strcatalloc(buf, "))%", &bufSz); XASSERT(buf);
01939 snprintf(numBuf, sizeof(numBuf), "%lld", rs->skip);
01940 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01941 buf = base_strcatalloc(buf, "=0 ", &bufSz); XASSERT(buf);
01942 }
01943 else
01944 {
01945
01946 buf = base_strcatalloc(buf, " AND (recnum-", &bufSz); XASSERT(buf);
01947 snprintf(numBuf, sizeof(numBuf), "%lld", rs->start);
01948 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01949 buf = base_strcatalloc(buf, ")%", &bufSz); XASSERT(buf);
01950 snprintf(numBuf, sizeof(numBuf), "%lld", rs->skip);
01951 buf = base_strcatalloc(buf, numBuf, &bufSz); XASSERT(buf);
01952 buf = base_strcatalloc(buf, "=0 ", &bufSz); XASSERT(buf);
01953 }
01954 }
01955 }
01956
01957
01958 buf = base_strcatalloc(buf, " )", &bufSz); XASSERT(buf);
01959 if (rs->next)
01960 {
01961
01962 buf = base_strcatalloc(buf, " OR ", &bufSz); XASSERT(buf);
01963 }
01964 rs = rs->next;
01965 }
01966 while (rs);
01967 }
01968
01969
01970 snprintf(*query, sizeq, buf);
01971
01972 #ifdef DEBUG
01973 printf("Added '%s'\nExit sql_recnum_set\n",*query);
01974 #endif
01975
01976 *query += strlen(buf);
01977
01978 free(buf);
01979 buf = NULL;
01980
01981 return 0;
01982 }
01983
01984
01985 static int sql_primekey_set(PrimekeyRangeSet_t *rs, char *seriesname, char **query, int sizeq)
01986 {
01987 if (rs->type == INDEX_RANGE)
01988 return sql_primekey_index_set(rs->index_rangeset, rs->keyword, seriesname, query);
01989 else if(rs->type == VALUE_RANGE)
01990 return sql_primekey_value_set(rs->value_rangeset, rs->keyword, seriesname, query);
01991 else
01992 return 1;
01993 }
01994
01995
01996 static int sql_primekey_index_set(IndexRangeSet_t *rs, DRMS_Keyword_t *keyword,
01997 char *seriesname, char **query)
01998 {
01999 char *p=*query;
02000 DRMS_Type_t datatype;
02001 DRMS_Type_Value_t base, step, tmpval;
02002 double dbase;
02003 double dstep;
02004 int drmsstat = DRMS_SUCCESS;
02005
02006 #ifdef DEBUG
02007 printf("Enter sql_primekey_index_set\n");
02008 #endif
02009
02010
02011
02012 datatype = keyword->info->type;
02013
02014
02015
02016
02017 if (drms_keyword_isindex(keyword))
02018 {
02019
02020
02021
02022
02023
02024 dbase = 0;
02025 dstep = 1;
02026 }
02027 else
02028 {
02029
02030 dbase = drms_keyword_getvalkeybase(keyword, &drmsstat);
02031 dstep = drms_keyword_getvalkeystep(keyword, &drmsstat);
02032 }
02033
02034 if (drms_ismissing_double(dbase))
02035 {
02036 dbase = 0.0;
02037 }
02038
02039 base.string_val = NULL;
02040 tmpval.double_val = dbase;
02041 drms_convert(datatype, &base, DRMS_TYPE_DOUBLE, &tmpval);
02042
02043 if (drms_ismissing_double(dstep))
02044 {
02045 dstep = 1.0;
02046 }
02047
02048 step.string_val = NULL;
02049 tmpval.double_val = dstep;
02050 drms_convert(datatype, &step, DRMS_TYPE_DOUBLE, &tmpval);
02051
02052 do {
02053 p += sprintf(p,"( ");
02054
02055
02056 if (rs->type == FIRST_VALUE) {
02057 p += sprintf(p,"%s=(select min(%s) from %s)", keyword->info->name, keyword->info->name, seriesname);
02058 } else if (rs->type == LAST_VALUE) {
02059 p += sprintf(p,"%s=(select max(%s) from %s)", keyword->info->name, keyword->info->name, seriesname);
02060 } else if (rs->type == SINGLE_VALUE)
02061 {
02062 p += sprintf(p,"%s=((%lld*",keyword->info->name,rs->start);
02063 p += drms_sprintfval(p, datatype, &step, 1);
02064 p += sprintf(p,")+");
02065 p += drms_sprintfval(p, datatype, &base, 1);
02066 p += sprintf(p,")");
02067 }
02068 else
02069 {
02070 if (rs->type == RANGE_ALL) {
02071 p += sprintf(p,"1 = 1 ");
02072 } else if (rs->type == RANGE_START) {
02073 p += sprintf(p,"%s>=((%lld*",keyword->info->name,rs->start);
02074 p += drms_sprintfval(p, datatype, &step, 1);
02075 p += sprintf(p,")+");
02076 p += drms_sprintfval(p, datatype, &base, 1);
02077 p += sprintf(p,") ");
02078 } else if (rs->type == RANGE_END) {
02079 p += sprintf(p,"%s<=((%lld*",keyword->info->name,rs->x);
02080 p += drms_sprintfval(p, datatype, &step, 1);
02081 p += sprintf(p,")+");
02082 p += drms_sprintfval(p, datatype, &base, 1);
02083 p += sprintf(p,") ");
02084 } else if (rs->type == START_END) {
02085 p += sprintf(p,"%s>=((%lld*",keyword->info->name,rs->start);
02086 p += drms_sprintfval(p, datatype, &step, 1);
02087 p += sprintf(p,")+");
02088 p += drms_sprintfval(p, datatype, &base, 1);
02089 p += sprintf(p,") AND %s<=((%lld*",keyword->info->name,rs->x);
02090 p += drms_sprintfval(p, datatype, &step, 1);
02091 p += sprintf(p,")+");
02092 p += drms_sprintfval(p, datatype, &base, 1);
02093 p += sprintf(p,")");
02094 }
02095 else if (rs->type == START_DURATION)
02096 {
02097 p += sprintf(p,"%s>=((%lld*",keyword->info->name,rs->start);
02098 p += drms_sprintfval(p, datatype, &step, 1);
02099 p += sprintf(p,")+");
02100 p += drms_sprintfval(p, datatype, &base, 1);
02101 p += sprintf(p,") AND %s<((%lld*",keyword->info->name,rs->start+rs->x);
02102 p += drms_sprintfval(p, datatype, &step, 1);
02103 p += sprintf(p,")+");
02104 p += drms_sprintfval(p, datatype, &base, 1);
02105 p += sprintf(p,")");
02106 }
02107 if (rs->skip!=1)
02108 {
02109 if (rs->type == RANGE_END || rs->type == RANGE_ALL)
02110 p += sprintf(p," AND (cast (round((%s-(select min(%s) from %s))/",keyword->info->name, keyword->info->name, seriesname);
02111 else
02112 p += sprintf(p," AND (cast (round((%s-%lld)/",keyword->info->name, rs->start);
02113 p += drms_sprintfval(p, datatype, &step, 1);
02114 p += sprintf(p,") as integer) %%%lld)=0",rs->skip);
02115 }
02116 }
02117 p += sprintf(p," )");
02118 if (rs->next)
02119 p += sprintf(p," OR ");
02120 rs = rs->next;
02121 }
02122 while (rs);
02123
02124 #ifdef DEBUG
02125 printf("Added '%s'\nExit sql_primekey_index_set\n",*query);
02126 #endif
02127 *query=p;
02128 return 0;
02129 }
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 static int sql_primekey_value_set(ValueRangeSet_t *rs, DRMS_Keyword_t *keyword,
02147 char *seriesname, char **query)
02148 {
02149 char *p=*query;
02150 DRMS_Type_t datatype;
02151
02152 #ifdef DEBUG
02153 printf("Enter sql_primekey_value_set\n");
02154 #endif
02155
02156 datatype = keyword->info->type;
02157
02158
02159
02160 do {
02161 p += sprintf(p,"( ");
02162
02163
02164
02165
02166
02167
02168
02169 if (rs->type == FIRST_VALUE) {
02170 p += sprintf(p,"%s=(select min(%s) from %s)", keyword->info->name, keyword->info->name, seriesname);
02171 } else if (rs->type == LAST_VALUE) {
02172 p += sprintf(p,"%s=(select max(%s) from %s)", keyword->info->name, keyword->info->name, seriesname);
02173 } else if (rs->type == SINGLE_VALUE)
02174 {
02175 p += sprintf(p,"%s=",keyword->info->name);
02176 p += drms_sprintfval(p, keyword->info->type, &rs->start, 1);
02177 }
02178 else
02179 {
02180 p += drms_sprintfval(p, keyword->info->type, &rs->start, 1);
02181 if (rs->type == START_END)
02182 {
02183 p += sprintf(p,"<=%s AND %s<=",keyword->info->name,keyword->info->name);
02184 p += drms_sprintfval(p, keyword->info->type, &rs->x, 1);
02185 }
02186 else if (rs->type == START_DURATION)
02187 {
02188 p += sprintf(p,"<=%s AND %s<( ",keyword->info->name,keyword->info->name);
02189 p += drms_sprintfval(p, keyword->info->type, &rs->start, 1);
02190 p += sprintf(p," + ");
02191 p += drms_sprintfval(p, keyword->info->type, &rs->x, 1);
02192 p += sprintf(p," )");
02193 }
02194
02195 if (rs->has_skip)
02196 {
02197 double dskip = drms2double(datatype, &rs->skip, NULL);
02198
02199
02200 if (datatype == DRMS_TYPE_CHAR || datatype == DRMS_TYPE_SHORT ||
02201 datatype == DRMS_TYPE_INT || datatype == DRMS_TYPE_LONGLONG)
02202 {
02203 long long llstart = drms2longlong(datatype, &rs->start, NULL);;
02204 p += sprintf(p, " AND (cast((%s - %lld)", keyword->info->name, llstart);
02205 p += sprintf(p, " as integer) %% ");
02206 p += drms_sprintfval(p, datatype, &rs->skip, 1);
02207 p += sprintf(p, ") = 0");
02208 }
02209 else
02210 {
02211
02212 double dstart = drms2double(datatype, &rs->start, NULL);
02213 double tolerance = 1.0e-11 * 2 * dstart;
02214
02215 p += sprintf(p,
02216 " AND (abs(((%s - %g) / %g) - (round((%s - %g) / %g))) < %g)",
02217 keyword->info->name,
02218 dstart,
02219 dskip,
02220 keyword->info->name,
02221 dstart,
02222 dskip,
02223 tolerance);
02224 }
02225 }
02226 }
02227 p += sprintf(p," )");
02228 if (rs->next)
02229 p += sprintf(p," OR ");
02230 rs = rs->next;
02231 }
02232 while (rs);
02233 #ifdef DEBUG
02234 printf("Added '%s'\nExit sql_primekey_value_set\n",*query);
02235 #endif
02236 *query=p;
02237 return 0;
02238 }
02239
02240
02241
02242
02243 static void free_record_set_filter(RecordSet_Filter_t *rs);
02244 static void free_record_query(RecordQuery_t *rs);
02245 static void free_record_list(RecordList_t *rs);
02246 static void free_primekey_set(PrimekeyRangeSet_t *rs);
02247 static void free_index_set(IndexRangeSet_t *rs);
02248 static void free_value_set(ValueRangeSet_t *rs);
02249
02250 void free_record_set(RecordSet_t *rs)
02251 {
02252 if (rs->recordset_spec)
02253 free_record_set_filter(rs->recordset_spec);
02254 free(rs);
02255 }
02256
02257 static void free_record_set_filter(RecordSet_Filter_t *rs)
02258 {
02259 RecordSet_Filter_t *old;
02260 do {
02261 switch(rs->type)
02262 {
02263 case RECORDQUERY:
02264 free_record_query(rs->record_query);
02265 break;
02266 case RECORDLIST:
02267 free_record_list(rs->record_list);
02268 break;
02269 }
02270 old = rs;
02271 rs = rs->next;
02272 free(old);
02273 } while (rs);
02274 }
02275
02276 static void free_record_query(RecordQuery_t *rs)
02277 {
02278 free(rs);
02279 }
02280
02281 static void free_record_list(RecordList_t *rs)
02282 {
02283 switch(rs->type)
02284 {
02285 case RECNUMSET:
02286 free_index_set(rs->recnum_rangeset);
02287 break;
02288 case PRIMEKEYSET:
02289 free_primekey_set(rs->primekey_rangeset);
02290 break;
02291 }
02292 free(rs);
02293 }
02294
02295 static void free_primekey_set(PrimekeyRangeSet_t *rs)
02296 {
02297 if (rs->type == INDEX_RANGE)
02298 free_index_set(rs->index_rangeset);
02299 else if(rs->type == VALUE_RANGE)
02300 free_value_set(rs->value_rangeset);
02301 free(rs);
02302 }
02303
02304 static void free_index_set(IndexRangeSet_t *rs)
02305 {
02306 IndexRangeSet_t *old;
02307 while(rs)
02308 {
02309 old = rs;
02310 rs = rs->next;
02311 free(old);
02312 }
02313 }
02314
02315 static void free_value_set(ValueRangeSet_t *rs)
02316 {
02317 ValueRangeSet_t *old;
02318 while (rs)
02319 {
02320 old = rs;
02321 rs = rs->next;
02322 free(old);
02323 }
02324 }
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435 char *drms_recordset_extractfilter(DRMS_Record_t *template, const char *in, int *status)
02436 {
02437 int allvers = 0;
02438 char *rsquery = strdup(in);
02439 char *pc = rsquery;
02440 char *rv = NULL;
02441 RecordSet_Filter_t *dontcare = NULL;
02442 char *filter = NULL;
02443
02444
02445 prime_keynum = 0;
02446 syntax_error = 0;
02447 recnum_filter = 0;
02448
02449 SKIPWS(pc);
02450 if (!parse_name(&pc, template->seriesinfo->seriesname, DRMS_MAXSERIESNAMELEN))
02451 {
02452 SKIPWS(pc);
02453
02454 if (*pc == 0)
02455 {
02456 if (status)
02457 {
02458 *status = 0;
02459 }
02460
02461 return NULL;
02462 }
02463 else if (*pc != '[')
02464 {
02465 if (status)
02466 {
02467 *status = 1;
02468 }
02469
02470 return NULL;
02471 }
02472
02473 filter = pc;
02474 dontcare = parse_record_set_filter(template, &pc, &allvers);
02475
02476
02477 if (dontcare)
02478 {
02479 *pc = '\0';
02480 rv = strdup(filter);
02481 free_record_set_filter(dontcare);
02482 }
02483
02484 free(rsquery);
02485
02486 if (status)
02487 {
02488 *status = 0;
02489 }
02490 }
02491 else
02492 {
02493 if (status)
02494 {
02495 *status = 1;
02496 }
02497 }
02498
02499 return rv;
02500 }
02501
02502
02503
02504
02505
02506
02507
02508
02509
02510
02511
02512
02513
02514
02515
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534 static void FreeNFL(void *data)
02535 {
02536 if (data)
02537 {
02538 if (*(char **)data)
02539 {
02540 free(*(char **)data);
02541 }
02542 }
02543 }
02544
02545 int drms_recordset_query(DRMS_Env_t *env,
02546 const char *recordsetname,
02547 char **query,
02548 char **pkwhere,
02549 char **npkwhere,
02550 char **seriesname,
02551 int *filter,
02552 int *mixed,
02553 int *allvers,
02554 HContainer_t **firstlast,
02555 HContainer_t **pkwhereNFL,
02556 int *recnumq)
02557 {
02558 RecordSet_t *rs;
02559 char *rsn = strdup(recordsetname);
02560 char *p = rsn;
02561 int ret = 0;
02562 RecordSet_Filter_t *filt = NULL;
02563 char fl;
02564
02565 *mixed = 0;
02566
02567 if ((rs = parse_record_set(env,&p)))
02568 {
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579 filt = rs->recordset_spec;
02580 *firstlast = hcon_create(sizeof(char), DRMS_MAXKEYNAMELEN, NULL, NULL, NULL, NULL, 0);
02581 XASSERT(*firstlast);
02582 if (recnumq)
02583 {
02584 *recnumq = 0;
02585 }
02586
02587
02588 while (filt != NULL)
02589 {
02590 if (filt->record_query)
02591 {
02592 *mixed = 1;
02593 }
02594
02595 if (filt->type == RECORDLIST)
02596 {
02597 if (filt->record_list->type == RECNUMSET)
02598 {
02599
02600
02601
02602
02603 if (recnumq)
02604 {
02605 *recnumq = 1;
02606 }
02607 }
02608 else if (filt->record_list->type == PRIMEKEYSET)
02609 {
02610 if (filt->record_list->primekey_rangeset->type == INDEX_RANGE)
02611 {
02612 fl = (char)((filt->record_list->primekey_rangeset->index_rangeset->type == FIRST_VALUE ? 'F' : (filt->record_list->primekey_rangeset->index_rangeset->type == LAST_VALUE ? 'L' : 'N')));
02613 if (fl != 'N')
02614 {
02615 hcon_insert_lower(*firstlast, filt->record_list->primekey_rangeset->keyword->info->name, &fl);
02616 }
02617 }
02618 else if (filt->record_list->primekey_rangeset->type == VALUE_RANGE)
02619 {
02620 fl = (char)((filt->record_list->primekey_rangeset->value_rangeset->type == FIRST_VALUE ? 'F' : (filt->record_list->primekey_rangeset->value_rangeset->type == LAST_VALUE ? 'L' : 'N')));
02621 if (fl != 'N')
02622 {
02623 hcon_insert_lower(*firstlast, filt->record_list->primekey_rangeset->keyword->info->name, &fl);
02624 }
02625 }
02626 }
02627 }
02628
02629 filt = filt->next;
02630 }
02631
02632 *query = malloc(DRMS_MAXQUERYLEN);
02633 XASSERT(*query);
02634 *pkwhere = malloc(DRMS_MAXQUERYLEN);
02635 XASSERT(*pkwhere);
02636 *npkwhere = malloc(DRMS_MAXQUERYLEN);
02637 XASSERT(*npkwhere);
02638 *seriesname = strdup(rs->seriesname);
02639 *filter = !recnum_filter;
02640 *pkwhereNFL = hcon_create(sizeof(char *), DRMS_MAXKEYNAMELEN, (void (*)(const void *value))FreeNFL, NULL, NULL, NULL, 0);
02641 XASSERT(*pkwhereNFL);
02642
02643 if (allvers)
02644 {
02645 *allvers = rs->allvers;
02646 }
02647
02648 sql_record_set(rs,*seriesname, *query, DRMS_MAXQUERYLEN, *pkwhere, DRMS_MAXQUERYLEN, *npkwhere, DRMS_MAXQUERYLEN, *pkwhereNFL);
02649 free_record_set(rs);
02650 ret = 0;
02651 }
02652 else
02653 ret = 1;
02654
02655 if (rsn)
02656 {
02657 free(rsn);
02658 }
02659
02660 return ret;
02661 }
02662
02663 static RecordSet_t *parse_record_set_ext(DB_Handle_t *dbh, DRMS_Record_t *template, char **in, char **seriesstr, char **filterstr)
02664 {
02665 char *p = *in;
02666 RecordSet_t *rs;
02667 int allvers = 0;
02668 char query[1024];
02669 char *lcseries = NULL;
02670 DB_Binary_Result_t *qres = NULL;
02671 char buf[DRMS_MAXPRIMIDX * DRMS_MAXKEYNAMELEN];
02672 char *pch = NULL;
02673 char *qch = NULL;
02674 char *namespace = NULL;
02675 char *table = NULL;
02676 int irow;
02677 DRMS_Keyword_t *key = NULL;
02678 DRMS_Keyword_t *kw = NULL;
02679 char kwname[DRMS_MAXKEYNAMELEN];
02680 char kwtype[16];
02681 char *filter = NULL;
02682 char defval[DRMS_DEFVAL_MAXLEN];
02683
02684 prime_keynum = 0;
02685 syntax_error = 0;
02686 recnum_filter = 0;
02687
02688 rs = malloc(sizeof(RecordSet_t));
02689 XASSERT(rs);
02690 memset(rs, 0, sizeof(RecordSet_t));
02691
02692
02693 SKIPWS(p);
02694 if (!parse_name(&p, rs->seriesname, DRMS_MAXSERIESNAMELEN))
02695 {
02696 if (seriesstr)
02697 {
02698 *seriesstr = strdup(rs->seriesname);
02699 }
02700
02701
02702
02703 lcseries = strdup(rs->seriesname);
02704
02705 if (!lcseries)
02706 {
02707 fprintf(stderr, "Out of memory.\n");
02708 goto empty;
02709 }
02710
02711 strtolower(lcseries);
02712
02713 if (!get_namespace(lcseries, &namespace, &table))
02714 {
02715 snprintf(query, sizeof(query),
02716 "SELECT seriesname, primary_idx FROM %s.%s WHERE lower(seriesname) = '%s'",
02717 namespace,
02718 DRMS_MASTER_SERIES_TABLE,
02719 lcseries);
02720
02721 }
02722 else
02723 {
02724 fprintf(stderr, "Out of memory.\n");
02725 goto empty;
02726 }
02727
02728 if ((qres = db_query_bin(dbh, query)) == NULL)
02729 {
02730 fprintf(stderr, "Failed to retrieve series information for series %s.\n", rs->seriesname);
02731 goto empty;
02732 }
02733
02734
02735 if (qres->num_rows != 1 || qres->num_cols != 2)
02736 {
02737 fprintf(stderr, "Unexpected query result.\n");
02738 goto empty;
02739 }
02740
02741
02742 db_binary_field_getstr(qres, 0, 0, DRMS_MAXSERIESNAMELEN, template->seriesinfo->seriesname);
02743
02744
02745 db_binary_field_getstr(qres, 0, 1, sizeof(buf), buf);
02746
02747
02748 db_free_binary_result(qres);
02749 qres = NULL;
02750
02751 snprintf(query, sizeof(query),
02752 "SELECT keywordname, type, defaultval, islink, isconstant, persegment FROM %s.%s WHERE lower(seriesname) = '%s'",
02753 namespace,
02754 DRMS_MASTER_KEYWORD_TABLE,
02755 lcseries);
02756
02757
02758 free(namespace);
02759 free(table);
02760 free(lcseries);
02761
02762 if ((qres = db_query_bin(dbh, query)) == NULL)
02763 {
02764 fprintf(stderr, "Failed to retrieve keyword information for series %s.\n", rs->seriesname);
02765 goto empty;
02766 }
02767
02768
02769
02770
02771
02772
02773
02774
02775 for (irow = 0; irow < (int)qres->num_rows; irow++)
02776 {
02777 db_binary_field_getstr(qres, irow, 0, sizeof(kwname), kwname);
02778 key = hcon_allocslot_lower(&template->keywords, kwname);
02779 memset(key, 0, sizeof(DRMS_Keyword_t));
02780 key->record = template;
02781 key->info = malloc(sizeof(DRMS_KeywordInfo_t));
02782 XASSERT(key->info);
02783 memset(key->info, 0, sizeof(DRMS_KeywordInfo_t));
02784 snprintf(key->info->name, sizeof(key->info->name), "%s", kwname);
02785 db_binary_field_getstr(qres, irow, 1, sizeof(kwtype), kwtype);
02786 key->info->type = drms_str2type(kwtype);
02787 db_binary_field_getstr(qres, irow, 2, sizeof(defval), defval);
02788 drms_strval(key->info->type, &key->value, defval);
02789 key->info->islink = db_binary_field_getint(qres, irow, 3);
02790 key->info->recscope = (DRMS_RecScopeType_t)db_binary_field_getint(qres, irow, 4);
02791 key->info->kwflags = db_binary_field_getint(qres, irow, 5);
02792 }
02793
02794
02795 if (!db_binary_field_is_null(qres, 0, 1))
02796 {
02797 pch = buf;
02798
02799 template->seriesinfo->pidx_num = 0;
02800 while(*pch)
02801 {
02802 XASSERT(template->seriesinfo->pidx_num < DRMS_MAXPRIMIDX);
02803 while(*pch && isspace(*pch))
02804 {
02805 ++pch;
02806 }
02807
02808 qch = pch;
02809 while(*pch && !isspace(*pch) && *pch != ',')
02810 {
02811 ++pch;
02812 }
02813
02814 *pch++ = 0;
02815
02816
02817 kw = hcon_lookup_lower(&template->keywords, qch);
02818 XASSERT(kw);
02819
02820 template->seriesinfo->pidx_keywords[(template->seriesinfo->pidx_num)++] = kw;
02821 }
02822 }
02823 else
02824 {
02825 template->seriesinfo->pidx_num = 0;
02826 }
02827
02828 db_free_binary_result(qres);
02829 qres = NULL;
02830
02831 SKIPWS(p);
02832
02833 if (*p==0)
02834 {
02835 rs->template = NULL;
02836 rs->recordset_spec = NULL;
02837 return rs;
02838 }
02839 else if (*p != '[')
02840 {
02841 fprintf(stderr,"Syntax error in record_set: Series name must be "
02842 "followed by '[', found '%c'\n",*p);
02843 ++syntax_error;
02844 goto empty;
02845 }
02846
02847
02848
02849 rs->template = template;
02850 filter = p;
02851 rs->recordset_spec = parse_record_set_filter(rs->template, &p, &allvers);
02852
02853
02854 if (filterstr)
02855 {
02856 if (rs->recordset_spec)
02857 {
02858 *filterstr = strdup(filter);
02859 (*filterstr)[p - filter] = '\0';
02860 }
02861 else
02862 {
02863 *filterstr = NULL;
02864 }
02865 }
02866
02867 if (syntax_error)
02868 goto empty;
02869
02870 rs->allvers = allvers;
02871
02872 *in = p;
02873 #ifdef DEBUG
02874 printf("exit parse_record_set\n");
02875 #endif
02876 return rs;
02877 }
02878 empty:
02879 free(rs);
02880 return NULL;
02881 }
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894 int drms_recordset_query_ext(DB_Handle_t *dbh,
02895 const char *recordsetname,
02896 char **query,
02897 char **pkwhere,
02898 char **npkwhere,
02899 char **seriesname,
02900 char **filterstr,
02901 int *filter,
02902 int *mixed,
02903 int *allvers,
02904 HContainer_t **firstlast,
02905 HContainer_t **pkwhereNFL,
02906 int *recnumq)
02907 {
02908 RecordSet_t *rs;
02909 char *rsn = strdup(recordsetname);
02910 char *p = rsn;
02911 int ret = 0;
02912 RecordSet_Filter_t *filt = NULL;
02913 DRMS_Record_t *template = NULL;
02914 char fl;
02915
02916 *mixed = 0;
02917
02918
02919
02920 template = malloc(sizeof(DRMS_Record_t));
02921 memset(template, 0, sizeof(DRMS_Record_t));
02922
02923
02924 template->env = NULL;
02925
02926
02927 template->init = 1;
02928 template->recnum = 0;
02929 template->sunum = -1LL;
02930 template->sessionid = 0;
02931 template->sessionns = NULL;
02932 template->su = NULL;
02933 template->seriesinfo = calloc(1, sizeof(DRMS_SeriesInfo_t));
02934 XASSERT(template->seriesinfo);
02935 template->seriesinfo->hasshadow = -1;
02936 template->seriesinfo->createshadow = 0;
02937
02938
02939
02940 hcon_init(&template->keywords, sizeof(DRMS_Keyword_t),
02941 DRMS_MAXHASHKEYLEN,
02942 (void (*)(const void *)) drms_free_template_keyword_struct,
02943 (void (*)(const void *, const void *)) drms_copy_keyword_struct);
02944
02945 if ((rs = parse_record_set_ext(dbh, template, &p, NULL, filterstr)))
02946 {
02947 filt = rs->recordset_spec;
02948 *firstlast = hcon_create(sizeof(char), DRMS_MAXKEYNAMELEN, NULL, NULL, NULL, NULL, 0);
02949 XASSERT(*firstlast);
02950 if (recnumq)
02951 {
02952 *recnumq = 0;
02953 }
02954
02955
02956 while (filt != NULL)
02957 {
02958 if (filt->record_query)
02959 {
02960 *mixed = 1;
02961 }
02962
02963 if (filt->type == RECORDLIST)
02964 {
02965 if (filt->record_list->type == RECNUMSET)
02966 {
02967
02968
02969
02970
02971 if (recnumq)
02972 {
02973 *recnumq = 1;
02974 }
02975 }
02976 else if (filt->record_list->type == PRIMEKEYSET)
02977 {
02978 if (filt->record_list->primekey_rangeset->type == INDEX_RANGE)
02979 {
02980 fl = (char)((filt->record_list->primekey_rangeset->index_rangeset->type == FIRST_VALUE ? 'F' : (filt->record_list->primekey_rangeset->index_rangeset->type == LAST_VALUE ? 'L' : 'N')));
02981 hcon_insert_lower(*firstlast, filt->record_list->primekey_rangeset->keyword->info->name, &fl);
02982 }
02983 else if (filt->record_list->primekey_rangeset->type == VALUE_RANGE)
02984 {
02985 fl = (char)((filt->record_list->primekey_rangeset->value_rangeset->type == FIRST_VALUE ? 'F' : (filt->record_list->primekey_rangeset->value_rangeset->type == LAST_VALUE ? 'L' : 'N')));
02986 hcon_insert_lower(*firstlast, filt->record_list->primekey_rangeset->keyword->info->name, &fl);
02987 }
02988 }
02989 }
02990
02991 filt = filt->next;
02992 }
02993
02994 *query = malloc(DRMS_MAXQUERYLEN);
02995 XASSERT(*query);
02996 *pkwhere = malloc(DRMS_MAXQUERYLEN);
02997 XASSERT(*pkwhere);
02998 *npkwhere = malloc(DRMS_MAXQUERYLEN);
02999 XASSERT(*npkwhere);
03000 *seriesname = strdup(rs->seriesname);
03001 *filter = !recnum_filter;
03002 *pkwhereNFL = hcon_create(sizeof(char *), DRMS_MAXKEYNAMELEN, (void (*)(const void *value))FreeNFL, NULL, NULL, NULL, 0);
03003 XASSERT(*pkwhereNFL);
03004
03005 if (allvers)
03006 {
03007 *allvers = rs->allvers;
03008 }
03009
03010 sql_record_set(rs, *seriesname, *query, DRMS_MAXQUERYLEN, *pkwhere, DRMS_MAXQUERYLEN, *npkwhere, DRMS_MAXQUERYLEN, *pkwhereNFL);
03011 free_record_set(rs);
03012 ret = 0;
03013 }
03014 else
03015 {
03016 ret = 1;
03017 }
03018
03019
03020 hcon_free(&template->keywords);
03021 free(template->seriesinfo);
03022 free(template);
03023 template = NULL;
03024
03025 if (rsn)
03026 {
03027 free(rsn);
03028 }
03029
03030 return ret;
03031 }
03032
03033
03034 char *drms_recordset_extractfilter_ext(DB_Handle_t *dbh, const char *in, int *status)
03035 {
03036 char *query = NULL;
03037 char *pkwhere = NULL;
03038 char *npkwhere = NULL;
03039 char *seriesname = NULL;
03040 char *filterstr = NULL;
03041 int filter = 0;
03042 int mixed = 0;
03043 int allvers = 0;
03044 int istat = 0;
03045 HContainer_t *firstlast = NULL;
03046 HContainer_t *pkwhereNFL = NULL;
03047 int recnumq = 0;
03048
03049 istat = drms_recordset_query_ext(dbh, in, &query, &pkwhere, &npkwhere, &seriesname, &filterstr, &filter, &mixed, &allvers, &firstlast, &pkwhereNFL, &recnumq);
03050
03051
03052 if (pkwhere)
03053 {
03054 free(pkwhere);
03055 }
03056
03057 if (npkwhere)
03058 {
03059 free(npkwhere);
03060 }
03061
03062 if (query)
03063 {
03064 free(query);
03065 }
03066
03067 if (seriesname)
03068 {
03069 free(seriesname);
03070 }
03071
03072 if (pkwhereNFL)
03073 {
03074 hcon_destroy(&pkwhereNFL);
03075 }
03076
03077 if (status)
03078 {
03079 *status = istat;
03080 }
03081
03082 return filterstr;
03083 }