00001
00002 #include "drms.h"
00003 #include "drms_priv.h"
00004 #include "xmem.h"
00005 #include <regex.h>
00006 #include "atoinc.h"
00007
00008
00009
00010
00011 #if (defined TOC && TOC)
00012 #define kTableOfCountsNS "public"
00013 #define kTableOfCountsTab "recordcounts"
00014 #define kTableOfCountsColSeries "seriesname"
00015 #define kTableOfCountsColNRecs "nrecords"
00016 #endif
00017
00018 #define kShadowSuffix "_shadow"
00019 #define kShadowColRecnum "recnum"
00020 #define kShadowColNRecs "nrecords"
00021 #define kShadowTrig "updateshadowtrig"
00022 #define kShadowTrigFxn "updateshadow"
00023 #define kLimitCutoff 100000
00024
00025 #if (defined TRACKSHADOWS && TRACKSHADOWS)
00026 #define kShadowTrackTab "drms.shadowtrack"
00027 #define kshadowTrackerFxn "drms.shadowtrackfxn"
00028 #endif
00029
00030 #if (defined TOC && TOC)
00031 static int TocExists(DRMS_Env_t *env, int *status)
00032 {
00033 int istat = DRMS_SUCCESS;
00034 int tabexists = 0;
00035
00036 tabexists = drms_query_tabexists(env->session, kTableOfCountsNS, kTableOfCountsTab, &istat);
00037
00038 if (status)
00039 {
00040 *status = istat;
00041 }
00042
00043 return tabexists;
00044 }
00045
00046 static int CreateTableOfCounts(DRMS_Env_t *env)
00047 {
00048 char createstmt[8192];
00049 int status = DRMS_SUCCESS;
00050
00051
00052 snprintf(createstmt, sizeof(createstmt), "CREATE TABLE %s (%s text not null, %s bigint not null, PRIMARY KEY (seriesname))", kTableOfCountsTab, kTableOfCountsColSeries, kTableOfCountsColNRecs);
00053
00054 if (drms_dms(env->session, NULL, createstmt))
00055 {
00056 fprintf(stderr, "Failed: %s\n", createstmt);
00057 status = DRMS_ERROR_BADDBQUERY;
00058 }
00059 else
00060 {
00061 snprintf(createstmt, sizeof(createstmt), "GRANT ALL ON %s TO public", kTableOfCountsTab);
00062
00063 if (drms_dms(env->session, NULL, createstmt))
00064 {
00065 fprintf(stderr, "Failed: %s\n", createstmt);
00066 status = DRMS_ERROR_BADDBQUERY;
00067 }
00068 else
00069 {
00070
00071
00072 snprintf(createstmt, sizeof(createstmt), "CREATE INDEX %s_%s_lower ON %s.%s (lower(%s))", kTableOfCountsTab, kTableOfCountsColSeries, kTableOfCountsNS, kTableOfCountsTab, kTableOfCountsColSeries);
00073
00074 if (drms_dms(env->session, NULL, createstmt))
00075 {
00076 fprintf(stderr, "Failed: %s\n", createstmt);
00077 status = DRMS_ERROR_BADDBQUERY;
00078 }
00079 }
00080 }
00081
00082 return status;
00083 }
00084
00085 static long long CountRecordGroups(DRMS_Env_t *env,
00086 const char *series,
00087 int *status)
00088 {
00089 int istat = DRMS_SUCCESS;
00090 char query[DRMS_MAXQUERYLEN];
00091 char *pklist = NULL;
00092 size_t stsz = DRMS_MAXQUERYLEN;
00093 DB_Text_Result_t *tres = NULL;
00094 long long count = -1;
00095 int ipkey;
00096
00097 char *lcseries = strdup(series);
00098
00099 if (lcseries)
00100 {
00101 strtolower(lcseries);
00102 pklist = malloc(stsz);
00103
00104 if (pklist)
00105 {
00106 DRMS_Record_t *template = drms_template_record(env, series, &istat);
00107
00108 *pklist = '\0';
00109
00110 if (istat == DRMS_SUCCESS)
00111 {
00112
00113 for (ipkey = 0; ipkey < template->seriesinfo->pidx_num; ipkey++)
00114 {
00115 pklist = base_strcatalloc(pklist, lcseries, &stsz);
00116 pklist = base_strcatalloc(pklist, ".", &stsz);
00117 pklist = base_strcatalloc(pklist, template->seriesinfo->pidx_keywords[ipkey]->info->name, &stsz);
00118
00119 if (ipkey < template->seriesinfo->pidx_num - 1)
00120 {
00121 pklist = base_strcatalloc(pklist, ", ", &stsz);
00122 }
00123 }
00124
00125 snprintf(query, sizeof(query), "SELECT count(*) FROM (SELECT max(recnum) FROM %s GROUP BY %s) AS T1", lcseries, pklist);
00126
00127 tres = drms_query_txt(env->session, query);
00128
00129 if (tres)
00130 {
00131 if (tres->num_rows == 1 && tres->num_cols == 1)
00132 {
00133 count = atoll(tres->field[0][0]);
00134 }
00135
00136 db_free_text_result(tres);
00137 tres = NULL;
00138 }
00139 else
00140 {
00141 fprintf(stderr, "Failed: %s\n", query);
00142 istat = DRMS_ERROR_BADDBQUERY;
00143 }
00144 }
00145 }
00146 else
00147 {
00148 istat = DRMS_ERROR_OUTOFMEMORY;
00149 }
00150 }
00151 else
00152 {
00153 istat = DRMS_ERROR_OUTOFMEMORY;
00154 }
00155
00156 if (status)
00157 {
00158 *status = istat;
00159 }
00160
00161 return count;
00162 }
00163
00164
00165 static int IsSeriesPresent(DRMS_Env_t *env, const char *ns, const char *tab, const char *series, int *status)
00166 {
00167 char *query = NULL;
00168 size_t stsz = 8192;
00169 int istat = DRMS_SUCCESS;
00170 int ans = -1;
00171 DB_Text_Result_t *tres = NULL;
00172 char *lcseries = strdup(series);
00173
00174 if (lcseries)
00175 {
00176 strtolower(lcseries);
00177
00178 query = malloc(stsz);
00179 if (query)
00180 {
00181 *query = '\0';
00182
00183 query = base_strcatalloc(query, "SELECT seriesname FROM ", &stsz);
00184 query = base_strcatalloc(query, ns, &stsz);
00185 query = base_strcatalloc(query, ".", &stsz);
00186 query = base_strcatalloc(query, tab, &stsz);
00187 query = base_strcatalloc(query, " WHERE lower(seriesname) = '", &stsz);
00188 query = base_strcatalloc(query, lcseries, &stsz);
00189 query = base_strcatalloc(query, "'", &stsz);
00190
00191 tres = drms_query_txt(env->session, query);
00192
00193 if (tres)
00194 {
00195 if (tres->num_rows == 1)
00196 {
00197 ans = 1;
00198 }
00199 else if (tres->num_rows == 0)
00200 {
00201 ans = 0;
00202 }
00203 else
00204 {
00205 istat = DRMS_ERROR_BADDBQUERY;
00206 }
00207
00208 db_free_text_result(tres);
00209 tres = NULL;
00210 }
00211 else
00212 {
00213 fprintf(stderr, "Failed: %s\n", query);
00214 istat = DRMS_ERROR_BADDBQUERY;
00215 }
00216
00217 free(query);
00218 query = NULL;
00219 }
00220 else
00221 {
00222 istat = DRMS_ERROR_OUTOFMEMORY;
00223 }
00224
00225 free(lcseries);
00226 lcseries = NULL;
00227 }
00228 else
00229 {
00230 istat = DRMS_ERROR_OUTOFMEMORY;
00231 }
00232
00233 if (status)
00234 {
00235 *status = istat;
00236 }
00237
00238 return ans;
00239 }
00240
00241
00242 static int InsertSeries(DRMS_Env_t *env, const char *ns, const char *tab, const char *series, long long count)
00243 {
00244 char stmnt[8192];
00245 int status = DRMS_SUCCESS;
00246
00247 snprintf(stmnt, sizeof(stmnt), "INSERT INTO %s.%s (%s, %s) VALUES ('%s', %lld)", ns, tab, "seriesname", "nrecords", series, count);
00248
00249 if (drms_dms(env->session, NULL, stmnt))
00250 {
00251 fprintf(stderr, "Failed: %s\n", stmnt);
00252 status = DRMS_ERROR_BADDBQUERY;
00253 }
00254
00255 return status;
00256 }
00257
00258 static int AdvanceGroupCount(DRMS_Env_t *env,
00259 const char *ns,
00260 const char *tab,
00261 const char *series)
00262 {
00263
00264 char *query = NULL;
00265 size_t stsz = 8192;
00266 char *lcseries = NULL;
00267 int status = DRMS_SUCCESS;
00268
00269 lcseries = strdup(series);
00270 if (lcseries)
00271 {
00272 strtolower(lcseries);
00273
00274 query = malloc(stsz);
00275 if (query)
00276 {
00277 *query = '\0';
00278
00279 if (query)
00280 {
00281 query = base_strcatalloc(query, "UPDATE ", &stsz);
00282 query = base_strcatalloc(query, ns, &stsz);
00283 query = base_strcatalloc(query, ".", &stsz);
00284 query = base_strcatalloc(query, tab, &stsz);
00285 query = base_strcatalloc(query, " SET nrecords = nrecords + 1 WHERE lower(seriesname) = '", &stsz);
00286 query = base_strcatalloc(query, lcseries, &stsz);
00287 query = base_strcatalloc(query, "'", &stsz);
00288
00289 if (drms_dms(env->session, NULL, query))
00290 {
00291 fprintf(stderr, "Failed: %s\n", query);
00292 status = DRMS_ERROR_BADDBQUERY;
00293 }
00294
00295 free(query);
00296 query = NULL;
00297 }
00298 }
00299 else
00300 {
00301 status = DRMS_ERROR_OUTOFMEMORY;
00302 }
00303 free(lcseries);
00304 lcseries = NULL;
00305 }
00306 else
00307 {
00308 status = DRMS_ERROR_OUTOFMEMORY;
00309 }
00310
00311 return status;
00312 }
00313 #endif
00314
00315
00316 void FreeKey(void *data)
00317 {
00318 if (data)
00319 {
00320 if (*(char **)data)
00321 {
00322 free(*(char **)data);
00323 }
00324 }
00325 }
00326
00327 static int ShadowExists(DRMS_Env_t *env, const char *series, int *status)
00328 {
00329 int istat = DRMS_SUCCESS;
00330 int tabexists = 0;
00331 char *namespace = NULL;
00332 char *table = NULL;
00333 char shadowtable[DRMS_MAXSERIESNAMELEN];
00334 DRMS_Record_t *template = NULL;
00335
00336 template = drms_template_record(env, series, &istat);
00337
00338 if (istat == DRMS_SUCCESS)
00339 {
00340
00341
00342 if (template->seriesinfo->hasshadow == 1)
00343 {
00344 if (status)
00345 {
00346 *status = istat;
00347 }
00348 return 1;
00349 }
00350 else if (template->seriesinfo->hasshadow == 0)
00351 {
00352 if (status)
00353 {
00354 *status = istat;
00355 }
00356 return 0;
00357 }
00358
00359
00360
00361 if (!get_namespace(series, &namespace, &table))
00362 {
00363 snprintf(shadowtable, sizeof(shadowtable), "%s%s", table, kShadowSuffix);
00364 tabexists = drms_query_tabexists(env->session, namespace, shadowtable, &istat);
00365
00366 free(namespace);
00367 free(table);
00368 }
00369 else
00370 {
00371 istat = DRMS_ERROR_OUTOFMEMORY;
00372 }
00373
00374 template->seriesinfo->hasshadow = tabexists;
00375 }
00376
00377 if (status)
00378 {
00379 *status = istat;
00380 }
00381
00382 return tabexists;
00383 }
00384
00385
00386 static int GetTempTable(char *tabname, int size)
00387 {
00388 static int id = 0;
00389
00390 if (id < INT_MAX)
00391 {
00392 snprintf(tabname, size, "shadowtemp%03d", id);
00393 id++;
00394 return 0;
00395 }
00396
00397 return 1;
00398 }
00399
00400
00401
00402
00403 static int PopulateShadow(DRMS_Env_t *env, const char *series, const char *tname)
00404 {
00405 int status = DRMS_SUCCESS;
00406 char *lcseries = NULL;
00407 char *pklist = NULL;
00408 char *tpklist = NULL;
00409 size_t stsz = DRMS_MAXQUERYLEN;
00410 size_t stsz2 = DRMS_MAXQUERYLEN;
00411 int ipkey;
00412 char stmnt[8192];
00413 DRMS_Keyword_t *key = NULL;
00414 char shadow[DRMS_MAXSERIESNAMELEN * 2];
00415
00416 lcseries = strdup(series);
00417 pklist = malloc(stsz);
00418 tpklist = malloc(stsz2);
00419
00420 if (lcseries && pklist && tpklist)
00421 {
00422 DRMS_Record_t *template = drms_template_record(env, series, &status);
00423 char lckeyname[DRMS_MAXKEYNAMELEN + 1];
00424
00425 *pklist = '\0';
00426 *tpklist = '\0';
00427
00428 if (status == DRMS_SUCCESS)
00429 {
00430
00431 for (ipkey = 0; ipkey < template->seriesinfo->pidx_num; ipkey++)
00432 {
00433 key = template->seriesinfo->pidx_keywords[ipkey];
00434 snprintf(lckeyname, sizeof(lckeyname), "%s", key->info->name);
00435 strtolower(lckeyname);
00436
00437 pklist = base_strcatalloc(pklist, lckeyname, &stsz);
00438 tpklist = base_strcatalloc(tpklist, "T1.", &stsz2);
00439 tpklist = base_strcatalloc(tpklist, lckeyname, &stsz2);
00440
00441 if (ipkey < template->seriesinfo->pidx_num - 1)
00442 {
00443 pklist = base_strcatalloc(pklist, ", ", &stsz);
00444 tpklist = base_strcatalloc(tpklist, ", ", &stsz2);
00445 }
00446 }
00447
00448
00449 if (tname == NULL)
00450 {
00451 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
00452 }
00453 else
00454 {
00455 char *lctname = strdup(tname);
00456
00457 strtolower(lctname);
00458 snprintf(shadow, sizeof(shadow), "%s", lctname);
00459 }
00460
00461 snprintf(stmnt, sizeof(stmnt), "INSERT INTO %s (%s, %s, %s) SELECT %s, T2.c, T2.m FROM %s AS T1, (SELECT count(*) AS c, max(recnum) AS m FROM %s GROUP BY %s) AS T2 WHERE T1.recnum = T2.m", shadow, pklist, kShadowColNRecs, kShadowColRecnum, tpklist, lcseries, lcseries, pklist);
00462
00463 if (drms_dms(env->session, NULL, stmnt))
00464 {
00465 fprintf(stderr, "Failed: %s\n", stmnt);
00466 status = DRMS_ERROR_BADDBQUERY;
00467 }
00468 }
00469 }
00470 else
00471 {
00472 status = DRMS_ERROR_OUTOFMEMORY;
00473 }
00474
00475 return status;
00476 }
00477
00478
00479 static int UpdateShadow(DRMS_Env_t *env,
00480 const char *series,
00481 char **pkeynames,
00482 int ncols,
00483 long long recnum,
00484 int added)
00485 {
00486 char *lcseries = NULL;
00487 char *namespace = NULL;
00488 char *table = NULL;
00489 char *query = NULL;
00490 size_t stsz = 1024;
00491 char srecnum[32];
00492 char smaxrec[32];
00493 char scolnum[8];
00494 DB_Binary_Result_t *qres = NULL;
00495 long long maxrec = -1;
00496 int status = DRMS_SUCCESS;
00497
00498
00499 lcseries = strdup(series);
00500 query = malloc(stsz);
00501
00502 if (lcseries && query)
00503 {
00504 *query = '\0';
00505
00506 if (!get_namespace(series, &namespace, &table))
00507 {
00508 int icol;
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 snprintf(srecnum, sizeof(srecnum), "%lld", recnum);
00521
00522 query = base_strcatalloc(query, "SELECT max(T1.recnum) FROM ", &stsz);
00523 query = base_strcatalloc(query, lcseries, &stsz);
00524 query = base_strcatalloc(query, " AS T1, (SELECT ", &stsz);
00525
00526 for (icol = 0; icol < ncols; icol++)
00527 {
00528 snprintf(scolnum, sizeof(scolnum), "%d", icol);
00529 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00530 query = base_strcatalloc(query, " AS p", &stsz);
00531 query = base_strcatalloc(query, scolnum, &stsz);
00532
00533 if (icol < ncols - 1)
00534 {
00535 query = base_strcatalloc(query, ", ", &stsz);
00536 }
00537 }
00538
00539 query = base_strcatalloc(query, " FROM ", &stsz);
00540 query = base_strcatalloc(query, lcseries, &stsz);
00541 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
00542 query = base_strcatalloc(query, srecnum, &stsz);
00543 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
00544
00545 for (icol = 0; icol < ncols; icol++)
00546 {
00547 snprintf(scolnum, sizeof(scolnum), "%d", icol);
00548 query = base_strcatalloc(query, "T1.", &stsz);
00549 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00550 query = base_strcatalloc(query, " = T2.p", &stsz);
00551 query = base_strcatalloc(query, scolnum, &stsz);
00552
00553 if (icol < ncols - 1)
00554 {
00555 query = base_strcatalloc(query, " AND ", &stsz);
00556 }
00557 }
00558
00559 if ((qres = drms_query_bin(env->session, query)) != NULL)
00560 {
00561 if (qres->num_cols == 1 && qres->num_rows == 1)
00562 {
00563 maxrec = db_binary_field_getlonglong(qres, 0, 0);
00564 }
00565 else
00566 {
00567 status = DRMS_ERROR_BADDBQUERY;
00568 }
00569
00570 db_free_binary_result(qres);
00571 qres = NULL;
00572 }
00573 else
00574 {
00575 status = DRMS_ERROR_BADDBQUERY;
00576 }
00577
00578 if (status == DRMS_SUCCESS)
00579 {
00580 if (added && recnum == maxrec)
00581 {
00582
00583
00584
00585
00586
00587
00588
00589 *query = '\0';
00590 query = base_strcatalloc(query, "UPDATE ", &stsz);
00591 query = base_strcatalloc(query, namespace, &stsz);
00592 query = base_strcatalloc(query, ".", &stsz);
00593 query = base_strcatalloc(query, table, &stsz);
00594 query = base_strcatalloc(query, kShadowSuffix, &stsz);
00595 query = base_strcatalloc(query, " AS T1 SET ", &stsz);
00596 query = base_strcatalloc(query, kShadowColRecnum, &stsz);
00597 query = base_strcatalloc(query, " = ", &stsz);
00598 query = base_strcatalloc(query, srecnum, &stsz);
00599 query = base_strcatalloc(query, ", ", &stsz);
00600 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00601 query = base_strcatalloc(query, " = T1.", &stsz);
00602 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00603 query = base_strcatalloc(query, " + 1 FROM (SELECT ", &stsz);
00604
00605 for (icol = 0; icol < ncols; icol++)
00606 {
00607 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00608
00609 if (icol < ncols - 1)
00610 {
00611 query = base_strcatalloc(query, ", ", &stsz);
00612 }
00613 }
00614
00615 query = base_strcatalloc(query, " FROM ", &stsz);
00616 query = base_strcatalloc(query, lcseries, &stsz);
00617 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
00618 query = base_strcatalloc(query, srecnum, &stsz);
00619 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
00620
00621 for (icol = 0; icol < ncols; icol++)
00622 {
00623 snprintf(scolnum, sizeof(scolnum), "%d", icol);
00624 query = base_strcatalloc(query, "T1.", &stsz);
00625 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00626 query = base_strcatalloc(query, " = T2.", &stsz);
00627 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00628
00629 if (icol < ncols - 1)
00630 {
00631 query = base_strcatalloc(query, " AND ", &stsz);
00632 }
00633 }
00634
00635 if (drms_dms(env->session, NULL, query))
00636 {
00637
00638
00639 fprintf(stderr, "Failed: %s\n", query);
00640 status = DRMS_ERROR_BADDBQUERY;
00641 }
00642 }
00643
00644 if (!added)
00645 {
00646
00647
00648 if (maxrec > recnum)
00649 {
00650
00651
00652
00653
00654 *query = '\0';
00655 query = base_strcatalloc(query, "UPDATE ", &stsz);
00656 query = base_strcatalloc(query, namespace, &stsz);
00657 query = base_strcatalloc(query, ".", &stsz);
00658 query = base_strcatalloc(query, table, &stsz);
00659 query = base_strcatalloc(query, kShadowSuffix, &stsz);
00660 query = base_strcatalloc(query, " AS T1 SET ", &stsz);
00661 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00662 query = base_strcatalloc(query, " = T1.", &stsz);
00663 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00664 query = base_strcatalloc(query, " - 1 FROM (SELECT ", &stsz);
00665
00666 for (icol = 0; icol < ncols; icol++)
00667 {
00668 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00669
00670 if (icol < ncols - 1)
00671 {
00672 query = base_strcatalloc(query, ", ", &stsz);
00673 }
00674 }
00675
00676 query = base_strcatalloc(query, " FROM ", &stsz);
00677 query = base_strcatalloc(query, lcseries, &stsz);
00678 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
00679 query = base_strcatalloc(query, srecnum, &stsz);
00680 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
00681
00682 for (icol = 0; icol < ncols; icol++)
00683 {
00684 snprintf(scolnum, sizeof(scolnum), "%d", icol);
00685 query = base_strcatalloc(query, "T1.", &stsz);
00686 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00687 query = base_strcatalloc(query, " = T2.", &stsz);
00688 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00689
00690 if (icol < ncols - 1)
00691 {
00692 query = base_strcatalloc(query, " AND ", &stsz);
00693 }
00694 }
00695
00696 if (drms_dms(env->session, NULL, query))
00697 {
00698
00699
00700 fprintf(stderr, "Failed: %s\n", query);
00701 status = DRMS_ERROR_BADDBQUERY;
00702 }
00703
00704 }
00705 else if (maxrec < recnum)
00706 {
00707
00708
00709
00710
00711
00712 snprintf(smaxrec, sizeof(smaxrec), "%lld", maxrec);
00713
00714 *query = '\0';
00715 query = base_strcatalloc(query, "UPDATE ", &stsz);
00716 query = base_strcatalloc(query, namespace, &stsz);
00717 query = base_strcatalloc(query, ".", &stsz);
00718 query = base_strcatalloc(query, table, &stsz);
00719 query = base_strcatalloc(query, kShadowSuffix, &stsz);
00720 query = base_strcatalloc(query, " AS T1 SET ", &stsz);
00721 query = base_strcatalloc(query, kShadowColRecnum, &stsz);
00722 query = base_strcatalloc(query, " = ", &stsz);
00723 query = base_strcatalloc(query, smaxrec, &stsz);
00724 query = base_strcatalloc(query, ", ", &stsz);
00725 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00726 query = base_strcatalloc(query, " = T1.", &stsz);
00727 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00728 query = base_strcatalloc(query, " - 1 FROM (SELECT ", &stsz);
00729
00730 for (icol = 0; icol < ncols; icol++)
00731 {
00732 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00733
00734 if (icol < ncols - 1)
00735 {
00736 query = base_strcatalloc(query, ", ", &stsz);
00737 }
00738 }
00739
00740 query = base_strcatalloc(query, " FROM ", &stsz);
00741 query = base_strcatalloc(query, lcseries, &stsz);
00742 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
00743 query = base_strcatalloc(query, srecnum, &stsz);
00744 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
00745
00746 for (icol = 0; icol < ncols; icol++)
00747 {
00748 snprintf(scolnum, sizeof(scolnum), "%d", icol);
00749 query = base_strcatalloc(query, "T1.", &stsz);
00750 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00751 query = base_strcatalloc(query, " = T2.", &stsz);
00752 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00753
00754 if (icol < ncols - 1)
00755 {
00756 query = base_strcatalloc(query, " AND ", &stsz);
00757 }
00758 }
00759
00760 if (drms_dms(env->session, NULL, query))
00761 {
00762
00763
00764 fprintf(stderr, "Failed: %s\n", query);
00765 status = DRMS_ERROR_BADDBQUERY;
00766 }
00767 }
00768 else
00769 {
00770
00771 }
00772 }
00773 }
00774
00775 free(namespace);
00776 free(table);
00777 }
00778 else
00779 {
00780 status = DRMS_ERROR_OUTOFMEMORY;
00781 }
00782
00783 free(query);
00784 free(lcseries);
00785 }
00786 else
00787 {
00788 status = DRMS_ERROR_OUTOFMEMORY;
00789 }
00790
00791 return status;
00792 }
00793
00794 static char *PrependWhere(DRMS_Env_t *env, const char *pkwhere, const char *series, const char *prefix, int *status)
00795 {
00796 int istat = DRMS_SUCCESS;
00797 DRMS_Record_t *template = drms_template_record(env, series, &istat);
00798 char *ret = NULL;
00799 char *qualpkwhere = NULL;
00800 char *orig = NULL;
00801 char lckeyname[DRMS_MAXKEYNAMELEN];
00802 char repl[DRMS_MAXKEYNAMELEN + 16];
00803 int ipkey;
00804 DRMS_Keyword_t *key = NULL;
00805
00806 if (istat == DRMS_SUCCESS)
00807 {
00808 if (template->seriesinfo->pidx_num > 0)
00809 {
00810 qualpkwhere = strdup(pkwhere);
00811 if (qualpkwhere)
00812 {
00813 orig = qualpkwhere;
00814
00815 for (ipkey = 0; ipkey < template->seriesinfo->pidx_num; ipkey++)
00816 {
00817 key = template->seriesinfo->pidx_keywords[ipkey];
00818 snprintf(lckeyname, sizeof(lckeyname), "%s", key->info->name);
00819 strtolower(lckeyname);
00820 snprintf(repl, sizeof(repl), "%s%s", prefix, lckeyname);
00821 orig = qualpkwhere;
00822 qualpkwhere = base_strcasereplace(orig, lckeyname, repl);
00823 if (!qualpkwhere)
00824 {
00825
00826
00827 qualpkwhere = orig;
00828 orig = NULL;
00829 continue;
00830 }
00831 free(orig);
00832 orig = NULL;
00833 }
00834
00835 if (orig)
00836 {
00837 free(orig);
00838 orig = NULL;
00839 }
00840
00841 ret = qualpkwhere;
00842 }
00843 else
00844 {
00845 istat = DRMS_ERROR_OUTOFMEMORY;
00846 }
00847 }
00848 }
00849
00850 if (status)
00851 {
00852 *status = istat;
00853 }
00854
00855 return ret;
00856 }
00857
00858
00859 int InsertIntoShadow(DRMS_Env_t *env,
00860 const char *series,
00861 char **pkeynames,
00862 int ncols,
00863 long long recnum)
00864 {
00865 char *lcseries = NULL;
00866 char *query = NULL;
00867 size_t stsz = 1024;
00868 char srecnum[32];
00869 int icol;
00870 int status = DRMS_SUCCESS;
00871
00872 lcseries = strdup(series);
00873 query = malloc(stsz);
00874
00875 if (lcseries && query)
00876 {
00877 *query = '\0';
00878 snprintf(srecnum, sizeof(srecnum), "%lld", recnum);
00879
00880 query = base_strcatalloc(query, "INSERT INTO ", &stsz);
00881 query = base_strcatalloc(query, lcseries, &stsz);
00882 query = base_strcatalloc(query, kShadowSuffix, &stsz);
00883 query = base_strcatalloc(query, " (", &stsz);
00884
00885 for (icol = 0; icol < ncols; icol++)
00886 {
00887 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00888 query = base_strcatalloc(query, ", ", &stsz);
00889 }
00890
00891 query = base_strcatalloc(query, kShadowColRecnum, &stsz);
00892 query = base_strcatalloc(query, ", ", &stsz);
00893 query = base_strcatalloc(query, kShadowColNRecs, &stsz);
00894 query = base_strcatalloc(query, ") SELECT ", &stsz);
00895
00896 for (icol = 0; icol < ncols; icol++)
00897 {
00898 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00899 query = base_strcatalloc(query, ", ", &stsz);
00900 }
00901
00902 query = base_strcatalloc(query, "recnum, 1 FROM ", &stsz);
00903 query = base_strcatalloc(query, lcseries, &stsz);
00904 query = base_strcatalloc(query, "WHERE recnum = ", &stsz);
00905 query = base_strcatalloc(query, srecnum, &stsz);
00906
00907 if (drms_dms(env->session, NULL, query))
00908 {
00909 status = DRMS_ERROR_BADDBQUERY;
00910 }
00911
00912 free(query);
00913 free(lcseries);
00914 }
00915 else
00916 {
00917 status = DRMS_ERROR_OUTOFMEMORY;
00918 }
00919
00920 return status;
00921 }
00922
00923
00924
00925
00926 static int GroupExists(DRMS_Env_t *env,
00927 long long recnum,
00928 const char *series,
00929 char **pkeynames,
00930 int ncols,
00931 int *status)
00932 {
00933 char *query = NULL;
00934 size_t stsz = 4096;
00935 char srecnum[32];
00936 DB_Text_Result_t *tres = NULL;
00937 int ans = -1;
00938 int icol;
00939 char *lcseries = NULL;
00940 int istat = DRMS_SUCCESS;
00941
00942
00943 snprintf(srecnum, sizeof(srecnum), "%lld", recnum);
00944
00945 lcseries = strdup(series);
00946
00947 if (lcseries)
00948 {
00949 strtolower(lcseries);
00950 query = malloc(stsz);
00951 if (query)
00952 {
00953 *query = '\0';
00954 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
00955 query = base_strcatalloc(query, lcseries, &stsz);
00956 query = base_strcatalloc(query, " AS T1, (SELECT ", &stsz);
00957
00958 for (icol = 0; icol < ncols; icol++)
00959 {
00960 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00961
00962 if (icol < ncols - 1)
00963 {
00964 query = base_strcatalloc(query, ", ", &stsz);
00965 }
00966 }
00967
00968 query = base_strcatalloc(query, " FROM ", &stsz);
00969 query = base_strcatalloc(query, lcseries, &stsz);
00970 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
00971 query = base_strcatalloc(query, srecnum, &stsz);
00972 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
00973
00974 for (icol = 0; icol < ncols; icol++)
00975 {
00976 query = base_strcatalloc(query, "T1.", &stsz);
00977 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00978 query = base_strcatalloc(query, " = T2.", &stsz);
00979 query = base_strcatalloc(query, pkeynames[icol], &stsz);
00980
00981 if (icol < ncols - 1)
00982 {
00983 query = base_strcatalloc(query, " AND ", &stsz);
00984 }
00985 }
00986
00987 tres = drms_query_txt(env->session, query);
00988
00989 if (tres)
00990 {
00991 if (tres->num_rows == 0)
00992 {
00993 ans = 0;
00994 }
00995 else
00996 {
00997 ans = 1;
00998 }
00999
01000 db_free_text_result(tres);
01001 }
01002 else
01003 {
01004 fprintf(stderr, "Failed: %s\n", query);
01005 istat = DRMS_ERROR_BADDBQUERY;
01006 }
01007
01008 free(query);
01009 }
01010
01011 free(lcseries);
01012 }
01013
01014 if (status)
01015 {
01016 *status = istat;
01017 }
01018
01019 return ans;
01020 }
01021
01022 static int WasGroupDeleted(DRMS_Env_t *env,
01023 long long recnum,
01024 const char *series,
01025 char **pkeynames,
01026 int ncols,
01027 int *status)
01028 {
01029 return (!GroupExists(env, recnum, series, pkeynames, ncols, status));
01030 }
01031
01032
01033 static int DeleteFromShadow(DRMS_Env_t *env,
01034 const char *series,
01035 char **pkeynames,
01036 int ncols,
01037 long long recnum)
01038 {
01039 char *lcseries = NULL;
01040 char *query = NULL;
01041 size_t stsz = 1024;
01042 char srecnum[32];
01043 int icol;
01044 int status = DRMS_SUCCESS;
01045
01046 lcseries = strdup(series);
01047 query = malloc(stsz);
01048
01049 if (lcseries && query)
01050 {
01051 snprintf(srecnum, sizeof(srecnum), "%lld", recnum);
01052 *query = '\0';
01053
01054 query = base_strcatalloc(query, "DELETE FROM ", &stsz);
01055 query = base_strcatalloc(query, lcseries, &stsz);
01056 query = base_strcatalloc(query, kShadowSuffix, &stsz);
01057 query = base_strcatalloc(query, " USING (SELECT ", &stsz);
01058
01059 for (icol = 0; icol < ncols; icol++)
01060 {
01061 query = base_strcatalloc(query, pkeynames[icol], &stsz);
01062
01063 if (icol < ncols - 1)
01064 {
01065 query = base_strcatalloc(query, ", ", &stsz);
01066 }
01067 }
01068
01069 query = base_strcatalloc(query, " FROM ", &stsz);
01070 query = base_strcatalloc(query, lcseries, &stsz);
01071 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
01072 query = base_strcatalloc(query, srecnum, &stsz);
01073 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
01074
01075 for (icol = 0; icol < ncols; icol++)
01076 {
01077 query = base_strcatalloc(query, "T1.", &stsz);
01078 query = base_strcatalloc(query, pkeynames[icol], &stsz);
01079 query = base_strcatalloc(query, " = T2.", &stsz);
01080 query = base_strcatalloc(query, pkeynames[icol], &stsz);
01081
01082 if (icol < ncols - 1)
01083 {
01084 query = base_strcatalloc(query, " AND ", &stsz);
01085 }
01086 }
01087
01088 if (drms_dms(env->session, NULL, query))
01089 {
01090
01091
01092 fprintf(stderr, "Failed: %s\n", query);
01093 status = DRMS_ERROR_BADDBQUERY;
01094 }
01095
01096 free(query);
01097 free(lcseries);
01098 }
01099 else
01100 {
01101 status = DRMS_ERROR_OUTOFMEMORY;
01102 }
01103
01104 return status;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 #define kPrivStringLen 32
01119 #define kPrivCodeLen 1
01120 #define kPrivStringList 256
01121 #define kPrivContainerUserLen 64
01122
01123 typedef enum ExtPrivState_enum
01124 {
01125 kEPStateNext = 0,
01126 kEPStateUser = 1,
01127 kEPStatePrivs = 2,
01128 kEPStateGrantor = 3,
01129 kEPStateErr = 4
01130 } ExtPrivState_t;
01131
01132 static int ExtractPrivileges(DRMS_Env_t *env, const char *ns, const char *tab, HContainer_t *privs)
01133 {
01134 static HContainer_t *privmap = NULL;
01135
01136 int status = DRMS_SUCCESS;
01137 char *lcns = NULL;
01138 char *lctab = NULL;
01139 char val[kPrivStringLen];
01140 char *query = NULL;
01141 size_t stsz = 512;
01142 DB_Text_Result_t *qres = NULL;
01143 char *row = NULL;
01144 char aprivcode[2];
01145 char *apriv = NULL;
01146 char *pch = NULL;
01147 char user[256];
01148 char *privlist = NULL;
01149
01150
01151 hcon_init(privs, kPrivStringList, kPrivContainerUserLen, NULL, NULL);
01152
01153 if (!privmap)
01154 {
01155 privmap = hcon_create(kPrivStringLen, kPrivCodeLen, NULL, NULL, NULL, NULL, 0);
01156 }
01157
01158 if (privmap)
01159 {
01160 snprintf(val, sizeof(val), "%s", "SELECT");
01161 hcon_insert(privmap, "r", val);
01162 snprintf(val, sizeof(val), "%s", "UPDATE");
01163 hcon_insert(privmap, "w", val);
01164 snprintf(val, sizeof(val), "%s", "INSERT");
01165 hcon_insert(privmap, "a", val);
01166 snprintf(val, sizeof(val), "%s", "DELETE");
01167 hcon_insert(privmap, "d", val);
01168 snprintf(val, sizeof(val), "%s", "TRUNCATE");
01169 hcon_insert(privmap, "D", val);
01170 snprintf(val, sizeof(val), "%s", "REFERENCES");
01171 hcon_insert(privmap, "x", val);
01172 snprintf(val, sizeof(val), "%s", "TRIGGER");
01173 hcon_insert(privmap, "t", val);
01174 snprintf(val, sizeof(val), "%s", "EXECUTE");
01175 hcon_insert(privmap, "X", val);
01176 snprintf(val, sizeof(val), "%s", "USAGE");
01177 hcon_insert(privmap, "U", val);
01178 snprintf(val, sizeof(val), "%s", "CREATE");
01179 hcon_insert(privmap, "C", val);
01180 snprintf(val, sizeof(val), "%s", "CONNECT");
01181 hcon_insert(privmap, "c", val);
01182 snprintf(val, sizeof(val), "%s", "TEMPORARY");
01183 hcon_insert(privmap, "T", val);
01184 }
01185 else
01186 {
01187 status = DRMS_ERROR_OUTOFMEMORY;
01188 }
01189
01190 if (status == DRMS_SUCCESS)
01191 {
01192 query = malloc(stsz);
01193 lcns = strdup(ns);
01194 lctab = strdup(tab);
01195
01196 if (query && lcns && lctab)
01197 {
01198 strtolower(lcns);
01199 strtolower(lctab);
01200 *query = '\0';
01201 query = base_strcatalloc(query, "SELECT T1.relacl AS acl FROM pg_catalog.pg_class T1, (SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = '", &stsz);
01202 query = base_strcatalloc(query, lcns, &stsz);
01203 query = base_strcatalloc(query, "\') AS T2 WHERE T1.relnamespace = T2.oid AND T1.relname = \'", &stsz);
01204 query = base_strcatalloc(query, lctab, &stsz);
01205 query = base_strcatalloc(query, "\'", &stsz);
01206
01207 if ((qres = drms_query_txt(env->session, query)) != NULL)
01208 {
01209 if (qres->num_cols == 1 && qres->num_rows == 1)
01210 {
01211 ExtPrivState_t state;
01212 char *puser = NULL;
01213
01214 row = strdup(qres->field[0][0]);
01215
01216 if (row)
01217 {
01218
01219
01220
01221 pch = row;
01222
01223 while (*pch)
01224 {
01225 if (*pch == ' ')
01226 {
01227 pch++;
01228 }
01229 else
01230 {
01231 break;
01232 }
01233 }
01234
01235 if (*pch == '{')
01236 {
01237 pch++;
01238 state = kEPStateNext;
01239 aprivcode[1] = '\0';
01240
01241 while (*pch)
01242 {
01243 if (state == kEPStateErr)
01244 {
01245 status = DRMS_ERROR_BADDBQUERY;
01246 break;
01247 }
01248 else if (state == kEPStateNext)
01249 {
01250 if (*pch == '=')
01251 {
01252 snprintf(user, sizeof(user), "%s", "PUBLIC");
01253 state = kEPStatePrivs;
01254 pch++;
01255 }
01256 else if (*pch == '/' || *pch == ',')
01257 {
01258 fprintf(stderr, "Invalid user string.\n");
01259 state = kEPStateErr;
01260 }
01261 else if (*pch == '}')
01262 {
01263
01264 break;
01265 }
01266 else
01267 {
01268 state = kEPStateUser;
01269 puser = user;
01270 }
01271 }
01272 else if (state == kEPStateUser)
01273 {
01274 if (*pch == '=')
01275 {
01276 *puser = '\0';
01277 puser = user;
01278 pch++;
01279 state = kEPStatePrivs;
01280 }
01281 else if (*pch == '/' || *pch == ',' || *pch == '}')
01282 {
01283 fprintf(stderr, "Invalid user string.\n");
01284 state = kEPStateErr;
01285 }
01286 else
01287 {
01288 *puser++ = *pch++;
01289 }
01290 }
01291 else if (state == kEPStatePrivs)
01292 {
01293 if (*pch == '/')
01294 {
01295
01296 state = kEPStateGrantor;
01297 pch++;
01298 }
01299 else if (*pch == '=' || *pch == ',' || *pch == '}')
01300 {
01301 fprintf(stderr, "Invalid grantor string.\n");
01302 state = kEPStateErr;
01303 }
01304 else
01305 {
01306 aprivcode[0] = *pch;
01307
01308 if ((apriv = (char *)hcon_lookup(privmap, aprivcode)) != NULL)
01309 {
01310 if ((privlist = (char *)hcon_lookup(privs, user)) != NULL)
01311 {
01312
01313
01314 base_strlcat(privlist, ",", kPrivStringList);
01315 base_strlcat(privlist, apriv, kPrivStringList);
01316 }
01317 else
01318 {
01319
01320
01321 hcon_insert(privs, user, apriv);
01322 }
01323
01324 pch++;
01325 }
01326 else
01327 {
01328 fprintf(stderr, "Unsupported privilege code '%s'.\n", aprivcode);
01329 state = kEPStateErr;
01330 }
01331 }
01332 }
01333 else if (state == kEPStateGrantor)
01334 {
01335 if (*pch == ',')
01336 {
01337
01338 state = kEPStateNext;
01339 pch++;
01340 }
01341 else if (*pch == '}')
01342 {
01343
01344 state = kEPStateNext;
01345 }
01346 else if (*pch == '=' || *pch == '/')
01347 {
01348 fprintf(stderr, "Invalid grantor string.\n");
01349 state = kEPStateErr;
01350 }
01351 else
01352 {
01353
01354 pch++;
01355 }
01356 }
01357 }
01358 }
01359 else
01360 {
01361
01362 }
01363
01364 free(row);
01365 row = NULL;
01366 }
01367 else
01368 {
01369 status = DRMS_ERROR_OUTOFMEMORY;
01370 }
01371 }
01372 else
01373 {
01374 fprintf(stderr, "Unexpected database response to query '%s'.\n", query);
01375 status = DRMS_ERROR_BADDBQUERY;
01376 }
01377
01378 db_free_text_result(qres);
01379 qres = NULL;
01380 }
01381 else
01382 {
01383 fprintf(stderr, "Invalid query '%s'.\n", query);
01384 status = DRMS_ERROR_BADDBQUERY;
01385 }
01386
01387 free(lctab);
01388 lctab = NULL;
01389 free(lcns);
01390 lcns = NULL;
01391 free(query);
01392 query = NULL;
01393 }
01394 else
01395 {
01396 status = DRMS_ERROR_OUTOFMEMORY;
01397 }
01398 }
01399
01400 return status;
01401 }
01402
01403
01404
01405 static int CreateShadow(DRMS_Env_t *env, const char *series, const char *tname, int *created)
01406 {
01407 int status = DRMS_SUCCESS;
01408 int ipkey;
01409 char *pklist = NULL;
01410 char *pkdatatype = NULL;
01411 char *indexquery = NULL;
01412 size_t stsz = 256;
01413 size_t stsz2 = 512;
01414 size_t stsz3 = 512;
01415 char *lcseries = strdup(series);
01416 char query[1024];
01417 DRMS_Keyword_t *key = NULL;
01418 char dtypestr[32];
01419
01420 if (created)
01421 {
01422 *created = 0;
01423 }
01424
01425 if (lcseries)
01426 {
01427 strtolower(lcseries);
01428 pklist = malloc(stsz);
01429 pkdatatype = malloc(stsz2);
01430 *pklist = '\0';
01431 *pkdatatype = '\0';
01432
01433 if (pklist && pkdatatype)
01434 {
01435 DRMS_Record_t *template = drms_template_record(env, series, &status);
01436 char lckeyname[DRMS_MAXKEYNAMELEN + 1];
01437
01438 if (status == DRMS_SUCCESS)
01439 {
01440 if (template->seriesinfo->pidx_num > 0)
01441 {
01442 indexquery = calloc(1, sizeof(char) * stsz3);
01443
01444 if (!indexquery)
01445 {
01446 status = DRMS_ERROR_OUTOFMEMORY;
01447 }
01448 }
01449 }
01450 else
01451 {
01452 fprintf(stderr, "Series %s not found.\n", series);
01453 }
01454
01455 if (status == DRMS_SUCCESS)
01456 {
01457 if (tname == NULL)
01458 {
01459 if (template->seriesinfo->hasshadow == -1)
01460 {
01461
01462
01463 ShadowExists(env, series, &status);
01464
01465 if (status == DRMS_ERROR_BADDBQUERY)
01466 {
01467 fprintf(stderr, "Unable to check database for the existence of shadow table.\n");
01468 }
01469 }
01470 }
01471 }
01472
01473 if (status == DRMS_SUCCESS)
01474 {
01475 char *shnamens = NULL;
01476 char *shnametab = NULL;
01477
01478 if (tname != NULL)
01479 {
01480 if (get_namespace(tname, &shnamens, &shnametab))
01481 {
01482 status = DRMS_ERROR_OUTOFMEMORY;
01483 }
01484 }
01485
01486 if (status == DRMS_SUCCESS)
01487 {
01488 if (template->seriesinfo->hasshadow == 0 || (tname != NULL && !drms_query_tabexists(env->session, shnamens, shnametab, &status)))
01489 {
01490 if (status != DRMS_SUCCESS)
01491 {
01492 fprintf(stderr, "Unable to check for the existence of the shadow table %s.\n", tname);
01493 }
01494
01495 if (status == DRMS_SUCCESS)
01496 {
01497 if (!env->createshadows)
01498 {
01499 status = DRMS_ERROR_CANTCREATESHADOW;
01500 fprintf(stderr, "Environment does not permit shadow-table creation.\n");
01501 }
01502 }
01503
01504 if (status == DRMS_SUCCESS)
01505 {
01506 char *ns = NULL;
01507 char *tab = NULL;
01508 size_t shnamestsz;
01509
01510 if (!get_namespace(lcseries, &ns, &tab))
01511 {
01512 if (tname == NULL)
01513 {
01514 shnamens = strdup(ns);
01515 shnametab = strdup(tab);
01516 shnamestsz = strlen(shnametab) + 1;
01517 shnametab = base_strcatalloc(shnametab, kShadowSuffix, &shnamestsz);
01518 }
01519 }
01520 else
01521 {
01522 status = DRMS_ERROR_OUTOFMEMORY;
01523 }
01524
01525 if (status == DRMS_SUCCESS)
01526 {
01527
01528
01529 for (ipkey = 0; ipkey < template->seriesinfo->pidx_num; ipkey++)
01530 {
01531 key = template->seriesinfo->pidx_keywords[ipkey];
01532 snprintf(lckeyname, sizeof(lckeyname), "%s", key->info->name);
01533 strtolower(lckeyname);
01534
01535 pklist = base_strcatalloc(pklist, lckeyname, &stsz);
01536
01537 if (key->info->type == DRMS_TYPE_STRING)
01538 {
01539 snprintf(dtypestr, sizeof(dtypestr), "%s", db_stringtype_maxlen(4000));
01540 }
01541 else
01542 {
01543 snprintf(dtypestr, sizeof(dtypestr), "%s", db_type_string(drms2dbtype(key->info->type)));
01544 }
01545
01546 pkdatatype = base_strcatalloc(pkdatatype, lckeyname, &stsz2);
01547 pkdatatype = base_strcatalloc(pkdatatype, " ", &stsz2);
01548 pkdatatype = base_strcatalloc(pkdatatype, dtypestr, &stsz2);
01549
01550 if (ipkey < template->seriesinfo->pidx_num - 1)
01551 {
01552 pklist = base_strcatalloc(pklist, ", ", &stsz);
01553 pkdatatype = base_strcatalloc(pkdatatype, ", ", &stsz2);
01554 }
01555
01556
01557
01558
01559
01560
01561
01562
01563 indexquery = base_strcatalloc(indexquery, "CREATE INDEX ", &stsz3);
01564 indexquery = base_strcatalloc(indexquery, shnametab, &stsz3);
01565 indexquery = base_strcatalloc(indexquery, "_", &stsz3);
01566 indexquery = base_strcatalloc(indexquery, lckeyname, &stsz3);
01567 indexquery = base_strcatalloc(indexquery, " ON ", &stsz3);
01568 indexquery = base_strcatalloc(indexquery, shnamens, &stsz3);
01569 indexquery = base_strcatalloc(indexquery, ".", &stsz3);
01570 indexquery = base_strcatalloc(indexquery, shnametab, &stsz3);
01571 indexquery = base_strcatalloc(indexquery, " (", &stsz3);
01572 indexquery = base_strcatalloc(indexquery, lckeyname, &stsz3);
01573 indexquery = base_strcatalloc(indexquery, ");", &stsz3);
01574 }
01575 }
01576
01577
01578
01579
01580
01581
01582 if (status == DRMS_SUCCESS)
01583 {
01584 snprintf(query, sizeof(query), "CREATE TABLE %s.%s (%s, nrecords integer, recnum bigint, PRIMARY KEY (%s))", shnamens, shnametab, pkdatatype, pklist);
01585
01586 if (drms_dms(env->session, NULL, query))
01587 {
01588 fprintf(stderr, "Failed: %s\n", query);
01589 status = DRMS_ERROR_BADDBQUERY;
01590 }
01591 else
01592 {
01593
01594 HContainer_t privs;
01595 const char *user = NULL;
01596 char *privlist = NULL;
01597
01598
01599 if (drms_dms(env->session, NULL, indexquery))
01600 {
01601 fprintf(stderr, "Failed: %s\n", indexquery);
01602 status = DRMS_ERROR_BADDBQUERY;
01603 }
01604 else
01605 {
01606 status = ExtractPrivileges(env, ns, tab, &privs);
01607
01608 if (status == DRMS_SUCCESS)
01609 {
01610 HIterator_t *hit = hiter_create(&privs);
01611
01612 if (hit)
01613 {
01614 while ((privlist = hiter_extgetnext(hit, &user)) != NULL)
01615 {
01616 snprintf(query, sizeof(query), "GRANT %s ON %s.%s TO %s", privlist, shnamens, shnametab, user);
01617
01618 if (drms_dms(env->session, NULL, query))
01619 {
01620 fprintf(stderr, "Failed: %s\n", query);
01621 status = DRMS_ERROR_BADDBQUERY;
01622 }
01623 }
01624
01625 hiter_destroy(&hit);
01626 }
01627 else
01628 {
01629 status = DRMS_ERROR_OUTOFMEMORY;
01630 }
01631
01632 hcon_free(&privs);
01633 }
01634 }
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 if (status == DRMS_SUCCESS)
01646 {
01647 if (tname == NULL)
01648 {
01649
01650
01651
01652 snprintf(query, sizeof(query), "CREATE TRIGGER %s AFTER INSERT OR DELETE on %s FOR EACH ROW EXECUTE PROCEDURE %s()", kShadowTrig, lcseries, kShadowTrigFxn);
01653
01654 if (drms_dms(env->session, NULL, query))
01655 {
01656 fprintf(stderr, "Failed: %s\n", query);
01657 status = DRMS_ERROR_BADDBQUERY;
01658 }
01659 }
01660 }
01661
01662 #if (defined TRACKSHADOWS && TRACKSHADOWS)
01663 #error
01664
01665
01666
01667 if (status == DRMS_SUCCESS)
01668 {
01669 snprintf(query,
01670 sizeof(query),
01671 "DROP TRIGGER IF EXISTS shadowtracker on %s; CREATE TRIGGER shadowtracker AFTER INSERT OR DELETE ON %s FOR EACH ROW EXECUTE PROCEDURE %s()",
01672 lcseries,
01673 lcseries,
01674 kshadowTrackerFxn);
01675
01676 if (drms_dms(env->session, NULL, query))
01677 {
01678 fprintf(stderr, "Failed: %s\n", query);
01679 status = DRMS_ERROR_BADDBQUERY;
01680 }
01681 }
01682 #endif
01683 }
01684 }
01685
01686
01687
01688
01689 if (status == DRMS_SUCCESS)
01690 {
01691 status = PopulateShadow(env, series, tname);
01692 }
01693
01694 if (status == DRMS_SUCCESS)
01695 {
01696 template->seriesinfo->hasshadow = 1;
01697
01698 if (created)
01699 {
01700 *created = 1;
01701 }
01702 }
01703
01704 if (ns)
01705 {
01706 free(ns);
01707 }
01708
01709 if (tab)
01710 {
01711 free(tab);
01712 }
01713 }
01714 }
01715 else
01716 {
01717 fprintf(stderr, "Shadow table %s%s already exists.\n", lcseries, kShadowSuffix);
01718 }
01719 }
01720
01721 if (shnamens)
01722 {
01723 free(shnamens);
01724 }
01725
01726 if (shnametab)
01727 {
01728 free(shnametab);
01729 }
01730 }
01731
01732 free(pklist);
01733 pklist = NULL;
01734 free(indexquery);
01735 indexquery = NULL;
01736 free(pkdatatype);
01737 pkdatatype = NULL;
01738 }
01739 else
01740 {
01741 status = DRMS_ERROR_OUTOFMEMORY;
01742 }
01743
01744 free(lcseries);
01745 lcseries = NULL;
01746 }
01747 else
01748 {
01749 status = DRMS_ERROR_OUTOFMEMORY;
01750 }
01751
01752 return status;
01753 }
01754
01755
01756
01757
01758
01759 static int DropShadow(DRMS_Env_t *env, const char *series, const char *tname, int *dropped)
01760 {
01761 int status = DRMS_SUCCESS;
01762 int exists = 0;
01763 char cmd[1024];
01764 char *lcseries = strdup(series);
01765 char *shadow = NULL;
01766
01767 if (dropped)
01768 {
01769 *dropped = 0;
01770 }
01771
01772
01773 if (tname != NULL)
01774 {
01775 shadow = strdup(tname);
01776 }
01777 else
01778 {
01779 shadow = malloc(strlen(lcseries) + strlen(kShadowSuffix) + 1);
01780 if (shadow)
01781 {
01782 snprintf(shadow, strlen(lcseries) + strlen(kShadowSuffix) + 1, "%s%s", lcseries, kShadowSuffix);
01783 }
01784 }
01785
01786 if (!shadow)
01787 {
01788 status = DRMS_ERROR_OUTOFMEMORY;
01789 }
01790 else
01791 {
01792 strtolower(shadow);
01793 }
01794
01795 if (status == DRMS_SUCCESS)
01796 {
01797
01798 char *shnamens = NULL;
01799 char *shnametab = NULL;
01800
01801 if (get_namespace(shadow, &shnamens, &shnametab))
01802 {
01803 status = DRMS_ERROR_OUTOFMEMORY;
01804 }
01805 else
01806 {
01807 exists = drms_query_tabexists(env->session, shnamens, shnametab, &status);
01808 }
01809 }
01810
01811 if (status == DRMS_SUCCESS)
01812 {
01813 if (lcseries)
01814 {
01815 strtolower(lcseries);
01816 }
01817 else
01818 {
01819 status = DRMS_ERROR_OUTOFMEMORY;
01820 }
01821 }
01822
01823
01824 if (status == DRMS_SUCCESS)
01825 {
01826 if (exists)
01827 {
01828 if (tname == NULL)
01829 {
01830
01831
01832 snprintf(cmd, sizeof(cmd), "DROP TRIGGER IF EXISTS %s ON %s", kShadowTrig, lcseries);
01833
01834 if (drms_dms(env->session, NULL, cmd))
01835 {
01836 fprintf(stderr, "Failed: %s\n", cmd);
01837 status = DRMS_ERROR_BADDBQUERY;
01838 }
01839 }
01840 }
01841 }
01842
01843
01844
01845 if (status == DRMS_SUCCESS)
01846 {
01847 if (exists)
01848 {
01849 snprintf(cmd, sizeof(cmd), "DROP TABLE IF EXISTS %s CASCADE", shadow);
01850
01851 if (drms_dms(env->session, NULL, cmd))
01852 {
01853 fprintf(stderr, "Failed: %s\n", cmd);
01854 status = DRMS_ERROR_BADDBQUERY;
01855 }
01856 else
01857 {
01858 if (dropped)
01859 {
01860 *dropped = 1;
01861 }
01862 }
01863 }
01864 }
01865
01866
01867 if (shadow)
01868 {
01869 free(shadow);
01870 shadow = NULL;
01871 }
01872
01873 if (lcseries)
01874 {
01875 free(lcseries);
01876 lcseries = NULL;
01877 }
01878
01879 return status;
01880 }
01881
01882
01883
01884
01885 static int IsGroupNew(DRMS_Env_t *env,
01886 long long recnum,
01887 const char *series,
01888 char **pkeynames,
01889 int ncols,
01890 int *status)
01891 {
01892 char *query = NULL;
01893 size_t stsz = 8192;
01894 char scolnum[8];
01895 char srecnum[32];
01896 DB_Text_Result_t *tres = NULL;
01897 int ans = -1;
01898 int icol;
01899 char *lcseries = NULL;
01900 int istat = DRMS_SUCCESS;
01901
01902 snprintf(srecnum, sizeof(srecnum), "%lld", recnum);
01903
01904 lcseries = strdup(series);
01905
01906 if (lcseries)
01907 {
01908 strtolower(lcseries);
01909 query = malloc(stsz);
01910 if (query)
01911 {
01912 *query = '\0';
01913
01914 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
01915 query = base_strcatalloc(query, lcseries, &stsz);
01916 query = base_strcatalloc(query, " AS T1, (SELECT ", &stsz);
01917
01918 for (icol = 0; icol < ncols; icol++)
01919 {
01920 snprintf(scolnum, sizeof(scolnum), "%d", icol);
01921 query = base_strcatalloc(query, pkeynames[icol], &stsz);
01922 query = base_strcatalloc(query, " AS p", &stsz);
01923 query = base_strcatalloc(query, scolnum, &stsz);
01924
01925 if (icol < ncols - 1)
01926 {
01927 query = base_strcatalloc(query, ", ", &stsz);
01928 }
01929 }
01930
01931 query = base_strcatalloc(query, " FROM ", &stsz);
01932 query = base_strcatalloc(query, lcseries, &stsz);
01933 query = base_strcatalloc(query, " WHERE recnum = ", &stsz);
01934 query = base_strcatalloc(query, srecnum, &stsz);
01935 query = base_strcatalloc(query, ") AS T2 WHERE ", &stsz);
01936
01937 for (icol = 0; icol < ncols; icol++)
01938 {
01939 snprintf(scolnum, sizeof(scolnum), "%d", icol);
01940 query = base_strcatalloc(query, "T1.", &stsz);
01941 query = base_strcatalloc(query, pkeynames[icol], &stsz);
01942 query = base_strcatalloc(query, " = T2.p", &stsz);
01943 query = base_strcatalloc(query, scolnum, &stsz);
01944
01945 if (icol < ncols - 1)
01946 {
01947 query = base_strcatalloc(query, " AND ", &stsz);
01948 }
01949 }
01950 }
01951 else
01952 {
01953 istat = DRMS_ERROR_OUTOFMEMORY;
01954 }
01955
01956 free(lcseries);
01957 lcseries = NULL;
01958 }
01959 else
01960 {
01961 istat = DRMS_ERROR_OUTOFMEMORY;
01962 }
01963
01964
01965 if (istat == DRMS_SUCCESS)
01966 {
01967 tres = drms_query_txt(env->session, query);
01968
01969 if (tres)
01970 {
01971 if (tres->num_rows == 1 && tres->num_cols == 1)
01972 {
01973 long long num = atoll(tres->field[0][0]);
01974
01975 if (num < 1)
01976 {
01977
01978 fprintf(stderr, "Unexpected record count %lld; should be at least one.\n", num);
01979 istat = DRMS_ERROR_BADFIELDCOUNT;
01980 }
01981 else
01982 {
01983 ans = (num == 1) ? 1 : 0;
01984 }
01985 }
01986
01987 db_free_text_result(tres);
01988 }
01989 else
01990 {
01991 fprintf(stderr, "Failed: %s\n", query);
01992 istat = DRMS_ERROR_BADDBQUERY;
01993 }
01994
01995 free(query);
01996 query = NULL;
01997 }
01998
01999 if (status)
02000 {
02001 *status = istat;
02002 }
02003
02004 return ans;
02005 }
02006
02007 static char *PrependFields(const char *list, const char *prefix, int *status)
02008 {
02009 char *pnext = NULL;
02010 char *fieldscp = NULL;
02011 char *qualfields = NULL;
02012 char *pch = NULL;
02013 size_t stsz2 = 4096;
02014 int istat = DRMS_SUCCESS;
02015
02016 qualfields = malloc(stsz2);
02017 fieldscp = strdup(list);
02018
02019 if (qualfields && fieldscp)
02020 {
02021 *qualfields = '\0';
02022
02023 pnext = fieldscp;
02024
02025 while ((pch = strchr(pnext, ',')) != NULL)
02026 {
02027 *pch = '\0';
02028 qualfields = base_strcatalloc(qualfields, prefix, &stsz2);
02029 qualfields = base_strcatalloc(qualfields, pnext, &stsz2);
02030 qualfields = base_strcatalloc(qualfields, ", ", &stsz2);
02031 pch++;
02032
02033 while (*pch == ' ')
02034 {
02035 pch++;
02036 }
02037
02038 pnext = pch;
02039 }
02040
02041
02042 qualfields = base_strcatalloc(qualfields, prefix, &stsz2);
02043 qualfields = base_strcatalloc(qualfields, pnext, &stsz2);
02044
02045 free(fieldscp);
02046 fieldscp = NULL;
02047 }
02048
02049 if (status)
02050 {
02051 *status = istat;
02052 }
02053
02054 return qualfields;
02055 }
02056
02057 static char *CreatePKeyList(DRMS_Env_t *env, const char *series, const char *prefix, const char *suffix, char *pkeyarr[], int *npkey, int doTypes, int *status)
02058 {
02059 int istat = DRMS_SUCCESS;
02060 int ipkey;
02061 char lckeyname[DRMS_MAXKEYNAMELEN];
02062 DRMS_Keyword_t *key = NULL;
02063 DRMS_Record_t *template = drms_template_record(env, series, &istat);
02064 char *pklist = NULL;
02065 size_t stsz = 4096;
02066
02067 if (istat == DRMS_SUCCESS)
02068 {
02069 if (template->seriesinfo->pidx_num > 0)
02070 {
02071 pklist = malloc(stsz);
02072
02073 if (pklist)
02074 {
02075 *pklist = '\0';
02076
02077 for (ipkey = 0; ipkey < template->seriesinfo->pidx_num; ipkey++)
02078 {
02079 key = template->seriesinfo->pidx_keywords[ipkey];
02080 snprintf(lckeyname, sizeof(lckeyname), "%s", key->info->name);
02081 strtolower(lckeyname);
02082
02083 if (prefix)
02084 {
02085 pklist = base_strcatalloc(pklist, prefix, &stsz);
02086 }
02087
02088 pklist = base_strcatalloc(pklist, lckeyname, &stsz);
02089
02090 if (doTypes)
02091 {
02092 pklist = base_strcatalloc(pklist, " ", &stsz);
02093 if (key->info->type == DRMS_TYPE_STRING)
02094 {
02095 pklist = base_strcatalloc(pklist, db_stringtype_maxlen(4000), &stsz);
02096 }
02097 else
02098 {
02099 pklist = base_strcatalloc(pklist, db_type_string(drms2dbtype(key->info->type)), &stsz);
02100 }
02101 }
02102
02103 if (suffix)
02104 {
02105 pklist = base_strcatalloc(pklist, suffix, &stsz);
02106 }
02107
02108 if (ipkey < template->seriesinfo->pidx_num - 1)
02109 {
02110 pklist = base_strcatalloc(pklist, ", ", &stsz);
02111 }
02112
02113
02114 if (pkeyarr)
02115 {
02116 pkeyarr[ipkey] = strdup(lckeyname);
02117 }
02118 }
02119 }
02120 else
02121 {
02122 istat = DRMS_ERROR_OUTOFMEMORY;
02123 }
02124 }
02125 }
02126
02127 if (npkey)
02128 {
02129 *npkey = template->seriesinfo->pidx_num;
02130 }
02131
02132 if (status)
02133 {
02134 *status = istat;
02135 }
02136
02137 return pklist;
02138 }
02139
02140 char *drms_series_createPkeyList(DRMS_Env_t *env, const char *series, const char *prefix, const char *suffix, char *pkeyarr[], int *npkey, int *status)
02141 {
02142 return CreatePKeyList(env, series, prefix, suffix, pkeyarr, npkey, 0, status);
02143 }
02144
02145 char *drms_series_createPkeyColList(DRMS_Env_t *env, const char *series, const char *prefix, const char *suffix, char *pkeyarr[], int *npkey, int *status)
02146 {
02147 return CreatePKeyList(env, series, prefix, suffix, pkeyarr, npkey, 1, status);
02148 }
02149
02150 static void DetermineDefval(DRMS_Keyword_t *key, char *defvalout)
02151 {
02152 int pret = 0;
02153 TIME interval;
02154 int internal;
02155 char defval[DRMS_DEFVAL_MAXLEN];
02156
02157 if (defvalout)
02158 {
02159 if (key->info->type == DRMS_TYPE_TIME)
02160 {
02161 interval = atoinc(key->info->unit);
02162 internal = (interval > 0);
02163
02164 pret = drms_sprintfval(defval,
02165 key->info->type,
02166 &key->value,
02167 internal);
02168 XASSERT(pret < DRMS_DEFVAL_MAXLEN);
02169 }
02170 else
02171 {
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183 pret = drms_sprintfval(defval,
02184 key->info->type,
02185 &key->value,
02186 0);
02187 XASSERT(pret < DRMS_DEFVAL_MAXLEN);
02188
02189
02190 if (key->info->type == DRMS_TYPE_STRING)
02191 {
02192 size_t slen = strlen(defval);
02193 int ich;
02194
02195 if (slen > 1)
02196 {
02197 if ((defval[0] == '\'' && defval[slen - 1] == '\'') ||
02198 (defval[0] == '\"' && defval[slen - 1] == '\"'))
02199 {
02200 ich = 0;
02201 while(ich < slen - 2)
02202 {
02203 defval[ich] = defval[ich + 1];
02204 ich++;
02205 }
02206
02207 defval[ich] = '\0';
02208 }
02209 }
02210 }
02211 }
02212
02213 snprintf(defvalout, DRMS_DEFVAL_MAXLEN, "%s", defval);
02214 }
02215 }
02216
02217
02218
02219
02220 int get_namespace(const char *seriesname, char **namespace, char **shortname) {
02221 if (strchr(seriesname, '.')) {
02222 const char *p = seriesname;
02223 while (*p != '.') {
02224 p++;
02225 }
02226 *namespace = ns(seriesname);
02227 if (shortname) {
02228 *shortname = strdup(p+1);
02229 }
02230 return 0;
02231 } else {
02232 return 1;
02233 }
02234 }
02235
02236 int drms_series_exists(DRMS_Env_t *drmsEnv, const char *sname, int *status)
02237 {
02238 int ret = 0;
02239
02240 if (sname != NULL && *sname != '\0')
02241 {
02242 drms_template_record(drmsEnv, sname, status);
02243
02244 if (*status == DRMS_ERROR_UNKNOWNSERIES)
02245 {
02246 ret = 0;
02247 }
02248 else if (*status != DRMS_SUCCESS)
02249 {
02250 fprintf(stderr, "DRMS Error calling drms_series_exists.\n");
02251 }
02252 else
02253 {
02254 ret = 1;
02255 }
02256 }
02257
02258 return ret;
02259 }
02260
02261
02262
02263
02264
02265
02266
02267
02268 int drms_insert_series(DRMS_Session_t *session, int update, DRMS_Record_t *template, int perms)
02269 {
02270 int i, len=0, segnum;
02271 char *pidx_buf=0, *dbidx_buf=0, scopestr[100], *axisstr=0;
02272 DRMS_SeriesInfo_t *si;
02273 DRMS_Keyword_t *key;
02274 DRMS_Segment_t *seg;
02275 DRMS_Link_t *link;
02276 HIterator_t hit;
02277 char *linktype,*p,*q;
02278 char dyn[]="dynamic";
02279 char stat[]="static";
02280 char defval[DRMS_DEFVAL_MAXLEN]={0};
02281 char *createstmt=0, *series_lower=0, *namespace=0;
02282 DB_Text_Result_t *qres;
02283
02284 createstmt = malloc(30000);
02285 XASSERT(createstmt);
02286
02287
02288 if (drms_makewritable(template->env) != DRMS_SUCCESS)
02289 {
02290 goto failure;
02291 }
02292
02293
02294 if (drms_link_getpidx(template) != DRMS_SUCCESS)
02295 {
02296 goto failure;
02297 }
02298
02299 si = template->seriesinfo;
02300
02301 if (get_namespace(si->seriesname, &namespace, &series_lower)) {
02302 fprintf(stderr, "Invalid seriesname: namespace missing\n");
02303 goto failure;
02304 }
02305 strtolower(namespace);
02306
02307
02308 strtolower(series_lower);
02309
02310
02311 sprintf(createstmt, "select * from pg_namespace where nspname = '%s'", namespace);
02312 if ( (qres = drms_query_txt(session, createstmt)) != NULL) {
02313 if (qres->num_rows == 0) {
02314 fprintf(stderr, "Namespace %s does not exist.\n", namespace);
02315 goto failure;
02316 }
02317 db_free_text_result(qres);
02318 }
02319
02320
02321
02322
02323 if (session->db_direct) {
02324 sprintf(createstmt, "select has_schema_privilege('%s', '%s', 'create')",
02325 session->db_handle->dbuser,
02326 namespace);
02327 if ( (qres = drms_query_txt(session, createstmt)) != NULL) {
02328 if (qres->num_rows > 0) {
02329 if (qres->field[0][0][0] == 'f') {
02330 fprintf(stderr, "dbuser %s does not have create privilege in namespace %s.\n",
02331 session->db_handle->dbuser, namespace);
02332 goto failure;
02333 }
02334 } else {
02335 fprintf(stderr, "Failed: %s\n", createstmt);
02336 goto failure;
02337 }
02338 } else {
02339 fprintf(stderr, "Failed: %s\n", createstmt);
02340 goto failure;
02341 }
02342 db_free_text_result(qres);
02343 }
02344
02345 sprintf(createstmt, "set search_path to %s", namespace);
02346 if(drms_dms(session, NULL, createstmt)) {
02347 fprintf(stderr, "Failed: %s\n", createstmt);
02348 goto failure;
02349 }
02350
02351 if (si->pidx_num==0)
02352 {
02353 pidx_buf = malloc(2);
02354 XASSERT(pidx_buf);
02355 *pidx_buf = 0;
02356 }
02357 else
02358 {
02359 len = 0;
02360 for (i=0; i<si->pidx_num; i++)
02361 len += strlen((si->pidx_keywords[i])->info->name) + 3;
02362 pidx_buf = malloc(len+1);
02363 XASSERT(pidx_buf);
02364 memset(pidx_buf,0,len+1);
02365 p = pidx_buf;
02366 p += sprintf(p,"%s",(si->pidx_keywords[0])->info->name);
02367 for (i=1; i<si->pidx_num; i++)
02368 p += sprintf(p,", %s",(si->pidx_keywords[i])->info->name);
02369 }
02370
02371 if (si->dbidx_num <= 0)
02372 {
02373 dbidx_buf = malloc(2);
02374 XASSERT(dbidx_buf);
02375 *dbidx_buf = 0;
02376 }
02377 else
02378 {
02379 len = 0;
02380 for (i=0; i<si->dbidx_num; i++)
02381 len += strlen((si->dbidx_keywords[i])->info->name) + 3;
02382 dbidx_buf = malloc(len+1);
02383 XASSERT(dbidx_buf);
02384 memset(dbidx_buf,0,len+1);
02385 p = dbidx_buf;
02386 p += sprintf(p,"%s",(si->dbidx_keywords[0])->info->name);
02387 for (i=1; i<si->dbidx_num; i++)
02388 p += sprintf(p,", %s",(si->dbidx_keywords[i])->info->name);
02389 }
02390
02391 if (drms_dmsv(session, NULL, "insert into " DRMS_MASTER_SERIES_TABLE
02392 "(seriesname, description, author, owner, unitsize, archive,"
02393 "retention, tapegroup, version, primary_idx, dbidx, created) values (?,?,?,?,"
02394 "?,?,?,?,?,?,?,LOCALTIMESTAMP(0))", -1,
02395 DB_STRING, si->seriesname, DB_STRING, si->description,
02396 DB_STRING, si->author, DB_STRING, si->owner,
02397 DB_INT4, si->unitsize, DB_INT4, si->archive,
02398 DB_INT4, si->retention, DB_INT4, si->tapegroup,
02399 DB_STRING, si->version,
02400 DB_STRING, pidx_buf,
02401 DB_STRING, dbidx_buf))
02402 goto failure;
02403
02404 p = createstmt;
02405
02406 p += sprintf(p,"create table %s (",series_lower);
02407 p += sprintf(p,"recnum bigint not null");
02408 p += sprintf(p,", sunum bigint");
02409 p += sprintf(p,", slotnum integer");
02410 p += sprintf(p,", sessionid bigint");
02411 p += sprintf(p,", sessionns text");
02412
02413
02414 hiter_new_sort(&hit, &template->links, drms_link_ranksort);
02415 while( (link = (DRMS_Link_t *)hiter_getnext(&hit)) )
02416 {
02417 if (link->info->type == STATIC_LINK)
02418 {
02419 linktype = stat;
02420 p += sprintf(p,", ln_%s bigint",link->info->name);
02421 }
02422 else
02423 {
02424 linktype = dyn;
02425 if (link->info->pidx_num) {
02426 p += sprintf(p,", ln_%s_isset %s default 0", link->info->name,
02427 db_type_string(drms2dbtype(DRMS_TYPE_INT)));
02428 }
02429
02430
02431 for (i=0; i<link->info->pidx_num; i++)
02432 {
02433 p += sprintf(p,", ln_%s_%s %s",link->info->name, link->info->pidx_name[i],
02434 db_type_string(drms2dbtype(link->info->pidx_type[i])));
02435 }
02436 }
02437
02438 if (drms_dmsv(session, NULL, "insert into " DRMS_MASTER_LINK_TABLE
02439 "(seriesname, linkname, target_seriesname, type, "
02440 "description) values (?,?,?,?,?)", -1,
02441 DB_STRING, si->seriesname, DB_STRING, link->info->name,
02442 DB_STRING, link->info->target_series, DB_STRING, linktype,
02443 DB_STRING, link->info->description))
02444 {
02445 hiter_free(&hit);
02446 goto failure;
02447 }
02448 }
02449
02450 hiter_free(&hit);
02451
02452
02453 hiter_new_sort(&hit, &template->keywords, drms_keyword_ranksort);
02454 while( (key = (DRMS_Keyword_t *)hiter_getnext(&hit)) )
02455 {
02456 if (!key->info->islink && !drms_keyword_isconstant(key))
02457 {
02458 if (key->info->type==DRMS_TYPE_STRING)
02459 {
02460 p += sprintf(p,", %s %s",key->info->name,
02461 db_stringtype_maxlen(4000));
02462 }
02463 else
02464 {
02465 p += sprintf(p,", %s %s",key->info->name,
02466 db_type_string(drms2dbtype(key->info->type)));
02467 }
02468 }
02469 #ifdef DEBUG
02470 printf("keyword '%s'\n",key->info->name);
02471 #endif
02472
02473
02474
02475
02476
02477 if (drms_keyword_getperseg(key))
02478 {
02479 len = strlen(key->info->name);
02480 if (strcmp(key->info->name+len-4,"_000"))
02481 continue;
02482 key->info->name[len-4] = 0;
02483 #ifdef DEBUG
02484 printf("Inserting per-segment keyword %s\n",key->info->name);
02485 #endif
02486 }
02487
02488 DetermineDefval(key, defval);
02489
02490
02491
02492
02493
02494
02495 if (drms_dmsv(session, NULL, "insert into " DRMS_MASTER_KEYWORD_TABLE
02496 "(seriesname, keywordname, linkname, targetkeyw, type, "
02497 "defaultval, format, unit, description, islink, "
02498 "isconstant, persegment) values (?,?,?,?,?,?,?,?,?,?,?,?)",
02499 -1,
02500 DB_STRING, key->record->seriesinfo->seriesname,
02501 DB_STRING, key->info->name, DB_STRING, key->info->linkname,
02502 DB_STRING, key->info->target_key,
02503 DB_STRING, drms_type2str(key->info->type), DB_STRING, defval,
02504 DB_STRING, key->info->format, DB_STRING, key->info->unit,
02505 DB_STRING, key->info->description,
02506 DB_INT4, key->info->islink,DB_INT4, key->info->recscope,
02507
02508 DB_INT4, key->info->kwflags))
02509 {
02510 hiter_free(&hit);
02511 goto failure;
02512 }
02513
02514
02515
02516
02517
02518 if (drms_keyword_getperseg(key))
02519 key->info->name[len-4] = '_';
02520
02521 }
02522
02523 hiter_free(&hit);
02524
02525
02526 hiter_new_sort(&hit, &template->segments, drms_segment_ranksort);
02527 segnum = 0;
02528 while( (seg = (DRMS_Segment_t *)hiter_getnext(&hit)) )
02529 {
02530 switch(seg->info->scope)
02531 {
02532 case DRMS_CONSTANT:
02533 strcpy(scopestr,"constant");
02534 break;
02535 case DRMS_VARIABLE:
02536 strcpy(scopestr,"variable");
02537 break;
02538 case DRMS_VARDIM:
02539 strcpy(scopestr,"vardim");
02540 break;
02541 default:
02542 printf("ERROR: Invalid value of scope (%d).\n", (int)seg->info->scope);
02543 hiter_free(&hit);
02544 goto failure;
02545 }
02546 if (seg->info->naxis < 0 || seg->info->naxis>DRMS_MAXRANK)
02547 {
02548 printf("ERROR: Invalid value of rank (%d).\n",seg->info->naxis);
02549 hiter_free(&hit);
02550 goto failure;
02551 }
02552 else
02553 {
02554 axisstr = malloc(2*seg->info->naxis*20+1);
02555 XASSERT(axisstr);
02556 axisstr[0] = 0;
02557 q = axisstr;
02558 if (seg->info->naxis>0)
02559 {
02560 q += sprintf(q,"%d",seg->axis[0]);
02561 for (i=1; i<seg->info->naxis; i++)
02562 q+=sprintf(q,", %d",seg->axis[i]);
02563 if (seg->info->protocol == DRMS_TAS)
02564 for (i=0; i<seg->info->naxis; i++)
02565 q+=sprintf(q,", %d",seg->blocksize[i]);
02566 }
02567 }
02568
02569 if (drms_dmsv(session, NULL, "insert into " DRMS_MASTER_SEGMENT_TABLE
02570 "(seriesname, segmentname, segnum, scope, type,"
02571 " naxis, axis, unit, protocol, description, islink, linkname, targetseg)"
02572 " values (?,?,?,?,?,?,?,?,?,?,?,?,?)",
02573 -1,
02574 DB_STRING, seg->record->seriesinfo->seriesname,
02575 DB_STRING, seg->info->name, DB_INT4, seg->info->segnum,
02576 DB_STRING, scopestr,
02577 DB_STRING, drms_type2str(seg->info->type),
02578 DB_INT4, seg->info->naxis, DB_STRING, axisstr,
02579 DB_STRING, seg->info->unit,
02580 DB_STRING, drms_prot2str(seg->info->protocol),
02581 DB_STRING, seg->info->description,
02582 DB_INT4, seg->info->islink,
02583 DB_STRING, seg->info->linkname,
02584 DB_STRING, seg->info->target_seg))
02585 {
02586 free(axisstr);
02587 hiter_free(&hit);
02588 goto failure;
02589 }
02590 free(axisstr);
02591
02592
02593 p += sprintf(p,", sg_%03d_file text", segnum);
02594
02595 if (seg->info->scope==DRMS_VARDIM)
02596 {
02597
02598 for (i=0; i<seg->info->naxis; i++)
02599 {
02600 p += sprintf(p,", sg_%03d_axis%03d integer",segnum,i);
02601 }
02602 }
02603
02604 segnum++;
02605 }
02606
02607 hiter_free(&hit);
02608
02609 p += sprintf(p,", primary key(recnum))");
02610 #ifdef DEBUG
02611 printf("statement = '%s'\n",createstmt);
02612 #endif
02613
02614
02615 if(drms_dms(session, NULL, createstmt))
02616 goto failure;
02617
02618
02619
02620
02621
02622
02623
02624 if (si->dbidx_num == -1 && si->pidx_num>0 && si->pidx_num <= 5)
02625 {
02626
02627 p = createstmt;
02628 p += sprintf(p,"create index %s_prime_idx on %s ( %s )",
02629 series_lower, series_lower, pidx_buf);
02630 if(drms_dms(session, NULL, createstmt))
02631 goto failure;
02632 }
02633
02634 if (si->dbidx_num > 0) {
02635 p = createstmt;
02636 for (i = 0; i < si->dbidx_num; i++) {
02637 char *dbidx_name = (si->dbidx_keywords[i])->info->name;
02638 p += sprintf(p,"create index %s_%s on %s ( %s );",
02639 series_lower, dbidx_name, series_lower, dbidx_name);
02640 }
02641 if(drms_dms(session, NULL, createstmt))
02642 goto failure;
02643 }
02644
02645
02646 if (drms_sequence_create(session, template->seriesinfo->seriesname))
02647 goto failure;
02648
02649
02650 p = createstmt;
02651 p += sprintf(p,"grant select on %s to public;",series_lower);
02652 p += sprintf(p,"grant select on %s_seq to public;",series_lower);
02653 p += sprintf(p,"grant delete on %s to sumsadmin;",series_lower);
02654 if(drms_dms(session, NULL, createstmt))
02655 goto failure;
02656
02657
02658 sprintf(createstmt, "select owner from admin.ns where name = '%s'", namespace);
02659 if ( (qres = drms_query_txt(session, createstmt)) != NULL) {
02660 if (qres->num_rows > 0) {
02661 char *nsowner = qres->field[0][0];
02662 p = createstmt;
02663 p += sprintf(p, "grant select, insert, update, delete on %s to %s;", series_lower, nsowner);
02664 p += sprintf(p, "grant update on %s_seq to %s;", series_lower, nsowner);
02665 if(drms_dms(session, NULL, createstmt))
02666 goto failure;
02667 } else {
02668 fprintf(stderr, "Failed: %s\n", createstmt);
02669 goto failure;
02670 }
02671 } else {
02672 fprintf(stderr, "Failed: %s\n", createstmt);
02673 goto failure;
02674 }
02675 db_free_text_result(qres);
02676
02677
02678 if (0 && perms)
02679 {
02680 char permstr[30];
02681 p = permstr;
02682 if (perms & DB_PRIV_SELECT)
02683 p += sprintf(p,"select");
02684 if (perms & DB_PRIV_INSERT)
02685 {
02686 if (p!=permstr)
02687 p += sprintf(p,", ");
02688 p += sprintf(p,"insert");
02689 }
02690 if (perms & DB_PRIV_UPDATE)
02691 {
02692 if (p!=permstr)
02693 p += sprintf(p,", ");
02694 p += sprintf(p,"update");
02695 }
02696 sprintf(createstmt,"grant %s on %s to jsoc",permstr,series_lower);
02697 #ifdef DEBUG
02698 printf("Setting permisions on table with '%s'\n",createstmt);
02699 #endif
02700
02701 if(drms_dms(session, NULL, createstmt))
02702 goto failure;
02703
02704 sprintf(createstmt,"grant %s on %s_seq to jsoc",permstr,series_lower);
02705 #ifdef DEBUG
02706 printf("Setting permisions on table with '%s'\n",createstmt);
02707 #endif
02708
02709 if(drms_dms(session, NULL, createstmt))
02710 goto failure;
02711
02712 if (perms & DB_PRIV_SELECT)
02713 {
02714 sprintf(createstmt,"grant select on %s to jsoc_reader",series_lower);
02715
02716 if(drms_dms(session, NULL, createstmt))
02717 goto failure;
02718 sprintf(createstmt,"grant select on %s_seq to jsoc_reader",series_lower);
02719
02720 if(drms_dms(session, NULL, createstmt))
02721 goto failure;
02722 }
02723 }
02724
02725
02726 if (si->createshadow)
02727 {
02728 int wascreated = 0;
02729
02730 if (CreateShadow(template->env, si->seriesname, NULL, &wascreated) != DRMS_SUCCESS || !wascreated)
02731 {
02732
02733
02734
02735 goto failure;
02736 }
02737 }
02738
02739 free(namespace);
02740 free(series_lower);
02741 free(pidx_buf);
02742 free(dbidx_buf);
02743 free(createstmt);
02744 return 0;
02745 failure:
02746 fprintf(stderr,"drms_insert_series(): failed to insert series %s.\n",
02747 template->seriesinfo->seriesname);
02748 free(namespace);
02749 free(series_lower);
02750 free(pidx_buf);
02751 free(dbidx_buf);
02752 free(createstmt);
02753 return 1;
02754 }
02755
02756 static int RankReverseSort(const void *he1, const void *he2)
02757 {
02758 DRMS_Keyword_t *k1 = (DRMS_Keyword_t *)hcon_getval(*((HContainerElement_t **)he1));
02759 DRMS_Keyword_t *k2 = (DRMS_Keyword_t *)hcon_getval(*((HContainerElement_t **)he2));
02760
02761 XASSERT(k1 && k2);
02762
02763 return (k1->info->rank < k2->info->rank) ? 1 : (k1->info->rank > k2->info->rank ? -1 : 0);
02764 }
02765
02766
02767 int drms_series_gethighestkeyrank(DRMS_Env_t *env, const char *series, int *status)
02768 {
02769 int drmsstat = DRMS_SUCCESS;
02770 DRMS_Record_t *rec = NULL;
02771 HContainer_t *keys = NULL;
02772 DRMS_Keyword_t *key = NULL;
02773 HIterator_t hit;
02774 int rv = -1;
02775
02776 rec = drms_template_record(env, series, &drmsstat);
02777
02778 if (!rec || drmsstat)
02779 {
02780 if (!drmsstat)
02781 {
02782 drmsstat = DRMS_ERROR_UNKNOWNSERIES;
02783 }
02784
02785 fprintf(stderr, "Unable to obtain template record for series %s; error %d.\n", series, drmsstat);
02786 }
02787 else
02788 {
02789 keys = &rec->keywords;
02790 if (hcon_size(keys) > 0)
02791 {
02792 hiter_new_sort(&hit, keys, RankReverseSort);
02793 key = (DRMS_Keyword_t *)hiter_getnext(&hit);
02794 if (!key)
02795 {
02796 fprintf(stderr, "Missing keyword.\n");
02797 drmsstat = DRMS_ERROR_UNKNOWNKEYWORD;
02798 }
02799 else
02800 {
02801 rv = key->info->rank;
02802 }
02803
02804 hiter_free(&hit);
02805 }
02806 }
02807
02808 if (status)
02809 {
02810 *status = drmsstat;
02811 }
02812
02813 return rv;
02814 }
02815
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
02830 int drms_addkeys_toseries(DRMS_Env_t *env, const char *series, const char *spec, char **sql)
02831 {
02832 int drmsstat = DRMS_SUCCESS;
02833 DRMS_Record_t *seriestemp = NULL;
02834 HContainer_t *keys = NULL;
02835 int hirank = -1;
02836 HIterator_t *hit = NULL;
02837 DRMS_Keyword_t *key = NULL;
02838 int isrepl = 0;
02839 char defval[DRMS_DEFVAL_MAXLEN];
02840 DRMS_Session_t *session = env->session;
02841 char numbuf[32];
02842 size_t szalterbuf;
02843 char *tblactionbuf = NULL;
02844 size_t szbuf;
02845 char *sqlbuf = NULL;
02846 int first;
02847 int skipkey;
02848 int len;
02849 char *ns = NULL;
02850 char *tab = NULL;
02851 int nkeys;
02852
02853 *sql = NULL;
02854
02855 if (series && *series && spec && *spec)
02856 {
02857 drmsstat = drms_makewritable(env);
02858
02859 if (drmsstat == DRMS_SUCCESS)
02860 {
02861 seriestemp = drms_template_record(env, series, &drmsstat);
02862
02863 if (seriestemp && drmsstat == DRMS_SUCCESS)
02864 {
02865 isrepl = drms_series_isreplicated(env, series);
02866
02867
02868 keys = drms_parse_keyworddesc(env, spec, &drmsstat);
02869
02870 if (keys && !drmsstat && hcon_size(keys) >= 1)
02871 {
02872
02873 hirank = drms_series_gethighestkeyrank(env, series, &drmsstat);
02874 if (drmsstat)
02875 {
02876 hirank = -1;
02877 drmsstat = DRMS_SUCCESS;
02878 }
02879
02880 if (isrepl)
02881 {
02882 szbuf = 1024;
02883 sqlbuf = calloc(1, szbuf);
02884
02885 if (!sqlbuf)
02886 {
02887 drmsstat = DRMS_ERROR_OUTOFMEMORY;
02888 }
02889 else
02890 {
02891 szalterbuf = 512;
02892 tblactionbuf = calloc(1, szalterbuf);
02893
02894 if (!tblactionbuf)
02895 {
02896 drmsstat = DRMS_ERROR_OUTOFMEMORY;
02897 }
02898 }
02899 }
02900 else
02901 {
02902 szalterbuf = 512;
02903 tblactionbuf = calloc(1, szalterbuf);
02904
02905 if (!tblactionbuf)
02906 {
02907 drmsstat = DRMS_ERROR_OUTOFMEMORY;
02908 }
02909 }
02910
02911 if (drmsstat == DRMS_SUCCESS)
02912 {
02913 if (get_namespace(series, &ns, &tab))
02914 {
02915 drmsstat = DRMS_ERROR_OUTOFMEMORY;
02916 }
02917 }
02918
02919 if (drmsstat == DRMS_SUCCESS)
02920 {
02921
02922 hit = hiter_create(keys);
02923
02924 if (hit)
02925 {
02926 first = 1;
02927 nkeys = 0;
02928 while((key = (DRMS_Keyword_t *)hiter_getnext(hit)) != NULL)
02929 {
02930
02931 if (drms_keyword_lookup(seriestemp, key->info->name, 0))
02932 {
02933 fprintf(stderr, "Cannot add keyword %s, skipping.\n", key->info->name);
02934 continue;
02935 }
02936
02937 nkeys++;
02938
02939 key->record = seriestemp;
02940
02941
02942
02943
02944
02945
02946
02947
02948 if (hirank >= 0)
02949 {
02950 key->info->rank = hirank;
02951 key->info->kwflags |= (hirank + 1) << 16;
02952 hirank++;
02953 }
02954 else
02955 {
02956 key->info->rank = -1;
02957 key->info->kwflags &= 0x0000FFFF;
02958 }
02959
02960 DetermineDefval(key, defval);
02961
02962
02963
02964
02965
02966
02967
02968 if (!key->info->islink && !drms_keyword_isconstant(key))
02969 {
02970 if (first)
02971 {
02972 first = 0;
02973 }
02974 else
02975 {
02976 tblactionbuf = base_strcatalloc(tblactionbuf, ", ", &szalterbuf);
02977 }
02978
02979 tblactionbuf = base_strcatalloc(tblactionbuf, "ADD COLUMN ", &szalterbuf);
02980 tblactionbuf = base_strcatalloc(tblactionbuf, key->info->name, &szalterbuf);
02981 tblactionbuf = base_strcatalloc(tblactionbuf, " ", &szalterbuf);
02982
02983 if (key->info->type == DRMS_TYPE_STRING)
02984 {
02985 tblactionbuf = base_strcatalloc(tblactionbuf, db_stringtype_maxlen(4000), &szalterbuf);
02986 }
02987 else
02988 {
02989 tblactionbuf = base_strcatalloc(tblactionbuf, db_type_string(drms2dbtype(key->info->type)), &szalterbuf);
02990 }
02991 }
02992
02993 skipkey = 0;
02994 if (drms_keyword_getperseg(key))
02995 {
02996 len = strlen(key->info->name);
02997 if (strcmp(key->info->name + len - 4, "_000"))
02998 {
02999 skipkey = 1;
03000 }
03001 else
03002 {
03003 key->info->name[len - 4] = 0;
03004 skipkey = 0;
03005 }
03006 }
03007
03008 if (isrepl)
03009 {
03010
03011
03012
03013 if (!skipkey)
03014 {
03015 sqlbuf = base_strcatalloc(sqlbuf, "INSERT INTO ", &szbuf);
03016 sqlbuf = base_strcatalloc(sqlbuf, ns, &szbuf);
03017 sqlbuf = base_strcatalloc(sqlbuf, ".", &szbuf);
03018 sqlbuf = base_strcatalloc(sqlbuf, DRMS_MASTER_KEYWORD_TABLE, &szbuf);
03019 sqlbuf = base_strcatalloc(sqlbuf, "(seriesname, keywordname, linkname, targetkeyw, type, defaultval, format, unit, description, islink, isconstant, persegment) VALUES (", &szbuf);
03020 sqlbuf = base_strcatalloc(sqlbuf, "'", &szbuf);
03021 sqlbuf = base_strcatalloc(sqlbuf, key->record->seriesinfo->seriesname, &szbuf);
03022 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03023 sqlbuf = base_strcatalloc(sqlbuf, key->info->name, &szbuf);
03024 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03025 sqlbuf = base_strcatalloc(sqlbuf, key->info->linkname, &szbuf);
03026 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03027 sqlbuf = base_strcatalloc(sqlbuf, key->info->target_key, &szbuf);
03028 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03029 sqlbuf = base_strcatalloc(sqlbuf, drms_type2str(key->info->type), &szbuf);
03030 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03031 sqlbuf = base_strcatalloc(sqlbuf, defval, &szbuf);
03032 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03033 sqlbuf = base_strcatalloc(sqlbuf, key->info->format, &szbuf);
03034 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03035 sqlbuf = base_strcatalloc(sqlbuf, key->info->unit, &szbuf);
03036 sqlbuf = base_strcatalloc(sqlbuf, "','", &szbuf);
03037 sqlbuf = base_strcatalloc(sqlbuf, key->info->description, &szbuf);
03038 sqlbuf = base_strcatalloc(sqlbuf, "',", &szbuf);
03039 sqlbuf = base_strcatalloc(sqlbuf, key->info->islink ? "1" : "0", &szbuf);
03040 sqlbuf = base_strcatalloc(sqlbuf, ",", &szbuf);
03041 snprintf(numbuf, sizeof(numbuf), "%d", (int)key->info->recscope);
03042 sqlbuf = base_strcatalloc(sqlbuf, numbuf, &szbuf);
03043 sqlbuf = base_strcatalloc(sqlbuf, ",", &szbuf);
03044 snprintf(numbuf, sizeof(numbuf), "%d", key->info->kwflags);
03045 sqlbuf = base_strcatalloc(sqlbuf, numbuf, &szbuf);
03046 sqlbuf = base_strcatalloc(sqlbuf, ")\n", &szbuf);
03047 }
03048 }
03049 else
03050 {
03051 *sql = NULL;
03052
03053 if (!skipkey)
03054 {
03055 char ibuf[2048];
03056 snprintf(ibuf, sizeof(ibuf), "INSERT INTO %s." DRMS_MASTER_KEYWORD_TABLE
03057 "(seriesname, keywordname, linkname, targetkeyw, type, "
03058 "defaultval, format, unit, description, islink, "
03059 "isconstant, persegment) values (?,?,?,?,?,?,?,?,?,?,?,?)", ns);
03060
03061 if (drms_dmsv(session,
03062 NULL,
03063 ibuf,
03064 -1,
03065 DB_STRING, key->record->seriesinfo->seriesname,
03066 DB_STRING, key->info->name,
03067 DB_STRING, key->info->linkname,
03068 DB_STRING, key->info->target_key,
03069 DB_STRING, drms_type2str(key->info->type),
03070 DB_STRING, defval,
03071 DB_STRING, key->info->format,
03072 DB_STRING, key->info->unit,
03073 DB_STRING, key->info->description,
03074 DB_INT4, key->info->islink,
03075 DB_INT4, key->info->recscope,
03076
03077 DB_INT4, key->info->kwflags))
03078 {
03079 drmsstat = DRMS_ERROR_BADDBQUERY;
03080 }
03081 }
03082 }
03083 }
03084
03085 if (drmsstat == DRMS_SUCCESS && nkeys > 0 && strlen(tblactionbuf) > 0)
03086 {
03087 tblactionbuf = base_strcatalloc(tblactionbuf, "\n", &szalterbuf);
03088
03089 szalterbuf = 2048;
03090 char *alterbuf = calloc(1, szalterbuf);
03091
03092 if (alterbuf)
03093 {
03094 alterbuf = base_strcatalloc(alterbuf, "ALTER TABLE ", &szalterbuf);
03095 alterbuf = base_strcatalloc(alterbuf, series, &szalterbuf);
03096 alterbuf = base_strcatalloc(alterbuf, " ", &szalterbuf);
03097 alterbuf = base_strcatalloc(alterbuf, tblactionbuf, &szalterbuf);
03098
03099 if (isrepl)
03100 {
03101
03102
03103 sqlbuf = base_strcatalloc(sqlbuf, alterbuf, &szbuf);
03104 }
03105 else
03106 {
03107
03108
03109 if (drms_dms(session, NULL, alterbuf))
03110 {
03111 drmsstat = DRMS_ERROR_BADDBQUERY;
03112 }
03113 }
03114
03115 free(alterbuf);
03116 alterbuf = NULL;
03117 }
03118 }
03119
03120 hiter_destroy(&hit);
03121 }
03122 else
03123 {
03124 drmsstat = DRMS_ERROR_OUTOFMEMORY;
03125 }
03126 }
03127 }
03128 else
03129 {
03130 fprintf(stderr, "Failed to parse keyword specification '%s'.\n", spec);
03131 drmsstat = DRMS_ERROR_BADJSD;
03132 }
03133
03134 if (keys)
03135 {
03136
03137
03138 hcon_destroy(&keys);
03139 }
03140 }
03141 else
03142 {
03143 fprintf(stderr, "Unable to obtain template record for series %s.\n", series);
03144 drmsstat = DRMS_ERROR_UNKNOWNSERIES;
03145 }
03146 }
03147 }
03148 else
03149 {
03150 drmsstat = DRMS_ERROR_INVALIDDATA;
03151 }
03152
03153 if (drmsstat == DRMS_SUCCESS)
03154 {
03155 if (isrepl)
03156 {
03157 drmsstat = DRMS_ERROR_CANTMODPUBSERIES;
03158
03159 if (sqlbuf && strlen(sqlbuf) > 0)
03160 {
03161 *sql = sqlbuf;
03162 sqlbuf = NULL;
03163 }
03164 else
03165 {
03166 drmsstat = DRMS_ERROR_BADJSD;
03167 }
03168 }
03169 }
03170
03171 if (tblactionbuf)
03172 {
03173 free(tblactionbuf);
03174 }
03175
03176 if (sqlbuf)
03177 {
03178 free(sqlbuf);
03179 }
03180
03181 if (ns)
03182 {
03183 free(ns);
03184 }
03185
03186 if (tab)
03187 {
03188 free(tab);
03189 }
03190
03191 return drmsstat;
03192 }
03193
03194 int drms_dropkeys_fromseries(DRMS_Env_t *env, const char *series, char **keys, int nkeys)
03195 {
03196 int drmsstat = DRMS_SUCCESS;
03197 DRMS_Record_t *seriestemp = NULL;
03198 size_t szbuf;
03199 char *sqlbuf = NULL;
03200 int first;
03201 char *keyname = NULL;
03202 DRMS_Keyword_t *key = NULL;
03203 char ibuf[2048];
03204 char *lcseries = NULL;
03205 char *lckeyname = NULL;
03206 int ikey;
03207 int iseg;
03208 int nsegs;
03209 char *ns = NULL;
03210 DRMS_Session_t *session = NULL;
03211
03212 if (series && *series && keys)
03213 {
03214 drmsstat = drms_makewritable(env);
03215
03216 if (drmsstat == DRMS_SUCCESS)
03217 {
03218 session = env->session;
03219 lcseries = strdup(series);
03220
03221 if (lcseries)
03222 {
03223 strtolower(lcseries);
03224 get_namespace(lcseries, &ns, NULL);
03225
03226 if (!ns)
03227 {
03228 drmsstat = DRMS_ERROR_OUTOFMEMORY;
03229 }
03230 else
03231 {
03232
03233
03234
03235 seriestemp = drms_create_jsdtemplate_record(env, series, &drmsstat);
03236 }
03237 }
03238 else
03239 {
03240 drmsstat = DRMS_ERROR_OUTOFMEMORY;
03241 }
03242
03243 if (seriestemp && drmsstat == DRMS_SUCCESS)
03244 {
03245 if (drms_series_isreplicated(env, series))
03246 {
03247 fprintf(stderr, "Cannot drop keywords from replicated series %s.\n", series);
03248 drmsstat = DRMS_ERROR_CANTMODPUBSERIES;
03249 }
03250 else
03251 {
03252 szbuf = 1024;
03253 sqlbuf = calloc(1, szbuf);
03254
03255 if (!sqlbuf)
03256 {
03257 drmsstat = DRMS_ERROR_OUTOFMEMORY;
03258 }
03259 }
03260 }
03261
03262 if (drmsstat == DRMS_SUCCESS)
03263 {
03264 for (ikey = 0, first = 1; ikey < nkeys; ikey++)
03265 {
03266 keyname = keys[ikey];
03267
03268 if (lckeyname)
03269 {
03270 free(lckeyname);
03271 }
03272
03273 lckeyname = strdup(keyname);
03274 strtolower(lckeyname);
03275
03276
03277 if ((key = drms_keyword_lookup(seriestemp, keyname, 0)) == NULL)
03278 {
03279 fprintf(stderr, "Cannot drop keyword %s because it does not exist in series %s, skipping.\n", keyname, series);
03280 continue;
03281 }
03282
03283
03284
03285 if (!key->info->islink && !drms_keyword_isconstant(key))
03286 {
03287 if (drms_keyword_getperseg(key))
03288 {
03289 char keybuf[DRMS_MAXKEYNAMELEN + 4];
03290
03291
03292 nsegs = drms_record_numsegments(seriestemp);
03293 for (iseg = 0; iseg < nsegs; iseg++)
03294 {
03295 snprintf(keybuf, sizeof(keybuf), "%s_%03d", keyname, iseg);
03296
03297 if (first)
03298 {
03299 first = 0;
03300 }
03301 else
03302 {
03303 sqlbuf = base_strcatalloc(sqlbuf, ", ", &szbuf);
03304 }
03305
03306
03307 sqlbuf = base_strcatalloc(sqlbuf, "DROP COLUMN ", &szbuf);
03308 sqlbuf = base_strcatalloc(sqlbuf, keybuf, &szbuf);
03309 }
03310 }
03311 else
03312 {
03313 if (first)
03314 {
03315 first = 0;
03316 }
03317 else
03318 {
03319 sqlbuf = base_strcatalloc(sqlbuf, ", ", &szbuf);
03320 }
03321
03322
03323 sqlbuf = base_strcatalloc(sqlbuf, "DROP COLUMN ", &szbuf);
03324 sqlbuf = base_strcatalloc(sqlbuf, keyname, &szbuf);
03325 }
03326 }
03327
03328 snprintf(ibuf, sizeof(ibuf), "DELETE FROM %s." DRMS_MASTER_KEYWORD_TABLE
03329 " WHERE lower(seriesname) = '%s' AND lower(keywordname) = '%s'", ns, lcseries, lckeyname);
03330
03331 if (drms_dms(session, NULL, ibuf))
03332 {
03333 drmsstat = DRMS_ERROR_BADDBQUERY;
03334 break;
03335 }
03336 }
03337
03338 if (lckeyname)
03339 {
03340 free(lckeyname);
03341 lckeyname = NULL;
03342 }
03343
03344
03345 if (sqlbuf && *sqlbuf)
03346 {
03347 size_t szalterbuf = 2048;
03348 char *alterbuf = calloc(1, szalterbuf);
03349
03350 if (alterbuf)
03351 {
03352 alterbuf = base_strcatalloc(alterbuf, "ALTER TABLE ", &szalterbuf);
03353 alterbuf = base_strcatalloc(alterbuf, lcseries, &szalterbuf);
03354 alterbuf = base_strcatalloc(alterbuf, " ", &szalterbuf);
03355 alterbuf = base_strcatalloc(alterbuf, sqlbuf, &szalterbuf);
03356
03357 if (drms_dms(session, NULL, alterbuf))
03358 {
03359 drmsstat = DRMS_ERROR_BADDBQUERY;
03360 }
03361
03362 free(alterbuf);
03363 alterbuf = NULL;
03364 }
03365 }
03366 }
03367
03368 if (seriestemp)
03369 {
03370 drms_destroy_jsdtemplate_record(&seriestemp);
03371 }
03372
03373 if (lcseries)
03374 {
03375 free(lcseries);
03376 lcseries = NULL;
03377 }
03378 }
03379 }
03380 else
03381 {
03382 drmsstat = DRMS_ERROR_INVALIDDATA;
03383 }
03384
03385 return drmsstat;
03386 }
03387
03388
03389
03390
03391
03392
03393
03394
03395 int drms_delete_series(DRMS_Env_t *env, const char *series, int cascade, int keepsums)
03396 {
03397 char query[1024], *series_lower = NULL, *namespace = NULL;
03398 DB_Binary_Result_t *qres;
03399 DRMS_Session_t *session;
03400 int drmsstatus = DRMS_SUCCESS;
03401 DRMS_Array_t *array = NULL;
03402 int repl = 0;
03403 int retstat = -1;
03404 char shadow[DRMS_MAXSERIESNAMELEN];
03405
03406 if (!env->session->db_direct && !env->selfstart)
03407 {
03408 fprintf(stderr, "Can't delete series if using drms_server. Please use a direct-connect modules, or a self-starting socket-connect module.\n");
03409 goto bailout;
03410 }
03411
03412 drmsstatus = drms_makewritable(env);
03413
03414 if (drmsstatus != DRMS_SUCCESS)
03415 {
03416 goto bailout;
03417 }
03418
03419 series_lower = strdup(series);
03420
03421 strtolower(series_lower);
03422
03423
03424 if (!drms_series_exists(env, series_lower, &drmsstatus))
03425 {
03426 fprintf(stderr, "The series '%s' does not exist. Please enter a valid series name.\n", series);
03427 goto bailout;
03428 }
03429
03430 if (!drms_series_candeleterecord(env, series_lower))
03431 {
03432 fprintf(stderr, "Permission failure - cannot delete series '%s'.\n", series);
03433 goto bailout;
03434 }
03435
03436
03437
03438
03439 if ((repl = drms_series_isreplicated(env, series)) == 0)
03440 {
03441 session = env->session;
03442 sprintf(query,"select seriesname from %s() where lower(seriesname) = '%s'",
03443 DRMS_MASTER_SERIES_TABLE, series_lower);
03444 #ifdef DEBUG
03445 printf("drms_delete_series: query = %s\n",query);
03446 #endif
03447 if ((qres = drms_query_bin(session, query)) == NULL)
03448 {
03449 printf("Query failed. Statement was: %s\n", query);
03450 goto bailout;
03451 }
03452 #ifdef DEBUG
03453 db_print_binary_result(qres);
03454 #endif
03455 if (qres->num_rows==1)
03456 {
03457 DB_Binary_Result_t *suqres = NULL;
03458
03459 get_namespace(series, &namespace, NULL);
03460
03461 if (!keepsums)
03462 {
03463
03464
03465
03466
03467 snprintf(query, sizeof(query), "SELECT segmentname FROM %s.%s where lower(seriesname) = '%s'", namespace, DRMS_MASTER_SEGMENT_TABLE, series_lower);
03468
03469 if ((suqres = drms_query_bin(session, query)) == NULL)
03470 {
03471 fprintf(stderr, "Query failed. Statement was: %s\n", query);
03472 free(namespace);
03473 goto bailout;
03474 }
03475
03476 if (suqres->num_rows == 0)
03477 {
03478 keepsums = 1;
03479 }
03480
03481 db_free_binary_result(suqres);
03482 suqres = NULL;
03483 }
03484
03485 if (cascade && !keepsums)
03486 {
03487 int irow;
03488 int nsunums;
03489 long long val;
03490 int axis[2];
03491 long long *llarr = NULL;
03492
03493
03494
03495 snprintf(query, sizeof(query), "SELECT DISTINCT sunum FROM %s ORDER BY sunum", series);
03496
03497
03498
03499
03500 if ((suqres = drms_query_bin(session, query)) == NULL)
03501 {
03502 fprintf(stderr, "Query failed. Statement was: %s\n", query);
03503 goto bailout;
03504 }
03505
03506 nsunums = 0;
03507
03508 if (suqres->num_rows > 0)
03509 {
03510 llarr = (long long *)malloc(sizeof(long long) * suqres->num_rows);
03511
03512 for (irow = 0; irow < suqres->num_rows; irow++)
03513 {
03514 val = db_binary_field_getlonglong(suqres, irow, 0);
03515 if (val >= 0)
03516 {
03517 llarr[nsunums++] = val;
03518 }
03519 }
03520
03521
03522 axis[0] = 1;
03523 axis[1] = nsunums;
03524 array = drms_array_create(DRMS_TYPE_LONGLONG, 2, axis, llarr, &drmsstatus);
03525 }
03526
03527 if (nsunums == 0)
03528 {
03529 keepsums = 1;
03530 }
03531
03532 db_free_binary_result(suqres);
03533 suqres = NULL;
03534 }
03535
03536
03537
03538 if (keepsums || (!drmsstatus && array && array->naxis == 2 && array->axis[0] == 1))
03539 {
03540 if (cascade && !keepsums) {
03541 if (array->axis[1] > 0) {
03542
03543
03544
03545 if (drms_dropseries(env, series, array))
03546 {
03547 fprintf(stderr, "Unable to drop SUNUMS; failure calling SUMS.\n");
03548 goto bailout;
03549 }
03550 }
03551 }
03552
03553 if (cascade) {
03554 sprintf(query,"drop table %s",series_lower);
03555 if (env->verbose)
03556 {
03557 fprintf(stdout, "drms_delete_series(): %s\n", query);
03558 }
03559
03560 if (drms_dms(session,NULL,query))
03561 goto bailout;
03562 if (drms_sequence_drop(session, series_lower))
03563 goto bailout;
03564 }
03565 sprintf(query, "set search_path to %s", namespace);
03566 if (env->verbose)
03567 {
03568 fprintf(stdout, "drms_delete_series(): %s\n", query);
03569 }
03570
03571 if (drms_dms(session,NULL,query)) {
03572 fprintf(stderr, "Failed: %s\n", query);
03573 goto bailout;
03574 }
03575 sprintf(query,"delete from %s where lower(seriesname) = '%s'",
03576 DRMS_MASTER_LINK_TABLE,series_lower);
03577 if (env->verbose)
03578 {
03579 fprintf(stdout, "drms_delete_series(): %s\n", query);
03580 }
03581
03582 if (drms_dms(session,NULL,query))
03583 goto bailout;
03584 sprintf(query,"delete from %s where lower(seriesname) = '%s'",
03585 DRMS_MASTER_KEYWORD_TABLE, series_lower);
03586 if (env->verbose)
03587 {
03588 fprintf(stdout, "drms_delete_series(): %s\n", query);
03589 }
03590
03591 if (drms_dms(session,NULL,query))
03592 goto bailout;
03593 sprintf(query,"delete from %s where lower(seriesname) = '%s'",
03594 DRMS_MASTER_SEGMENT_TABLE, series_lower);
03595 if (env->verbose)
03596 {
03597 fprintf(stdout, "drms_delete_series(): %s\n", query);
03598 }
03599
03600 if (drms_dms(session,NULL,query))
03601 goto bailout;
03602 sprintf(query,"delete from %s where lower(seriesname) = '%s'",
03603 DRMS_MASTER_SERIES_TABLE,series_lower);
03604 if (env->verbose)
03605 {
03606 fprintf(stdout, "drms_delete_series(): %s\n", query);
03607 }
03608
03609 if (drms_dms(session,NULL,query))
03610 goto bailout;
03611
03612
03613
03614
03615 if (ShadowExists(env, series_lower, &drmsstatus))
03616 {
03617 snprintf(shadow, sizeof(shadow), "%s%s", series_lower, kShadowSuffix);
03618 snprintf(query, sizeof(query), "DROP TABLE %s", shadow);
03619
03620 if (env->verbose)
03621 {
03622 fprintf(stdout, "drms_delete_series(): %s\n", query);
03623 }
03624
03625 if (drms_dms(session,NULL,query))
03626 {
03627 goto bailout;
03628 }
03629 }
03630
03631
03632 if (drmsstatus != DRMS_SUCCESS)
03633 {
03634 fprintf(stderr, "Unable to check for the existing of the shadow table for series %s.\n", series);
03635 goto bailout;
03636 }
03637
03638
03639
03640
03641
03642
03643
03644
03645 hcon_remove(&env->series_cache,series_lower);
03646 }
03647 else
03648 {
03649 fprintf(stderr, "Couldn't create vector of sunum keywords.\n");
03650 goto bailout;
03651 }
03652
03653 free(namespace);
03654 namespace = NULL;
03655 }
03656 else if (qres->num_rows>1)
03657 {
03658 fprintf(stderr,"TOO MANY ROWS RETURNED IN DRMS_DELETE_SERIES\n");
03659
03660
03661 goto bailout;
03662 }
03663 else {
03664
03665 fprintf(stderr, "Series '%s' does not exist\n", series);
03666 retstat = DRMS_ERROR_UNKNOWNSERIES;
03667 goto bailout;
03668 }
03669 db_free_binary_result(qres);
03670
03671 if (array)
03672 {
03673 drms_free_array(array);
03674 }
03675 }
03676 else if (repl == -1)
03677 {
03678
03679
03680 goto bailout;
03681 }
03682 else
03683 {
03684 fprintf(stderr, "Unable to delete series registered for replication.\n");
03685 }
03686
03687 free(series_lower);
03688
03689 return 0;
03690 bailout:
03691 fprintf(stderr,"drms_delete_series(): failed to delete series %s\n", series);
03692 if (series_lower)
03693 {
03694 free(series_lower);
03695 }
03696
03697 if (namespace)
03698 {
03699 free(namespace);
03700 }
03701
03702 if (array)
03703 {
03704 drms_free_array(array);
03705 }
03706
03707 if (retstat != -1)
03708 {
03709 return retstat;
03710 }
03711 else
03712 {
03713 return 1;
03714 }
03715 }
03716
03717 static int drms_series_keynamesort(const void *first, const void *second)
03718 {
03719 if (first && second)
03720 {
03721 const char *rFirst = *((const char **)first);
03722 const char *rSecond = *((const char **)second);
03723
03724 if (!rFirst && !rSecond)
03725 {
03726 return 0;
03727 }
03728 else if (!rFirst)
03729 {
03730 return 1;
03731 }
03732 else if (!rSecond)
03733 {
03734 return -1;
03735 }
03736 else
03737 {
03738 return strcmp(rFirst, rSecond);
03739 }
03740 }
03741
03742 return 0;
03743 }
03744
03745 static int drms_series_intpkeysmatch(DRMS_Record_t *recTemp1,
03746 char **pkArray1,
03747 int nPKeys1,
03748 DRMS_Record_t *recTemp2,
03749 char **pkArray2,
03750 int nPKeys2)
03751 {
03752 int ret = 0;
03753
03754 if (nPKeys1 == nPKeys2)
03755 {
03756
03757 qsort(pkArray1, nPKeys1, sizeof(char *), drms_series_keynamesort);
03758 qsort(pkArray2, nPKeys2, sizeof(char *), drms_series_keynamesort);
03759
03760 DRMS_Keyword_t *key1 = NULL;
03761 DRMS_Keyword_t *key2 = NULL;
03762
03763 int i = 0;
03764 for (; i < nPKeys1; i++)
03765 {
03766 if (strcmp(pkArray1[i], pkArray2[i]) == 0)
03767 {
03768 key1 = hcon_lookup_lower(&(recTemp1->keywords), pkArray1[i]);
03769 key2 = hcon_lookup_lower(&(recTemp2->keywords), pkArray1[i]);
03770
03771 XASSERT(key1 != NULL && key2 != NULL);
03772 if (key1 != NULL && key2 != NULL)
03773 {
03774 if (key1->info->type != key2->info->type ||
03775 key1->info->recscope != key2->info->recscope ||
03776 drms_keyword_getperseg(key1) != drms_keyword_getperseg(key2))
03777 {
03778 break;
03779 }
03780 }
03781 else
03782 {
03783 break;
03784 }
03785 }
03786 else
03787 {
03788 break;
03789 }
03790 }
03791
03792 if (i == nPKeys1)
03793 {
03794 ret = 1;
03795 }
03796 }
03797
03798 return ret;
03799 }
03800
03801
03802
03803 static int drms_series_pkeysmatch(DRMS_Env_t *drmsEnv,
03804 const char *series1,
03805 const char *series2,
03806 int *status)
03807 {
03808 int ret = 0;
03809
03810 int nPKeys1 = 0;
03811 int nPKeys2 = 0;
03812
03813 DRMS_Record_t *recTemp1 = drms_template_record(drmsEnv, series1, status);
03814 DRMS_Record_t *recTemp2 = NULL;
03815
03816 if (*status == DRMS_SUCCESS)
03817 {
03818 recTemp2 = drms_template_record(drmsEnv, series2, status);
03819 }
03820
03821 if (*status == DRMS_SUCCESS)
03822 {
03823 char **pkArray1 = drms_series_createrealpkeyarray(drmsEnv, series1, &nPKeys1, status);
03824 char **pkArray2 = NULL;
03825
03826 if (*status == DRMS_SUCCESS)
03827 {
03828 pkArray2 = drms_series_createrealpkeyarray(drmsEnv, series2, &nPKeys2, status);
03829 }
03830
03831 if (*status == DRMS_SUCCESS)
03832 {
03833 ret = drms_series_intpkeysmatch(recTemp1, pkArray1, nPKeys1, recTemp2, pkArray2, nPKeys2);
03834
03835 if (!ret)
03836 {
03837 fprintf(stdout,
03838 "Series %s prime key does not match series %s prime key.\n",
03839 series1,
03840 series2);
03841 }
03842 }
03843
03844 if (pkArray1)
03845 {
03846 drms_series_destroypkeyarray(&pkArray1, nPKeys1);
03847 }
03848
03849 if (pkArray2)
03850 {
03851 drms_series_destroypkeyarray(&pkArray2, nPKeys2);
03852 }
03853 }
03854
03855 return ret;
03856 }
03857
03858 static int drms_series_intcreatematchsegs(DRMS_Env_t *drmsEnv,
03859 const char *series,
03860 DRMS_Record_t *recTempl,
03861 HContainer_t *matchSegs,
03862 int *status)
03863 {
03864 int nMatch = 0;
03865
03866 DRMS_Record_t *seriesRec = drms_template_record(drmsEnv, series, status);
03867
03868 if (*status == DRMS_SUCCESS)
03869 {
03870 HContainer_t *s1SegCont = &(seriesRec->segments);
03871 HContainer_t *s2SegCont = &(recTempl->segments);
03872
03873 if (s1SegCont && s2SegCont)
03874 {
03875 HIterator_t *s1Hit = hiter_create(s1SegCont);
03876 HIterator_t *s2Hit = hiter_create(s2SegCont);
03877
03878 if (s1Hit && s2Hit)
03879 {
03880 DRMS_Segment_t *s1Seg = NULL;
03881 DRMS_Segment_t *s2Seg = NULL;
03882
03883 while ((s1Seg = (DRMS_Segment_t *)hiter_getnext(s1Hit)) != NULL)
03884 {
03885 if ((s2Seg =
03886 (DRMS_Segment_t *)hcon_lookup_lower(s2SegCont, s1Seg->info->name)) != NULL)
03887 {
03888
03889 if (drms_segment_segsmatch(s1Seg, s2Seg))
03890 {
03891 nMatch++;
03892
03893 if (nMatch == 1)
03894 {
03895 hcon_init(matchSegs,
03896 DRMS_MAXSEGNAMELEN,
03897 DRMS_MAXSEGNAMELEN,
03898 NULL,
03899 NULL);
03900 }
03901
03902 char *newSeg = (char *)hcon_allocslot(matchSegs, s1Seg->info->name);
03903 if (newSeg != NULL)
03904 {
03905 strncpy(newSeg, s1Seg->info->name, DRMS_MAXSEGNAMELEN);
03906 newSeg[DRMS_MAXSEGNAMELEN - 1] = '\0';
03907 }
03908 else
03909 {
03910 nMatch = -1;
03911 break;
03912 }
03913 }
03914 }
03915 }
03916 }
03917
03918 if (s1Hit)
03919 {
03920 hiter_destroy(&s1Hit);
03921 }
03922
03923 if (s2Hit)
03924 {
03925 hiter_destroy(&s2Hit);
03926 }
03927 }
03928 }
03929
03930 return nMatch;
03931 }
03932
03933
03934 static int drms_series_creatematchsegs(DRMS_Env_t *drmsEnv,
03935 const char *series1,
03936 const char *series2,
03937 HContainer_t *matchSegs,
03938 int *status)
03939 {
03940 int nMatch = 0;
03941
03942 if (matchSegs)
03943 {
03944 DRMS_Record_t *s2RecTempl = drms_template_record(drmsEnv, series2, status);
03945
03946 if (*status == DRMS_SUCCESS)
03947 {
03948 nMatch = drms_series_intcreatematchsegs(drmsEnv,
03949 series1,
03950 s2RecTempl,
03951 matchSegs,
03952 status);
03953
03954 if (nMatch == 0)
03955 {
03956 fprintf(stdout, "Series %s and %s have no matching segments.\n", series1, series2);
03957 }
03958 }
03959 }
03960 else
03961 {
03962 fprintf(stderr, "Must provide HContainer_t to CreateMatchingSegs\n");
03963 }
03964
03965 return nMatch;
03966 }
03967
03968
03969
03970
03971
03972 static char **drms_series_intcreatepkeyarray(DRMS_Record_t *recTempl,
03973 int *nPKeys,
03974 DRMS_PrimeKeyType_t pktype,
03975 int *status)
03976 {
03977 char **ret = NULL;
03978
03979 if (recTempl != NULL)
03980 {
03981 int nKeys = recTempl->seriesinfo->pidx_num;
03982 int iKey = 0;
03983
03984 ret = (char **)malloc(sizeof(char *) * nKeys);
03985
03986 if (ret != NULL)
03987 {
03988 while (iKey < nKeys)
03989 {
03990 DRMS_Keyword_t *pkey = recTempl->seriesinfo->pidx_keywords[iKey];
03991
03992 if (drms_keyword_isindex(pkey) && pktype == kPkeysDRMSExternal)
03993 {
03994
03995 pkey = drms_keyword_slotfromindex(pkey);
03996 ret[iKey] = strdup(pkey->info->name);
03997 }
03998 else
03999 {
04000 ret[iKey] = strdup(pkey->info->name);
04001 }
04002 iKey++;
04003 }
04004
04005 *nPKeys = nKeys;
04006 }
04007 else
04008 {
04009 *status = DRMS_ERROR_OUTOFMEMORY;
04010 }
04011 }
04012 else
04013 {
04014 *status = DRMS_ERROR_INVALIDDATA;
04015 }
04016
04017 return ret;
04018 }
04019
04020
04021 char **drms_series_createrealpkeyarray(DRMS_Env_t *env,
04022 const char *seriesName,
04023 int *nPKeys,
04024 int *status)
04025 {
04026 char **ret = NULL;
04027 int stat = 0;
04028
04029 DRMS_Record_t *template = drms_template_record(env, seriesName, &stat);
04030
04031 if (template != NULL && stat == DRMS_SUCCESS)
04032 {
04033 ret = drms_series_intcreatepkeyarray(template, nPKeys, kPkeysDRMSInternal, &stat);
04034 }
04035
04036 if (status)
04037 {
04038 *status = stat;
04039 }
04040
04041 return ret;
04042 }
04043
04044
04045 char **drms_series_createpkeyarray(DRMS_Env_t *env,
04046 const char *seriesName,
04047 int *nPKeys,
04048 int *status)
04049 {
04050 char **ret = NULL;
04051 int stat = 0;
04052
04053 DRMS_Record_t *template = drms_template_record(env, seriesName, &stat);
04054
04055 if (template != NULL && stat == DRMS_SUCCESS)
04056 {
04057 ret = drms_series_intcreatepkeyarray(template,
04058 nPKeys,
04059 kPkeysDRMSExternal,
04060 &stat);
04061 }
04062
04063 if (status)
04064 {
04065 *status = stat;
04066 }
04067
04068 return ret;
04069 }
04070
04071 void drms_series_destroypkeyarray(char ***pkeys, int nElements)
04072 {
04073 int iElement = 0;
04074 char **array = *pkeys;
04075
04076 while (iElement < nElements)
04077 {
04078 if (array[iElement] != NULL)
04079 {
04080 free(array[iElement]);
04081 }
04082
04083 iElement++;
04084 }
04085
04086 free(array);
04087 *pkeys = NULL;
04088 }
04089
04090
04091 int drms_series_checkseriescompat(DRMS_Env_t *drmsEnv,
04092 const char *series1,
04093 const char *series2,
04094 HContainer_t *matchSegs,
04095 int *status)
04096 {
04097 int ret = 0;
04098 int nMatch = 0;
04099
04100
04101 if (drms_series_pkeysmatch(drmsEnv, series1, series2, status) && *status == DRMS_SUCCESS)
04102 {
04103
04104 nMatch = drms_series_creatematchsegs(drmsEnv, series1, series2, matchSegs, status);
04105
04106 if (nMatch == 0)
04107 {
04108 fprintf(stdout, "Series %s and %s have no matching segments.\n", series1, series2);
04109 }
04110 }
04111
04112 if (*status == DRMS_SUCCESS)
04113 {
04114 ret = nMatch > 0;
04115 }
04116
04117 return ret;
04118 }
04119
04120
04121
04122
04123
04124
04125
04126
04127
04128
04129 int drms_series_checkrecordcompat(DRMS_Env_t *drmsEnv,
04130 const char *series,
04131 DRMS_Record_t *recTempl,
04132 HContainer_t *matchSegs,
04133 int *status)
04134 {
04135 int ret = 0;
04136 int nMatch = 0;
04137 DRMS_Record_t *seriesTempl = NULL;
04138 int nSeriesPKeys = 0;
04139 int nPKeys = 0;
04140 char **seriesPKArray = NULL;
04141 char **pkArray = NULL;
04142
04143 seriesPKArray = drms_series_createrealpkeyarray(drmsEnv,
04144 series,
04145 &nSeriesPKeys,
04146 status);
04147 if (*status == DRMS_SUCCESS)
04148 {
04149 pkArray = drms_series_intcreatepkeyarray(recTempl,
04150 &nPKeys,
04151 kPkeysDRMSInternal,
04152 status);
04153
04154 if (*status == DRMS_SUCCESS)
04155 {
04156 seriesTempl = drms_template_record(drmsEnv, series, status);
04157
04158 if (*status == DRMS_SUCCESS)
04159 {
04160 if (drms_series_intpkeysmatch(seriesTempl,
04161 seriesPKArray,
04162 nSeriesPKeys,
04163 recTempl,
04164 pkArray,
04165 nPKeys))
04166 {
04167
04168 nMatch = drms_series_intcreatematchsegs(drmsEnv,
04169 series,
04170 recTempl,
04171 matchSegs,
04172 status);
04173
04174 if (nMatch == 0)
04175 {
04176 fprintf(stdout,
04177 "No series %s segment matches a series %s segment.\n",
04178 recTempl->seriesinfo->seriesname,
04179 series);
04180 }
04181 }
04182 else
04183 {
04184 fprintf(stdout,
04185 "Series %s prime key does not match series %s prime key.\n",
04186 recTempl->seriesinfo->seriesname,
04187 series);
04188 }
04189 }
04190 }
04191 }
04192
04193 if (*status == DRMS_SUCCESS)
04194 {
04195 ret = nMatch > 0;
04196 }
04197
04198 if (seriesPKArray)
04199 {
04200 drms_series_destroypkeyarray(&seriesPKArray, nSeriesPKeys);
04201 }
04202
04203 if (pkArray)
04204 {
04205 drms_series_destroypkeyarray(&pkArray, nPKeys);
04206 }
04207
04208 return ret;
04209 }
04210
04211 int drms_series_checkkeycompat(DRMS_Env_t *drmsEnv,
04212 const char *series,
04213 DRMS_Keyword_t *keys,
04214 int nKeys,
04215 int *status)
04216 {
04217 int ret = 0;
04218
04219 DRMS_Record_t *recTempl = drms_template_record(drmsEnv, series, status);
04220 if (*status == DRMS_SUCCESS)
04221 {
04222 int iKey = 0;
04223 ret = 1;
04224 for (; iKey < nKeys; iKey++)
04225 {
04226 DRMS_Keyword_t *oneKey = &(keys[iKey]);
04227 DRMS_Keyword_t *sKey = drms_keyword_lookup(recTempl,
04228 oneKey->info->name,
04229 0);
04230
04231 if (sKey)
04232 {
04233 if (!drms_keyword_keysmatch(oneKey, sKey))
04234 {
04235 ret = 0;
04236 break;
04237 }
04238 }
04239 else
04240 {
04241 ret = 0;
04242 break;
04243 }
04244 }
04245 }
04246
04247 return ret;
04248 }
04249
04250 int drms_series_checksegcompat(DRMS_Env_t *drmsEnv,
04251 const char *series,
04252 DRMS_Segment_t *segs,
04253 int nSegs,
04254 int *status)
04255 {
04256 int ret = 0;
04257
04258 DRMS_Record_t *recTempl = drms_template_record(drmsEnv, series, status);
04259 if (*status == DRMS_SUCCESS)
04260 {
04261 int iSeg = 0;
04262 ret = 1;
04263 for (; iSeg < nSegs; iSeg++)
04264 {
04265 DRMS_Segment_t *oneSeg = &(segs[iSeg]);
04266 DRMS_Segment_t *sSeg = drms_segment_lookup(recTempl, oneSeg->info->name);
04267
04268 if (sSeg)
04269 {
04270 if (!drms_segment_segsmatch(oneSeg, sSeg))
04271 {
04272 ret = 0;
04273 break;
04274 }
04275 }
04276 else
04277 {
04278 ret = 0;
04279 break;
04280 }
04281 }
04282 }
04283
04284 return ret;
04285 }
04286
04287
04288 int drms_series_isvers(DRMS_SeriesInfo_t *si, DRMS_SeriesVersion_t *v)
04289 {
04290 long long smajor;
04291 long long sminor;
04292 long long vmajor;
04293 long long vminor;
04294
04295 int ok = 1;
04296
04297 if (*(si->version) == '\0')
04298 {
04299 ok = 0;
04300 }
04301 else if (sscanf(si->version, "%lld.%lld", &smajor, &sminor) == 2)
04302 {
04303 if (*(v->first) != '\0')
04304 {
04305
04306 if (sscanf(v->first, "%lld.%lld", &vmajor, &vminor) == 2)
04307 {
04308 if (smajor < vmajor || (smajor == vmajor && sminor < vminor))
04309 {
04310 ok = 0;
04311 }
04312 }
04313 else
04314 {
04315 fprintf(stderr, "Invalid series version '%s'.\n", v->first);
04316 ok = 0;
04317 }
04318 }
04319
04320 if (ok && *(v->last) != '\0')
04321 {
04322
04323 if (sscanf(v->last, "%lld.%lld", &vmajor, &vminor) == 2)
04324 {
04325 if (smajor > vmajor || (smajor == vmajor && sminor > vminor))
04326 {
04327 ok = 0;
04328 }
04329 }
04330 else
04331 {
04332 fprintf(stderr, "Invalid series version '%s'.\n", v->last);
04333 ok = 0;
04334 }
04335 }
04336 }
04337 else
04338 {
04339 fprintf(stderr, "Invalid series version '%s'.\n", si->version);
04340 ok = 0;
04341 }
04342
04343 return ok;
04344 }
04345
04346 static int CanCallDrmsReplicated(DRMS_Env_t *env)
04347 {
04348 int tabexists = 0;
04349 int status = DRMS_SUCCESS;
04350
04351 tabexists = drms_query_tabexists(env->session, "_jsoc", "sl_table", &status);
04352
04353 if (status == DRMS_ERROR_BADDBQUERY)
04354 {
04355 fprintf(stderr, "Unable to check database for the existence of _jsoc.sl_table.\n");
04356 return 0;
04357 }
04358
04359 return (!tabexists || drms_series_hastableprivs(env, "_jsoc", "sl_table", "SELECT"));
04360 }
04361
04362
04363
04364
04365
04366
04367
04368
04369 int drms_series_isreplicated(DRMS_Env_t *env, const char *series)
04370 {
04371 int ans = 0;
04372 char query[1024];
04373 DB_Binary_Result_t *qres = NULL;
04374
04375
04376
04377
04378
04379
04380
04381
04382 sprintf(query,
04383 "SELECT proname AS routine_name FROM pg_proc p JOIN pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname = 'public' AND p.proname = '%s'",
04384 DRMS_REPLICATED_SERIES_TABLE);
04385
04386
04387 if ((qres = drms_query_bin(env->session, query)) == NULL)
04388 {
04389 printf("Query failed. Statement was: %s\n", query);
04390 ans = -1;
04391 }
04392 else
04393 {
04394 if (qres->num_rows == 1)
04395 {
04396
04397 char *nspace = NULL;
04398 char *relname = NULL;
04399
04400
04401 if (!CanCallDrmsReplicated(env))
04402 {
04403 fprintf(stderr, "You do not have permission to call database function '%s'. Please have an administrator grant you permission before proceeding.\n", DRMS_REPLICATED_SERIES_TABLE);
04404 ans = -2;
04405 }
04406 else
04407 {
04408 db_free_binary_result(qres);
04409
04410 get_namespace(series, &nspace, &relname);
04411
04412 sprintf(query,
04413 "select tab_id from %s() where tab_nspname ~~* '%s' and tab_relname ~~* '%s'",
04414 DRMS_REPLICATED_SERIES_TABLE,
04415 nspace,
04416 relname);
04417
04418 if (nspace)
04419 {
04420 free(nspace);
04421 }
04422
04423 if (relname)
04424 {
04425 free(relname);
04426 }
04427
04428 if ((qres = drms_query_bin(env->session, query)) == NULL)
04429 {
04430 printf("Query failed. Statement was: %s\n", query);
04431 ans = -1;
04432 }
04433 else
04434 {
04435 if (qres->num_rows == 1)
04436 {
04437 ans = 1;
04438 }
04439
04440 db_free_binary_result(qres);
04441 }
04442 }
04443 }
04444 else
04445 {
04446
04447 ans = -1;
04448 }
04449 }
04450
04451 return ans;
04452 }
04453
04454 int GetTableOID(DRMS_Env_t *env, const char *ns, const char *table, char **oid)
04455 {
04456 char query[DRMS_MAXQUERYLEN];
04457 DB_Binary_Result_t *qres = NULL;
04458 DRMS_Session_t *session = env->session;
04459 int err = 0;
04460
04461 snprintf(query, sizeof(query), "SELECT c.oid, n.nspname, c.relname FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname ~ '^(%s)$' AND n.nspname ~ '^(%s)$' ORDER BY 2, 3", table, ns);
04462
04463 if (!oid)
04464 {
04465 fprintf(stderr, "Missing required argument 'oid'.\n");
04466 err = 1;
04467 }
04468 else if ((qres = drms_query_bin(session, query)) == NULL)
04469 {
04470 fprintf(stderr, "Invalid database query: '%s'\n", query);
04471 err = DRMS_ERROR_QUERYFAILED;
04472 }
04473 else
04474 {
04475 if (qres->num_rows != 1)
04476 {
04477 fprintf(stderr, "Unexpected database response to query '%s'\n", query);
04478 err = 1;
04479 }
04480 else
04481 {
04482
04483 char ioid[8];
04484 *oid = malloc(sizeof(char) * 64);
04485
04486
04487
04488
04489 memcpy(ioid, qres->column->data, 4);
04490
04491 #if __BYTE_ORDER == __LITTLE_ENDIAN
04492 db_byteswap(DB_INT4, 1, ioid);
04493 #endif
04494
04495 snprintf(*oid, 64, "%d", *((int *)ioid));
04496 db_free_binary_result(qres);
04497 }
04498 }
04499
04500 return err;
04501 }
04502
04503 int GetColumnNames(DRMS_Env_t *env, const char *oid, char **colnames)
04504 {
04505 int err = 0;
04506 char query[DRMS_MAXQUERYLEN];
04507 DB_Binary_Result_t *qres = NULL;
04508 DRMS_Session_t *session = env->session;
04509
04510 snprintf(query, sizeof(query), "SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod), (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128) FROM pg_catalog.pg_attrdef d WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) as defval, a.attnotnull FROM pg_catalog.pg_attribute a WHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped ORDER BY a.attnum", oid);
04511
04512 if ((qres = drms_query_bin(session, query)) == NULL)
04513 {
04514 fprintf(stderr, "Invalid database query: '%s'\n", query);
04515 err = 1;
04516 }
04517 else
04518 {
04519 if (qres->num_cols != 4)
04520 {
04521 fprintf(stderr, "Unexpected database response to query '%s'\n", query);
04522 err = 1;
04523 }
04524 else
04525 {
04526 char *list = NULL;
04527 int irow;
04528 size_t strsize = DRMS_MAXQUERYLEN;
04529 char colname[512];
04530
04531 if (colnames)
04532 {
04533 list = malloc(sizeof(char) * strsize);
04534 memset(list, 0, sizeof(char) * strsize);
04535
04536 for (irow = 0; irow < qres->num_rows; irow++)
04537 {
04538 if (irow)
04539 {
04540 list = base_strcatalloc(list, ",", &strsize);
04541 }
04542
04543
04544 db_binary_field_getstr(qres, irow, 0, sizeof(colname), colname);
04545 list = base_strcatalloc(list, colname, &strsize);
04546 }
04547
04548 *colnames = list;
04549 list = NULL;
04550 }
04551
04552 db_free_binary_result(qres);
04553 }
04554 }
04555
04556 return err;
04557 }
04558
04559
04560
04561
04562
04563
04564
04565
04566
04567 int drms_series_updatesummaries(DRMS_Env_t *env,
04568 const char *series,
04569 int nrows,
04570 int ncols,
04571 char **pkeynames,
04572 long long *recnums,
04573 int added)
04574 {
04575 int status = DRMS_SUCCESS;
04576 int shadowexists = 0;
04577 size_t lsz = 0;
04578 char *recnumlist = NULL;
04579
04580 #if (defined TOC && TOC)
04581 int tocexists = 0;
04582 char stmnt[8192];
04583 #endif
04584
04585
04586
04587
04588
04589
04590
04591
04592 #if (defined TOC && TOC)
04593 tocexists = TocExists(env, &status);
04594
04595 if (status == DRMS_ERROR_BADDBQUERY)
04596 {
04597 fprintf(stderr, "Unable to check database for the existence of %s.%s.\n", kTableOfCountsNS, kTableOfCountsTab);
04598 }
04599 else
04600 {
04601 snprintf(stmnt, sizeof(stmnt), "SET search_path TO %s", kTableOfCountsNS);
04602
04603 if (drms_dms(env->session, NULL, stmnt))
04604 {
04605 fprintf(stderr, "Failed: %s\n", stmnt);
04606 status = DRMS_ERROR_BADDBQUERY;
04607 }
04608 else
04609 {
04610 if (!tocexists && env->createshadows)
04611 {
04612 if ((status = CreateTableOfCounts(env)) == DRMS_SUCCESS)
04613 {
04614 tocexists = 1;
04615 }
04616 }
04617 }
04618 }
04619 #endif
04620
04621 if (status == DRMS_SUCCESS)
04622 {
04623 shadowexists = ShadowExists(env, series, &status);
04624
04625 if (status == DRMS_ERROR_BADDBQUERY)
04626 {
04627 fprintf(stderr, "Unable to check database for the existence of the shadow table.\n");
04628 }
04629 }
04630
04631
04632
04633 if (status == DRMS_SUCCESS && shadowexists)
04634 {
04635
04636 int irow;
04637
04638 #if (defined TOC && TOC)
04639 int present;
04640 long long count;
04641 #endif
04642
04643 long long recnum;
04644 int isnew = -1;
04645 char recnumstr[64];
04646
04647 #if (defined TOC && TOC)
04648 for (irow = 0; irow < nrows && status == DRMS_SUCCESS && tocexists; irow++)
04649 #else
04650 for (irow = 0; irow < nrows && status == DRMS_SUCCESS; irow++)
04651 #endif
04652 {
04653 recnum = recnums[irow];
04654 snprintf(recnumstr, sizeof(recnumstr), "%lld", recnum);
04655
04656 #if (defined TRACKSHADOWS && TRACKSHADOWS)
04657 lsz = 128;
04658 recnumlist = calloc(lsz, sizeof(char));
04659 recnumlist = base_strcatalloc(recnumlist, recnumstr, &lsz);
04660 if (irow < nrows - 1)
04661 {
04662 recnumlist = base_strcatalloc(recnumlist, ",", &lsz);
04663 }
04664 #endif
04665
04666 #if (defined TOC && TOC)
04667 if (tocexists)
04668 {
04669
04670
04671
04672 present = IsSeriesPresent(env, kTableOfCountsNS, kTableOfCountsTab, series, &status);
04673
04674 if (status == DRMS_SUCCESS)
04675 {
04676 if (!present)
04677 {
04678
04679
04680
04681 count = CountRecordGroups(env, series, &status);
04682 if (status == DRMS_SUCCESS)
04683 {
04684 status = InsertSeries(env, kTableOfCountsNS, kTableOfCountsTab, series, count);
04685 }
04686 }
04687 else
04688 {
04689
04690
04691
04692
04693
04694 isnew = IsGroupNew(env, recnum, series, pkeynames, ncols, &status);
04695
04696 if (status == DRMS_SUCCESS)
04697 {
04698 if (!isnew)
04699 {
04700 status = AdvanceGroupCount(env, kTableOfCountsNS, kTableOfCountsTab, series);
04701 }
04702 }
04703 }
04704 }
04705 }
04706 #endif
04707
04708 if (status == DRMS_SUCCESS)
04709 {
04710 if (added)
04711 {
04712
04713
04714 if (isnew == -1)
04715 {
04716
04717 isnew = IsGroupNew(env, recnum, series, pkeynames, ncols, &status);
04718 }
04719
04720 if (isnew == 0)
04721 {
04722
04723 status = UpdateShadow(env, series, pkeynames, ncols, recnum, 1);
04724 }
04725 else if (isnew == 1)
04726 {
04727
04728
04729
04730 status = InsertIntoShadow(env, series, pkeynames, ncols, recnum);
04731 }
04732 else
04733 {
04734
04735 }
04736 }
04737 else
04738 {
04739
04740
04741 int wasdel;
04742
04743 wasdel = WasGroupDeleted(env, recnum, series, pkeynames, ncols, &status);
04744 if (wasdel)
04745 {
04746
04747
04748 status = DeleteFromShadow(env, series, pkeynames, ncols, recnum);
04749 }
04750 else
04751 {
04752
04753
04754
04755
04756 status = UpdateShadow(env, series, pkeynames, ncols, recnum, 0);
04757 }
04758 }
04759 }
04760 }
04761 }
04762
04763 #if (defined TRACKSHADOWS && TRACKSHADOWS)
04764
04765
04766 if (status == DRMS_SUCCESS && shadowexists)
04767 {
04768
04769
04770
04771 char *ns = NULL;
04772 char *tab = NULL;
04773 int track = 0;
04774 char query[2048];
04775 char *lcseries = NULL;
04776 int ndel;
04777
04778 if (!get_namespace(kShadowTrackTab, &ns, &tab))
04779 {
04780 track = (drms_query_tabexists(env->session, ns, tab, &status) != 0);
04781 free(ns);
04782 free(tab);
04783
04784 if (track)
04785 {
04786
04787
04788
04789
04790
04791 lcseries = strdup(series);
04792 if (!lcseries)
04793 {
04794 status = DRMS_ERROR_OUTOFMEMORY;
04795 }
04796 else
04797 {
04798 strtolower(lcseries);
04799 snprintf(query, sizeof(query), "DELETE FROM %s WHERE seriesname = '%s' AND recnum IN (%s)", kShadowTrackTab, lcseries, recnumlist);
04800 free(lcseries);
04801
04802 if (drms_dms(env->session, &ndel, query))
04803 {
04804 fprintf(stderr, "Failed: %s\n", query);
04805 status = DRMS_ERROR_BADDBQUERY;
04806 }
04807 else
04808 {
04809 if (nrows > 0 && ndel != nrows)
04810 {
04811 fprintf(stderr, "Unexpected number of rows (%d) in the shadow tracker.\n", ndel);
04812 status = DRMS_ERROR_SHADOWTAB;
04813 }
04814 }
04815 }
04816 }
04817 }
04818 else
04819 {
04820 status = DRMS_ERROR_OUTOFMEMORY;
04821 }
04822 }
04823 #endif
04824
04825 return status;
04826 }
04827
04828 #if (defined TOC && TOC)
04829 int drms_series_tocexists(DRMS_Env_t *env, int *status)
04830 {
04831 return TocExists(env, status);
04832 }
04833
04834
04835
04836 int drms_series_createtoc(DRMS_Env_t *env)
04837 {
04838 if (env->createshadows)
04839 {
04840 return CreateTableOfCounts(env);
04841 }
04842 else
04843 {
04844 return DRMS_ERROR_CANTCREATESHADOW;
04845 }
04846 }
04847
04848 int drms_series_intoc(DRMS_Env_t *env, const char *series, int *status)
04849 {
04850 return IsSeriesPresent(env, kTableOfCountsNS, kTableOfCountsTab, series, status);
04851 }
04852
04853
04854
04855 int drms_series_insertintotoc(DRMS_Env_t *env, const char *series)
04856 {
04857 int status = DRMS_SUCCESS;
04858 int count;
04859
04860 count = CountRecordGroups(env, series, &status);
04861 if (status == DRMS_SUCCESS)
04862 {
04863 status = InsertSeries(env, kTableOfCountsNS, kTableOfCountsTab, series, count);
04864 }
04865
04866 return status;
04867 }
04868 #endif
04869
04870
04871 char *drms_series_nrecords_querystringA(const char *series, int *status)
04872 {
04873 char *query = NULL;
04874 size_t stsz = 8192;
04875 char *lcseries = NULL;
04876 int istat = DRMS_SUCCESS;
04877
04878 lcseries = strdup(series);
04879
04880 if (lcseries)
04881 {
04882 strtolower(lcseries);
04883 query = malloc(stsz);
04884 if (query)
04885 {
04886 *query = '\0';
04887
04888 #if (defined TOC && TOC)
04889 query = base_strcatalloc(query, "SELECT ", &stsz);
04890 query = base_strcatalloc(query, kTableOfCountsColNRecs, &stsz);
04891 query = base_strcatalloc(query, " FROM ", &stsz);
04892 query = base_strcatalloc(query, kTableOfCountsNS, &stsz);
04893 query = base_strcatalloc(query, ".", &stsz);
04894 query = base_strcatalloc(query, kTableOfCountsTab, &stsz);
04895 query = base_strcatalloc(query, " WHERE lower(", &stsz);
04896 query = base_strcatalloc(query, kTableOfCountsColSeries, &stsz);
04897 query = base_strcatalloc(query, ") = '", &stsz);
04898 query = base_strcatalloc(query, lcseries, &stsz);
04899 query = base_strcatalloc(query, "'", &stsz);
04900 #else
04901
04902 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
04903 query = base_strcatalloc(query, lcseries, &stsz);
04904 query = base_strcatalloc(query, kShadowSuffix, &stsz);
04905 #endif
04906 }
04907 else
04908 {
04909 istat = DRMS_ERROR_OUTOFMEMORY;
04910 }
04911
04912 free(lcseries);
04913 lcseries = NULL;
04914 }
04915 else
04916 {
04917 istat = DRMS_ERROR_OUTOFMEMORY;
04918 }
04919
04920 if (status)
04921 {
04922 *status = istat;
04923 }
04924
04925 return query;
04926 }
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938
04939
04940
04941
04942
04943
04944
04945
04946
04947
04948
04949
04950
04951
04952 char *drms_series_nrecords_querystringB(const char *series, const char *npkwhere, int *status)
04953 {
04954 char *query = NULL;
04955 size_t stsz = 8192;
04956 char *lcseries = NULL;
04957 char shadow[DRMS_MAXSERIESNAMELEN];
04958 char tabname[256];
04959 int istat = DRMS_SUCCESS;
04960
04961 lcseries = strdup(series);
04962
04963 if (lcseries)
04964 {
04965 strtolower(lcseries);
04966 query = malloc(stsz);
04967 if (query)
04968 {
04969 *query = '\0';
04970 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
04971 if (GetTempTable(tabname, sizeof(tabname)))
04972 {
04973 istat = DRMS_ERROR_OVERFLOW;
04974 }
04975 else
04976 {
04977
04978 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
04979 query = base_strcatalloc(query, tabname, &stsz);
04980 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
04981 query = base_strcatalloc(query, shadow, &stsz);
04982 query = base_strcatalloc(query, ";\n", &stsz);
04983
04984
04985 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
04986 query = base_strcatalloc(query, lcseries, &stsz);
04987 query = base_strcatalloc(query, " AS T WHERE T.recnum IN (SELECT recnum FROM ", &stsz);
04988 query = base_strcatalloc(query, tabname, &stsz);
04989 query = base_strcatalloc(query, ") AND ", &stsz);
04990 query = base_strcatalloc(query, npkwhere, &stsz);
04991 }
04992 }
04993 else
04994 {
04995 istat = DRMS_ERROR_OUTOFMEMORY;
04996 }
04997
04998 free(lcseries);
04999 lcseries = NULL;
05000 }
05001 else
05002 {
05003 istat = DRMS_ERROR_OUTOFMEMORY;
05004 }
05005
05006 if (status)
05007 {
05008 *status = istat;
05009 }
05010
05011 return query;
05012 }
05013
05014
05015
05016
05017 char *drms_series_nrecords_querystringC(const char *series, const char *pkwhere, int *status)
05018 {
05019 char *query = NULL;
05020 size_t stsz = 8192;
05021 char *lcseries = NULL;
05022 int istat = DRMS_SUCCESS;
05023
05024 lcseries = strdup(series);
05025
05026 if (lcseries)
05027 {
05028 strtolower(lcseries);
05029 query = malloc(stsz);
05030 if (query)
05031 {
05032 *query = '\0';
05033
05034 query = base_strcatalloc(query, "SELECT count(recnum) FROM ", &stsz);
05035 query = base_strcatalloc(query, lcseries, &stsz);
05036 query = base_strcatalloc(query, kShadowSuffix, &stsz);
05037 query = base_strcatalloc(query, " WHERE ", &stsz);
05038 query = base_strcatalloc(query, pkwhere, &stsz);
05039 }
05040 else
05041 {
05042 istat = DRMS_ERROR_OUTOFMEMORY;
05043 }
05044
05045 free(lcseries);
05046 lcseries = NULL;
05047 }
05048 else
05049 {
05050 istat = DRMS_ERROR_OUTOFMEMORY;
05051 }
05052
05053 if (status)
05054 {
05055 *status = istat;
05056 }
05057
05058 return query;
05059 }
05060
05061
05062
05063
05064
05065
05066
05067
05068
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078 char *drms_series_nrecords_querystringD(const char *series, const char *pkwhere, const char *npkwhere, int *status)
05079 {
05080 char *query = NULL;
05081 size_t stsz = 8192;
05082 char *lcseries = NULL;
05083 char shadow[DRMS_MAXSERIESNAMELEN];
05084 char tabname[256];
05085 int istat = DRMS_SUCCESS;
05086
05087 lcseries = strdup(series);
05088
05089 if (lcseries)
05090 {
05091 strtolower(lcseries);
05092 query = malloc(stsz);
05093 if (query)
05094 {
05095 *query = '\0';
05096
05097 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
05098 if (GetTempTable(tabname, sizeof(tabname)))
05099 {
05100 istat = DRMS_ERROR_OVERFLOW;
05101 }
05102 else
05103 {
05104
05105 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
05106 query = base_strcatalloc(query, tabname, &stsz);
05107 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
05108 query = base_strcatalloc(query, shadow, &stsz);
05109 query = base_strcatalloc(query, " WHERE ", &stsz);
05110 query = base_strcatalloc(query, pkwhere, &stsz);
05111 query = base_strcatalloc(query, ";\n", &stsz);
05112
05113
05114 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
05115 query = base_strcatalloc(query, lcseries, &stsz);
05116 query = base_strcatalloc(query, " AS T WHERE T.recnum IN (SELECT recnum FROM ", &stsz);
05117 query = base_strcatalloc(query, tabname, &stsz);
05118 query = base_strcatalloc(query, ") AND ", &stsz);
05119 query = base_strcatalloc(query, npkwhere, &stsz);
05120 }
05121 }
05122 else
05123 {
05124 istat = DRMS_ERROR_OUTOFMEMORY;
05125 }
05126
05127 free(lcseries);
05128 lcseries = NULL;
05129 }
05130 else
05131 {
05132 istat = DRMS_ERROR_OUTOFMEMORY;
05133 }
05134
05135 if (status)
05136 {
05137 *status = istat;
05138 }
05139
05140 return query;
05141 }
05142
05143
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179
05180
05181
05182
05183
05184
05185
05186
05187
05188
05189
05190
05191
05192
05193
05194
05195
05196
05197
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210
05211
05212
05213
05214
05215
05216
05217
05218 static int InnerFLSelect(int npkeys, HContainer_t *firstlast, size_t *stsz, char *pkey[], const char *pkeylist, const char *shadow, HContainer_t *pkwhereNFL, char **query, char **lasttab)
05219 {
05220 int iloop;
05221 int init;
05222 char *pkwhere = NULL;
05223 int istat = 0;
05224 char **ppkwhere = NULL;
05225 char fl;
05226 char tmptab[256];
05227 char prevtmptab[256];
05228
05229 init = 0;
05230 for (iloop = 0; iloop < npkeys; iloop++)
05231 {
05232 if (hcon_member_lower(firstlast, pkey[iloop]))
05233 {
05234
05235
05236 if (GetTempTable(tmptab, sizeof(tmptab)))
05237 {
05238 istat = DRMS_ERROR_OVERFLOW;
05239 }
05240 else
05241 {
05242 if (init != 0)
05243 {
05244 *query = base_strcatalloc(*query, ";", stsz);
05245 }
05246
05247 *query = base_strcatalloc(*query, "CREATE TEMPORARY TABLE ", stsz);
05248 *query = base_strcatalloc(*query, tmptab, stsz);
05249 *query = base_strcatalloc(*query, " AS ", stsz);
05250 *query = base_strcatalloc(*query, "SELECT recnum, ", stsz);
05251 *query = base_strcatalloc(*query, pkeylist, stsz);
05252 *query = base_strcatalloc(*query, " FROM ", stsz);
05253
05254 if (init == 0)
05255 {
05256 *query = base_strcatalloc(*query, shadow, stsz);
05257 }
05258 else
05259 {
05260 *query = base_strcatalloc(*query, prevtmptab, stsz);
05261 }
05262
05263 *query = base_strcatalloc(*query, " WHERE ", stsz);
05264 *query = base_strcatalloc(*query, pkey[iloop], stsz);
05265 *query = base_strcatalloc(*query, " = (SELECT ", stsz);
05266 fl = *((char *)hcon_lookup_lower(firstlast, pkey[iloop]));
05267 if (fl == 'F')
05268 {
05269 *query = base_strcatalloc(*query, "min(", stsz);
05270 }
05271 else
05272 {
05273 *query = base_strcatalloc(*query, "max(", stsz);
05274 }
05275
05276 *query = base_strcatalloc(*query, pkey[iloop], stsz);
05277 *query = base_strcatalloc(*query, ") FROM ", stsz);
05278
05279 if (init == 0)
05280 {
05281 *query = base_strcatalloc(*query, shadow, stsz);
05282 }
05283 else
05284 {
05285 *query = base_strcatalloc(*query, prevtmptab, stsz);
05286 }
05287
05288 *query = base_strcatalloc(*query, ")", stsz);
05289
05290 snprintf(prevtmptab, sizeof(prevtmptab), "%s", tmptab);
05291
05292 init = 1;
05293 }
05294 }
05295 else
05296 {
05297
05298
05299
05300 ppkwhere = (char **)hcon_lookup_lower(pkwhereNFL, pkey[iloop]);
05301 if (ppkwhere)
05302 {
05303 pkwhere = *ppkwhere;
05304 }
05305 else
05306 {
05307 pkwhere = NULL;
05308 }
05309
05310 if (pkwhere)
05311 {
05312 if (GetTempTable(tmptab, sizeof(tmptab)))
05313 {
05314 istat = DRMS_ERROR_OVERFLOW;
05315 }
05316 else
05317 {
05318 if (init != 0)
05319 {
05320 *query = base_strcatalloc(*query, ";", stsz);
05321 }
05322
05323 *query = base_strcatalloc(*query, "CREATE TEMPORARY TABLE ", stsz);
05324 *query = base_strcatalloc(*query, tmptab, stsz);
05325 *query = base_strcatalloc(*query, " AS ", stsz);
05326 *query = base_strcatalloc(*query, "SELECT recnum, ", stsz);
05327 *query = base_strcatalloc(*query, pkeylist, stsz);
05328 *query = base_strcatalloc(*query, " FROM ", stsz);
05329
05330 if (init == 0)
05331 {
05332 *query = base_strcatalloc(*query, shadow, stsz);
05333 }
05334 else
05335 {
05336 *query = base_strcatalloc(*query, prevtmptab, stsz);
05337 }
05338
05339 if (ppkwhere)
05340 {
05341 *query = base_strcatalloc(*query, " WHERE ", stsz);
05342 *query = base_strcatalloc(*query, pkwhere, stsz);
05343 }
05344
05345 snprintf(prevtmptab, sizeof(prevtmptab), "%s", tmptab);
05346
05347 init = 1;
05348 }
05349 }
05350 else
05351 {
05352
05353
05354
05355
05356 }
05357 }
05358 }
05359
05360 if (lasttab)
05361 {
05362 *lasttab = strdup(tmptab);
05363 }
05364
05365 return istat;
05366 }
05367
05368
05369
05370
05371
05372
05373 char *drms_series_nrecords_querystringFL(DRMS_Env_t *env, const char *series, const char *npkwhere, HContainer_t *pkwhereNFL, HContainer_t *firstlast, int *status)
05374 {
05375 char *query = NULL;
05376 size_t stsz = 2048;
05377 char *lcseries = NULL;
05378 int iloop;
05379 char *pkey[DRMS_MAXPRIMIDX];
05380 int npkeys;
05381 char shadow[DRMS_MAXSERIESNAMELEN];
05382 char *lasttab = NULL;
05383 char *pkeylist = NULL;
05384 int istat = DRMS_SUCCESS;
05385
05386 lcseries = strdup(series);
05387
05388 if (lcseries)
05389 {
05390 strtolower(lcseries);
05391 query = malloc(stsz);
05392 if (query)
05393 {
05394 *query = '\0';
05395 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
05396 pkeylist = CreatePKeyList(env, series, NULL, NULL, pkey, &npkeys, 0, &istat);
05397
05398 if (istat == DRMS_SUCCESS)
05399 {
05400 istat = InnerFLSelect(npkeys, firstlast, &stsz, pkey, pkeylist, shadow, pkwhereNFL, &query, &lasttab);
05401 }
05402
05403 if (istat == DRMS_SUCCESS)
05404 {
05405
05406
05407
05408
05409 query = base_strcatalloc(query, ";\n", &stsz);
05410
05411 query = base_strcatalloc(query, "SELECT count(*) FROM ", &stsz);
05412 query = base_strcatalloc(query, lcseries, &stsz);
05413 query = base_strcatalloc(query, " WHERE recnum in (SELECT recnum FROM ", &stsz);
05414 query = base_strcatalloc(query, lasttab, &stsz);
05415 query = base_strcatalloc(query, ")", &stsz);
05416
05417 if (npkwhere && *npkwhere)
05418 {
05419 query = base_strcatalloc(query, " AND ", &stsz);
05420 query = base_strcatalloc(query, npkwhere, &stsz);
05421 }
05422 }
05423
05424
05425 for (iloop = 0; iloop < npkeys; iloop++)
05426 {
05427 if (pkey[iloop])
05428 {
05429 free(pkey[iloop]);
05430 pkey[iloop] = NULL;
05431 }
05432 }
05433 }
05434 else
05435 {
05436 istat = DRMS_ERROR_OUTOFMEMORY;
05437 }
05438
05439 free(lcseries);
05440 lcseries = NULL;
05441 }
05442 else
05443 {
05444 istat = DRMS_ERROR_OUTOFMEMORY;
05445 }
05446
05447 if (status)
05448 {
05449 *status = istat;
05450 }
05451
05452 return query;
05453 }
05454
05455 int drms_series_nrecords(DRMS_Env_t *env, const char *series, int *status)
05456 {
05457 int count;
05458 int istat = DRMS_SUCCESS;
05459 char *query = NULL;
05460 DB_Text_Result_t *tres = NULL;
05461
05462 count = -1;
05463
05464 query = drms_series_nrecords_querystringA(series, &istat);
05465 tres = drms_query_txt(env->session, query);
05466
05467 if (tres)
05468 {
05469 if (tres->num_rows == 1 && tres->num_cols == 1)
05470 {
05471 count = atoll(tres->field[0][0]);
05472 }
05473
05474 db_free_text_result(tres);
05475 tres = NULL;
05476 }
05477 else
05478 {
05479 fprintf(stderr, "Failed: %s\n", query);
05480 istat = DRMS_ERROR_BADDBQUERY;
05481 }
05482
05483 if (status)
05484 {
05485 *status = istat;
05486 }
05487
05488 return count;
05489 }
05490
05491 int drms_series_shadowexists(DRMS_Env_t *env, const char *series, int *status)
05492 {
05493 return ShadowExists(env, series, status);
05494 }
05495
05496
05497 int drms_series_createshadow(DRMS_Env_t *env, const char *series, const char *tname)
05498 {
05499 return CreateShadow(env, series, tname, NULL);
05500 }
05501
05502 int drms_series_dropshadow(DRMS_Env_t *env, const char *series, const char *tname)
05503 {
05504 return DropShadow(env, series, tname, NULL);
05505 }
05506
05507 void drms_series_setcreateshadows(DRMS_Env_t *env, int *val)
05508 {
05509 if (val)
05510 {
05511 env->createshadows = (*val == 0 ? 0 : 1);
05512 }
05513 else
05514 {
05515 env->createshadows = 1;
05516 }
05517 }
05518
05519 void drms_series_unsetcreateshadows(DRMS_Env_t *env)
05520 {
05521 env->createshadows = 0;
05522 }
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545
05546
05547
05548
05549
05550
05551
05552 char *drms_series_all_querystringA(DRMS_Env_t *env, const char *series, const char *fields, int limit, int cursor, int *status)
05553 {
05554 char *query = NULL;
05555 int istat = DRMS_SUCCESS;
05556 size_t stsz = 8192;
05557 char *lcseries = NULL;
05558 char *qualfields = NULL;
05559 char *qualpkeylist = NULL;
05560 char limitstr[32];
05561 char tabname[256];
05562 char shadow[DRMS_MAXSERIESNAMELEN];
05563
05564 lcseries = strdup(series);
05565
05566 if (lcseries)
05567 {
05568 strtolower(lcseries);
05569 query = malloc(stsz);
05570
05571 if (query)
05572 {
05573 *query = '\0';
05574
05575 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
05576 snprintf(limitstr, sizeof(limitstr), "%d", limit);
05577
05578 if (limit > kLimitCutoff && !cursor)
05579 {
05580
05581
05582 if (GetTempTable(tabname, sizeof(tabname)))
05583 {
05584 istat = DRMS_ERROR_OVERFLOW;
05585 }
05586 else
05587 {
05588 qualpkeylist = CreatePKeyList(env, series, "", NULL, NULL, NULL, 0, &istat);
05589
05590 if (istat == DRMS_SUCCESS)
05591 {
05592
05593 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
05594 query = base_strcatalloc(query, tabname, &stsz);
05595 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
05596 query = base_strcatalloc(query, shadow, &stsz);
05597 query = base_strcatalloc(query, ";\n", &stsz);
05598
05599
05600 query = base_strcatalloc(query, "SELECT ", &stsz);
05601 query = base_strcatalloc(query, fields, &stsz);
05602 query = base_strcatalloc(query, " FROM ", &stsz);
05603 query = base_strcatalloc(query, lcseries, &stsz);
05604 query = base_strcatalloc(query, " WHERE recnum IN (SELECT recnum FROM ", &stsz);
05605 query = base_strcatalloc(query, tabname, &stsz);
05606 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
05607 query = base_strcatalloc(query, qualpkeylist, &stsz);
05608 query = base_strcatalloc(query, " LIMIT ", &stsz);
05609 query = base_strcatalloc(query, limitstr, &stsz);
05610
05611 free(qualpkeylist);
05612 qualpkeylist = NULL;
05613 }
05614 }
05615 }
05616 else
05617 {
05618
05619 qualfields = PrependFields(fields, "T1.", &istat);
05620
05621
05622 qualpkeylist = CreatePKeyList(env, series, "T2.", NULL, NULL, NULL, 0, &istat);
05623
05624 if (istat == DRMS_SUCCESS)
05625 {
05626
05627 query = base_strcatalloc(query, "SELECT ", &stsz);
05628 query = base_strcatalloc(query, qualfields, &stsz);
05629 query = base_strcatalloc(query, " FROM ", &stsz);
05630 query = base_strcatalloc(query, lcseries, &stsz);
05631 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
05632 query = base_strcatalloc(query, shadow, &stsz);
05633 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) ORDER BY ", &stsz);
05634 query = base_strcatalloc(query, qualpkeylist, &stsz);
05635 query = base_strcatalloc(query, " LIMIT ", &stsz);
05636 query = base_strcatalloc(query, limitstr, &stsz);
05637 }
05638
05639 free(qualpkeylist);
05640 qualpkeylist = NULL;
05641 free(qualfields);
05642 qualfields = NULL;
05643 }
05644 }
05645 else
05646 {
05647 istat = DRMS_ERROR_OUTOFMEMORY;
05648 }
05649
05650 free(lcseries);
05651 lcseries = NULL;
05652 }
05653 else
05654 {
05655 istat = DRMS_ERROR_OUTOFMEMORY;
05656 }
05657
05658 if (status)
05659 {
05660 *status = istat;
05661 }
05662
05663 return query;
05664 }
05665
05666
05667
05668
05669
05670
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695
05696
05697
05698 char *drms_series_all_querystringB(DRMS_Env_t *env, const char *series, const char *npkwhere, const char *fields, int limit, int cursor, int *status)
05699 {
05700 char *query = NULL;
05701 int istat = DRMS_SUCCESS;
05702 size_t stsz = 8192;
05703 char *lcseries = NULL;
05704 char *qualfields = NULL;
05705 char *qualpkeylist = NULL;
05706 char *qualnpkwhere = NULL;
05707 char limitstr[32];
05708 char shadow[DRMS_MAXSERIESNAMELEN];
05709 char tabname[256];
05710
05711 lcseries = strdup(series);
05712
05713 if (lcseries)
05714 {
05715 strtolower(lcseries);
05716 query = malloc(stsz);
05717
05718 if (query)
05719 {
05720 *query = '\0';
05721
05722 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
05723 snprintf(limitstr, sizeof(limitstr), "%d", limit);
05724
05725 if (limit > kLimitCutoff && !cursor)
05726 {
05727
05728
05729 if (GetTempTable(tabname, sizeof(tabname)))
05730 {
05731 istat = DRMS_ERROR_OVERFLOW;
05732 }
05733 else
05734 {
05735 qualpkeylist = CreatePKeyList(env, series, "", NULL, NULL, NULL, 0, &istat);
05736
05737 if (istat == DRMS_SUCCESS)
05738 {
05739
05740 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
05741 query = base_strcatalloc(query, tabname, &stsz);
05742 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
05743 query = base_strcatalloc(query, shadow, &stsz);
05744 query = base_strcatalloc(query, ";\n", &stsz);
05745
05746
05747 query = base_strcatalloc(query, "SELECT ", &stsz);
05748 query = base_strcatalloc(query, fields, &stsz);
05749 query = base_strcatalloc(query, " FROM ", &stsz);
05750 query = base_strcatalloc(query, lcseries, &stsz);
05751 query = base_strcatalloc(query, " WHERE recnum IN (SELECT recnum FROM ", &stsz);
05752 query = base_strcatalloc(query, tabname, &stsz);
05753 query = base_strcatalloc(query, ") AND ", &stsz);
05754 query = base_strcatalloc(query, npkwhere, &stsz);
05755 query = base_strcatalloc(query, " ORDER BY ", &stsz);
05756 query = base_strcatalloc(query, qualpkeylist, &stsz);
05757 query = base_strcatalloc(query, " LIMIT ", &stsz);
05758 query = base_strcatalloc(query, limitstr, &stsz);
05759
05760 free(qualpkeylist);
05761 qualpkeylist = NULL;
05762 }
05763 }
05764 }
05765 else
05766 {
05767
05768 qualfields = PrependFields(fields, "T1.", &istat);
05769
05770 if (istat == DRMS_SUCCESS)
05771 {
05772
05773
05774
05775 qualnpkwhere = base_strcasereplace(npkwhere, "recnum", "T1.recnum");
05776 if (!qualnpkwhere)
05777 {
05778
05779 qualnpkwhere = strdup(npkwhere);
05780 }
05781 }
05782
05783 if (qualnpkwhere)
05784 {
05785
05786
05787 char *tmp = NULL;
05788 tmp = PrependWhere(env, qualnpkwhere, series, "T2.", &istat);
05789 if (istat == DRMS_SUCCESS)
05790 {
05791 free(qualnpkwhere);
05792 qualnpkwhere = tmp;
05793 }
05794 }
05795 else
05796 {
05797 istat = DRMS_ERROR_OUTOFMEMORY;
05798 }
05799
05800 if (istat == DRMS_SUCCESS)
05801 {
05802
05803 qualpkeylist = CreatePKeyList(env, series, "T2.", NULL, NULL, NULL, 0, &istat);
05804 }
05805
05806 if (istat == DRMS_SUCCESS)
05807 {
05808
05809 query = base_strcatalloc(query, "SELECT ", &stsz);
05810 query = base_strcatalloc(query, qualfields, &stsz);
05811 query = base_strcatalloc(query, " FROM ", &stsz);
05812 query = base_strcatalloc(query, lcseries, &stsz);
05813 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
05814 query = base_strcatalloc(query, shadow, &stsz);
05815 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) WHERE ", &stsz);
05816 query = base_strcatalloc(query, qualnpkwhere, &stsz);
05817 query = base_strcatalloc(query, " ORDER BY ", &stsz);
05818 query = base_strcatalloc(query, qualpkeylist, &stsz);
05819 query = base_strcatalloc(query, " LIMIT ", &stsz);
05820 query = base_strcatalloc(query, limitstr, &stsz);
05821 }
05822
05823 free(qualnpkwhere);
05824 qualnpkwhere = NULL;
05825 free(qualpkeylist);
05826 qualpkeylist = NULL;
05827 free(qualfields);
05828 qualfields = NULL;
05829 }
05830 }
05831 else
05832 {
05833 istat = DRMS_ERROR_OUTOFMEMORY;
05834 }
05835
05836 free(lcseries);
05837 lcseries = NULL;
05838 }
05839 else
05840 {
05841 istat = DRMS_ERROR_OUTOFMEMORY;
05842 }
05843
05844 if (status)
05845 {
05846 *status = istat;
05847 }
05848
05849 return query;
05850 }
05851
05852
05853
05854
05855
05856
05857
05858
05859
05860
05861
05862
05863
05864
05865
05866
05867
05868
05869
05870
05871
05872
05873
05874
05875
05876
05877
05878
05879
05880
05881
05882 char *drms_series_all_querystringC(DRMS_Env_t *env, const char *series, const char *pkwhere, const char *fields, int limit, int cursor, int *status)
05883 {
05884 char *query = NULL;
05885 int istat = DRMS_SUCCESS;
05886 size_t stsz = 8192;
05887 char *lcseries = NULL;
05888 char *qualfields = NULL;
05889 char *qualpkeylist = NULL;
05890 char *qualpkwhere = NULL;
05891 char limitstr[32];
05892 char tabname[256];
05893 char shadow[DRMS_MAXSERIESNAMELEN];
05894
05895 lcseries = strdup(series);
05896
05897 if (lcseries)
05898 {
05899 strtolower(lcseries);
05900 query = malloc(stsz);
05901
05902 if (query)
05903 {
05904 *query = '\0';
05905
05906 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
05907 snprintf(limitstr, sizeof(limitstr), "%d", limit);
05908
05909 if (limit > kLimitCutoff && !cursor)
05910 {
05911
05912
05913 if (GetTempTable(tabname, sizeof(tabname)))
05914 {
05915 istat = DRMS_ERROR_OVERFLOW;
05916 }
05917 else
05918 {
05919 qualpkeylist = CreatePKeyList(env, series, "", NULL, NULL, NULL, 0, &istat);
05920
05921 if (istat == DRMS_SUCCESS)
05922 {
05923
05924 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
05925 query = base_strcatalloc(query, tabname, &stsz);
05926 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
05927 query = base_strcatalloc(query, shadow, &stsz);
05928 query = base_strcatalloc(query, " WHERE ", &stsz);
05929 query = base_strcatalloc(query, pkwhere, &stsz);
05930 query = base_strcatalloc(query, ";\n", &stsz);
05931
05932 query = base_strcatalloc(query, "SELECT ", &stsz);
05933 query = base_strcatalloc(query, fields, &stsz);
05934 query = base_strcatalloc(query, " FROM ", &stsz);
05935 query = base_strcatalloc(query, lcseries, &stsz);
05936 query = base_strcatalloc(query, " WHERE recnum IN (SELECT recnum FROM ", &stsz);
05937 query = base_strcatalloc(query, tabname, &stsz);
05938 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
05939 query = base_strcatalloc(query, qualpkeylist, &stsz);
05940 query = base_strcatalloc(query, " LIMIT ", &stsz);
05941 query = base_strcatalloc(query, limitstr, &stsz);
05942
05943 free(qualpkeylist);
05944 qualpkeylist = NULL;
05945 }
05946 }
05947 }
05948 else
05949 {
05950
05951 qualfields = PrependFields(fields, "T1.", &istat);
05952
05953
05954 if (istat == DRMS_SUCCESS)
05955 {
05956 qualpkeylist = CreatePKeyList(env, series, "T2.", NULL, NULL, NULL, 0, &istat);
05957 }
05958
05959
05960
05961
05962 if (istat == DRMS_SUCCESS)
05963 {
05964 qualpkwhere = PrependWhere(env, pkwhere, series, "T2.", &istat);
05965 }
05966
05967 if (istat == DRMS_SUCCESS)
05968 {
05969
05970 query = base_strcatalloc(query, "SELECT ", &stsz);
05971 query = base_strcatalloc(query, qualfields, &stsz);
05972 query = base_strcatalloc(query, " FROM ", &stsz);
05973 query = base_strcatalloc(query, lcseries, &stsz);
05974 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
05975 query = base_strcatalloc(query, shadow, &stsz);
05976 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) WHERE ", &stsz);
05977 query = base_strcatalloc(query, qualpkwhere, &stsz);
05978 query = base_strcatalloc(query, " ORDER BY ", &stsz);
05979 query = base_strcatalloc(query, qualpkeylist, &stsz);
05980 query = base_strcatalloc(query, " LIMIT ", &stsz);
05981 query = base_strcatalloc(query, limitstr, &stsz);
05982 }
05983
05984 free(qualpkwhere);
05985 qualpkwhere = NULL;
05986 free(qualpkeylist);
05987 qualpkeylist = NULL;
05988 free(qualfields);
05989 qualfields = NULL;
05990 }
05991 }
05992 else
05993 {
05994 istat = DRMS_ERROR_OUTOFMEMORY;
05995 }
05996
05997 free(lcseries);
05998 lcseries = NULL;
05999 }
06000 else
06001 {
06002 istat = DRMS_ERROR_OUTOFMEMORY;
06003 }
06004
06005 if (status)
06006 {
06007 *status = istat;
06008 }
06009
06010 return query;
06011 }
06012
06013
06014
06015
06016
06017
06018
06019
06020
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044 char *drms_series_all_querystringD(DRMS_Env_t *env, const char *series, const char *pkwhere, const char *npkwhere, const char *fields, int limit, int cursor, int *status)
06045 {
06046 char *query = NULL;
06047 int istat = DRMS_SUCCESS;
06048 size_t stsz = 8192;
06049 char *lcseries = NULL;
06050 char *qualfields = NULL;
06051 char *qualpkeylist = NULL;
06052 char *qualpkwhere = NULL;
06053 char *qualnpkwhere = NULL;
06054 char limitstr[32];
06055 char shadow[DRMS_MAXSERIESNAMELEN];
06056 char tabname[256];
06057
06058 lcseries = strdup(series);
06059
06060 if (lcseries)
06061 {
06062 strtolower(lcseries);
06063 query = malloc(stsz);
06064
06065 if (query)
06066 {
06067 *query = '\0';
06068
06069 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06070 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06071
06072 if (limit > kLimitCutoff && !cursor)
06073 {
06074
06075
06076 if (GetTempTable(tabname, sizeof(tabname)))
06077 {
06078 istat = DRMS_ERROR_OVERFLOW;
06079 }
06080 else
06081 {
06082 qualpkeylist = CreatePKeyList(env, series, "", NULL, NULL, NULL, 0, &istat);
06083
06084 if (istat == DRMS_SUCCESS)
06085 {
06086
06087 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
06088 query = base_strcatalloc(query, tabname, &stsz);
06089 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
06090 query = base_strcatalloc(query, shadow, &stsz);
06091 query = base_strcatalloc(query, " WHERE ", &stsz);
06092 query = base_strcatalloc(query, pkwhere, &stsz);
06093 query = base_strcatalloc(query, ";\n", &stsz);
06094
06095
06096 query = base_strcatalloc(query, "SELECT ", &stsz);
06097 query = base_strcatalloc(query, fields, &stsz);
06098 query = base_strcatalloc(query, " FROM ", &stsz);
06099 query = base_strcatalloc(query, lcseries, &stsz);
06100 query = base_strcatalloc(query, " WHERE recnum IN (SELECT recnum FROM ", &stsz);
06101 query = base_strcatalloc(query, tabname, &stsz);
06102 query = base_strcatalloc(query, ") AND ", &stsz);
06103 query = base_strcatalloc(query, npkwhere, &stsz);
06104 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06105 query = base_strcatalloc(query, qualpkeylist, &stsz);
06106 query = base_strcatalloc(query, " LIMIT ", &stsz);
06107 query = base_strcatalloc(query, limitstr, &stsz);
06108
06109 free(qualpkeylist);
06110 qualpkeylist = NULL;
06111 }
06112 }
06113 }
06114 else
06115 {
06116
06117
06118 qualfields = PrependFields(fields, "T1.", &istat);
06119
06120
06121 if (istat == DRMS_SUCCESS)
06122 {
06123 qualpkeylist = CreatePKeyList(env, series, "T2.", NULL, NULL, NULL, 0, &istat);
06124 }
06125
06126
06127
06128
06129 if (istat == DRMS_SUCCESS)
06130 {
06131 qualpkwhere = PrependWhere(env, pkwhere, series, "T2.", &istat);
06132 }
06133
06134 if (istat == DRMS_SUCCESS)
06135 {
06136
06137
06138
06139
06140 qualnpkwhere = base_strcasereplace(npkwhere, "recnum", "T1.recnum");
06141 if (!qualnpkwhere)
06142 {
06143
06144 qualnpkwhere = strdup(npkwhere);
06145 }
06146
06147 if (qualnpkwhere)
06148 {
06149
06150
06151 char *tmp = NULL;
06152 tmp = PrependWhere(env, qualnpkwhere, series, "T2.", &istat);
06153 if (istat == DRMS_SUCCESS)
06154 {
06155 free(qualnpkwhere);
06156 qualnpkwhere = tmp;
06157 }
06158 }
06159 else
06160 {
06161 istat = DRMS_ERROR_OUTOFMEMORY;
06162 }
06163 }
06164
06165 if (istat == DRMS_SUCCESS)
06166 {
06167
06168 query = base_strcatalloc(query, "SELECT ", &stsz);
06169 query = base_strcatalloc(query, qualfields, &stsz);
06170 query = base_strcatalloc(query, " FROM ", &stsz);
06171 query = base_strcatalloc(query, lcseries, &stsz);
06172 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
06173 query = base_strcatalloc(query, shadow, &stsz);
06174 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) WHERE ", &stsz);
06175 query = base_strcatalloc(query, qualpkwhere, &stsz);
06176 query = base_strcatalloc(query, " AND ", &stsz);
06177 query = base_strcatalloc(query, qualnpkwhere, &stsz);
06178 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06179 query = base_strcatalloc(query, qualpkeylist, &stsz);
06180 query = base_strcatalloc(query, " LIMIT ", &stsz);
06181 query = base_strcatalloc(query, limitstr, &stsz);
06182 }
06183
06184 free(qualnpkwhere);
06185 qualnpkwhere = NULL;
06186 free(qualpkwhere);
06187 qualpkwhere = NULL;
06188 free(qualpkeylist);
06189 qualpkeylist = NULL;
06190 free(qualfields);
06191 qualfields = NULL;
06192 }
06193 }
06194 else
06195 {
06196 istat = DRMS_ERROR_OUTOFMEMORY;
06197 }
06198
06199 free(lcseries);
06200 lcseries = NULL;
06201 }
06202 else
06203 {
06204 istat = DRMS_ERROR_OUTOFMEMORY;
06205 }
06206
06207 if (status)
06208 {
06209 *status = istat;
06210 }
06211
06212 return query;
06213 }
06214
06215
06216
06217
06218
06219
06220
06221
06222
06223 char *drms_series_all_querystringFL(DRMS_Env_t *env, const char *series, const char *npkwhere, HContainer_t *pkwhereNFL, const char *fields, int limit, HContainer_t *firstlast, int *status)
06224 {
06225 char *query = NULL;
06226 int istat = DRMS_SUCCESS;
06227 size_t stsz = 2048;
06228 char *lcseries = NULL;
06229 int npkeys = 0;
06230 char limitstr[32];
06231 char shadow[DRMS_MAXSERIESNAMELEN];
06232 char *pkey[DRMS_MAXPRIMIDX];
06233 char *pkeylist = NULL;
06234 char *lasttab = NULL;
06235 int iloop;
06236
06237 lcseries = strdup(series);
06238
06239 if (lcseries)
06240 {
06241 strtolower(lcseries);
06242 query = malloc(stsz);
06243
06244 if (query)
06245 {
06246 *query = '\0';
06247
06248 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06249 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06250
06251 pkeylist = CreatePKeyList(env, series, NULL, NULL, pkey, &npkeys, 0, &istat);
06252
06253 if (istat == DRMS_SUCCESS)
06254 {
06255 if (istat == DRMS_SUCCESS)
06256 {
06257 istat = InnerFLSelect(npkeys, firstlast, &stsz, pkey, pkeylist, shadow, pkwhereNFL, &query, &lasttab);
06258 }
06259
06260 if (istat == DRMS_SUCCESS)
06261 {
06262
06263
06264
06265
06266 query = base_strcatalloc(query, ";\n", &stsz);
06267
06268 query = base_strcatalloc(query, "SELECT ", &stsz);
06269 query = base_strcatalloc(query, fields, &stsz);
06270 query = base_strcatalloc(query, " FROM ", &stsz);
06271 query = base_strcatalloc(query, lcseries, &stsz);
06272 query = base_strcatalloc(query, " WHERE recnum in (SELECT recnum FROM ", &stsz);
06273 query = base_strcatalloc(query, lasttab, &stsz);
06274 query = base_strcatalloc(query, ")", &stsz);
06275
06276 if (npkwhere && *npkwhere)
06277 {
06278 query = base_strcatalloc(query, " AND ", &stsz);
06279 query = base_strcatalloc(query, npkwhere, &stsz);
06280 }
06281
06282 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06283 query = base_strcatalloc(query, pkeylist, &stsz);
06284 query = base_strcatalloc(query, " LIMIT ", &stsz);
06285 query = base_strcatalloc(query, limitstr, &stsz);
06286 }
06287
06288
06289 free(lasttab);
06290 lasttab = NULL;
06291
06292 free(pkeylist);
06293 pkeylist = NULL;
06294
06295 for (iloop = 0; iloop < npkeys; iloop++)
06296 {
06297 if (pkey[iloop])
06298 {
06299 free(pkey[iloop]);
06300 pkey[iloop] = NULL;
06301 }
06302 }
06303 }
06304 else
06305 {
06306 istat = DRMS_ERROR_OUTOFMEMORY;
06307 }
06308 }
06309 else
06310 {
06311 istat = DRMS_ERROR_OUTOFMEMORY;
06312 }
06313
06314 free(lcseries);
06315 lcseries = NULL;
06316 }
06317
06318 if (status)
06319 {
06320 *status = istat;
06321 }
06322
06323 return query;
06324 }
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347 char *drms_series_n_querystringA(DRMS_Env_t *env, const char *series, const char *fields, int nrecs, int limit, int *status)
06348 {
06349 char *query = NULL;
06350 int istat = DRMS_SUCCESS;
06351 size_t stsz = 8192;
06352 char *lcseries = NULL;
06353 int desc;
06354 char nrecsstr[32];
06355 char *qualfields = NULL;
06356 char *qualpkeylist = NULL;
06357 char *orderpkeylist = NULL;
06358
06359 char limitstr[32];
06360 char shadow[DRMS_MAXSERIESNAMELEN];
06361 char tabname[256];
06362
06363 desc = nrecs < 0;
06364
06365 lcseries = strdup(series);
06366
06367 if (lcseries)
06368 {
06369 strtolower(lcseries);
06370 query = malloc(stsz);
06371
06372 if (query)
06373 {
06374 *query = '\0';
06375
06376 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06377 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06378 snprintf(nrecsstr, sizeof(nrecsstr), "%d", abs(nrecs));
06379
06380
06381 qualfields = PrependFields(fields, "T.", &istat);
06382
06383
06384 qualpkeylist = CreatePKeyList(env, series, "T.", NULL, NULL, NULL, 0, &istat);
06385
06386
06387
06388 orderpkeylist = CreatePKeyList(env, series, NULL, desc ? " DESC" : NULL, NULL, NULL, 0, &istat);
06389
06390 if (istat == DRMS_SUCCESS)
06391 {
06392 if (GetTempTable(tabname, sizeof(tabname)))
06393 {
06394 istat = DRMS_ERROR_OVERFLOW;
06395 }
06396 }
06397
06398 if (istat == DRMS_SUCCESS)
06399 {
06400
06401 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
06402 query = base_strcatalloc(query, tabname, &stsz);
06403 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
06404 query = base_strcatalloc(query, shadow, &stsz);
06405 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06406 query = base_strcatalloc(query, orderpkeylist, &stsz);
06407 query = base_strcatalloc(query, " LIMIT ", &stsz);
06408
06409 if (limit < abs(nrecs))
06410 {
06411 query = base_strcatalloc(query, limitstr, &stsz);
06412 }
06413 else
06414 {
06415 query = base_strcatalloc(query, nrecsstr, &stsz);
06416 }
06417
06418 query = base_strcatalloc(query, ";\n", &stsz);
06419
06420
06421 query = base_strcatalloc(query, "SELECT ", &stsz);
06422 query = base_strcatalloc(query, qualfields, &stsz);
06423 query = base_strcatalloc(query, " FROM ", &stsz);
06424 query = base_strcatalloc(query, lcseries, &stsz);
06425 query = base_strcatalloc(query, " AS T WHERE T.recnum IN (SELECT recnum FROM ", &stsz);
06426 query = base_strcatalloc(query, tabname, &stsz);
06427 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
06428 query = base_strcatalloc(query, qualpkeylist, &stsz);
06429 }
06430
06431 free(orderpkeylist);
06432 orderpkeylist = NULL;
06433 free(qualpkeylist);
06434 qualpkeylist = NULL;
06435 free(qualfields);
06436 qualfields = NULL;
06437 }
06438 else
06439 {
06440 istat = DRMS_ERROR_OUTOFMEMORY;
06441 }
06442
06443 free(lcseries);
06444 lcseries = NULL;
06445 }
06446 else
06447 {
06448 istat = DRMS_ERROR_OUTOFMEMORY;
06449 }
06450
06451 if (status)
06452 {
06453 *status = istat;
06454 }
06455
06456 return query;
06457 }
06458
06459
06460
06461
06462
06463
06464
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487
06488
06489
06490
06491
06492
06493 char *drms_series_n_querystringB(DRMS_Env_t *env, const char *series, const char *npkwhere, const char *fields, int nrecs, int limit, int *status)
06494 {
06495 char *query = NULL;
06496 int istat = DRMS_SUCCESS;
06497 size_t stsz = 8192;
06498 char *lcseries = NULL;
06499 int desc;
06500 char nrecsstr[32];
06501 char *qualfields = NULL;
06502 char *qualpkeylist = NULL;
06503 char *orderpkeylist = NULL;
06504
06505 char *qualnpkwhere = NULL;
06506 char limitstr[32];
06507 char shadow[DRMS_MAXSERIESNAMELEN];
06508 char tabname[256];
06509
06510 desc = nrecs < 0;
06511
06512 lcseries = strdup(series);
06513
06514 if (lcseries)
06515 {
06516 strtolower(lcseries);
06517 query = malloc(stsz);
06518
06519 if (query)
06520 {
06521 *query = '\0';
06522
06523 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06524 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06525 snprintf(nrecsstr, sizeof(nrecsstr), "%d", abs(nrecs));
06526
06527 qualfields = PrependFields(fields, "T1.", &istat);
06528
06529
06530 qualpkeylist = CreatePKeyList(env, series, "T1.", NULL, NULL, NULL, 0, &istat);
06531
06532
06533
06534 orderpkeylist = CreatePKeyList(env, series, "T1.", desc ? " DESC" : NULL, NULL, NULL, 0, &istat);
06535
06536 if (istat == DRMS_SUCCESS)
06537 {
06538 if (GetTempTable(tabname, sizeof(tabname)))
06539 {
06540 istat = DRMS_ERROR_OVERFLOW;
06541 }
06542 }
06543
06544 if (istat == DRMS_SUCCESS)
06545 {
06546
06547 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
06548 query = base_strcatalloc(query, tabname, &stsz);
06549 query = base_strcatalloc(query, " AS SELECT T1.recnum, ", &stsz);
06550 query = base_strcatalloc(query, qualpkeylist, &stsz);
06551 query = base_strcatalloc(query, " FROM ", &stsz);
06552 query = base_strcatalloc(query, shadow, &stsz);
06553 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
06554 query = base_strcatalloc(query, lcseries, &stsz);
06555 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) WHERE ", &stsz);
06556
06557
06558
06559
06560
06561
06562
06563
06564 qualnpkwhere = PrependWhere(env, npkwhere, series, "T1.", &istat);
06565
06566 if (istat == DRMS_SUCCESS)
06567 {
06568 query = base_strcatalloc(query, qualnpkwhere, &stsz);
06569 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06570 query = base_strcatalloc(query, orderpkeylist, &stsz);
06571 query = base_strcatalloc(query, " LIMIT ", &stsz);
06572
06573 if (limit < abs(nrecs))
06574 {
06575 query = base_strcatalloc(query, limitstr, &stsz);
06576 }
06577 else
06578 {
06579 query = base_strcatalloc(query, nrecsstr, &stsz);
06580 }
06581
06582 query = base_strcatalloc(query, ";\n", &stsz);
06583
06584
06585 query = base_strcatalloc(query, "SELECT ", &stsz);
06586 query = base_strcatalloc(query, qualfields, &stsz);
06587 query = base_strcatalloc(query, " FROM ", &stsz);
06588 query = base_strcatalloc(query, lcseries, &stsz);
06589 query = base_strcatalloc(query, " AS T1 WHERE T1.recnum IN (SELECT recnum FROM ", &stsz);
06590 query = base_strcatalloc(query, tabname, &stsz);
06591 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
06592 query = base_strcatalloc(query, qualpkeylist, &stsz);
06593 }
06594 }
06595
06596 if (qualnpkwhere)
06597 {
06598 free(qualnpkwhere);
06599 qualnpkwhere = NULL;
06600 }
06601
06602 free(orderpkeylist);
06603 orderpkeylist = NULL;
06604 free(qualpkeylist);
06605 qualpkeylist = NULL;
06606 free(qualfields);
06607 qualfields = NULL;
06608 }
06609 else
06610 {
06611 istat = DRMS_ERROR_OUTOFMEMORY;
06612 }
06613
06614 free(lcseries);
06615 lcseries = NULL;
06616 }
06617 else
06618 {
06619 istat = DRMS_ERROR_OUTOFMEMORY;
06620 }
06621
06622 if (status)
06623 {
06624 *status = istat;
06625 }
06626
06627 return query;
06628 }
06629
06630
06631
06632
06633
06634
06635
06636
06637
06638
06639
06640
06641
06642
06643
06644
06645
06646
06647
06648
06649
06650
06651
06652 char *drms_series_n_querystringC(DRMS_Env_t *env, const char *series, const char *pkwhere, const char *fields, int nrecs, int limit, int *status)
06653 {
06654 char *query = NULL;
06655 int istat = DRMS_SUCCESS;
06656 size_t stsz = 8192;
06657 char *lcseries = NULL;
06658 int desc;
06659 char nrecsstr[32];
06660 char *qualfields = NULL;
06661 char *qualpkeylist = NULL;
06662 char *orderpkeylist = NULL;
06663
06664 char limitstr[32];
06665 char shadow[DRMS_MAXSERIESNAMELEN];
06666 char tabname[256];
06667
06668 desc = nrecs < 0;
06669
06670 lcseries = strdup(series);
06671
06672 if (lcseries)
06673 {
06674 strtolower(lcseries);
06675 query = malloc(stsz);
06676
06677 if (query)
06678 {
06679 *query = '\0';
06680
06681 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06682 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06683 snprintf(nrecsstr, sizeof(nrecsstr), "%d", abs(nrecs));
06684
06685
06686 qualfields = PrependFields(fields, "T.", &istat);
06687
06688
06689 qualpkeylist = CreatePKeyList(env, series, "T.", NULL, NULL, NULL, 0, &istat);
06690
06691
06692
06693 orderpkeylist = CreatePKeyList(env, series, NULL, desc ? " DESC" : NULL, NULL, NULL, 0, &istat);
06694
06695 if (istat == DRMS_SUCCESS)
06696 {
06697 if (GetTempTable(tabname, sizeof(tabname)))
06698 {
06699 istat = DRMS_ERROR_OVERFLOW;
06700 }
06701 }
06702
06703 if (istat == DRMS_SUCCESS)
06704 {
06705
06706 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
06707 query = base_strcatalloc(query, tabname, &stsz);
06708 query = base_strcatalloc(query, " AS SELECT recnum FROM ", &stsz);
06709 query = base_strcatalloc(query, shadow, &stsz);
06710 query = base_strcatalloc(query, " WHERE ", &stsz);
06711 query = base_strcatalloc(query, pkwhere, &stsz);
06712 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06713 query = base_strcatalloc(query, orderpkeylist, &stsz);
06714 query = base_strcatalloc(query, " LIMIT ", &stsz);
06715
06716 if (limit < abs(nrecs))
06717 {
06718 query = base_strcatalloc(query, limitstr, &stsz);
06719 }
06720 else
06721 {
06722 query = base_strcatalloc(query, nrecsstr, &stsz);
06723 }
06724
06725 query = base_strcatalloc(query, ";\n", &stsz);
06726
06727
06728 query = base_strcatalloc(query, "SELECT ", &stsz);
06729 query = base_strcatalloc(query, qualfields, &stsz);
06730 query = base_strcatalloc(query, " FROM ", &stsz);
06731 query = base_strcatalloc(query, lcseries, &stsz);
06732 query = base_strcatalloc(query, " AS T WHERE T.recnum IN (SELECT recnum FROM ", &stsz);
06733 query = base_strcatalloc(query, tabname, &stsz);
06734 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
06735 query = base_strcatalloc(query, qualpkeylist, &stsz);
06736 }
06737
06738 free(orderpkeylist);
06739 orderpkeylist = NULL;
06740 free(qualpkeylist);
06741 qualpkeylist = NULL;
06742 free(qualfields);
06743 qualfields = NULL;
06744 }
06745 else
06746 {
06747 istat = DRMS_ERROR_OUTOFMEMORY;
06748 }
06749
06750 free(lcseries);
06751 lcseries = NULL;
06752 }
06753 else
06754 {
06755 istat = DRMS_ERROR_OUTOFMEMORY;
06756 }
06757
06758 if (status)
06759 {
06760 *status = istat;
06761 }
06762
06763 return query;
06764 }
06765
06766
06767
06768
06769
06770
06771
06772
06773
06774
06775
06776
06777
06778
06779
06780
06781
06782
06783
06784
06785
06786
06787
06788
06789
06790
06791
06792
06793
06794
06795
06796
06797 char *drms_series_n_querystringD(DRMS_Env_t *env, const char *series, const char *pkwhere, const char *npkwhere, const char *fields, int nrecs, int limit, int *status)
06798 {
06799 char *query = NULL;
06800 int istat = DRMS_SUCCESS;
06801 size_t stsz = 8192;
06802 char *lcseries = NULL;
06803 int desc;
06804 char nrecsstr[32];
06805 char *qualfields = NULL;
06806 char *qualpkeylist = NULL;
06807 char *orderpkeylist = NULL;
06808
06809 char *qualpkwhere = NULL;
06810 char limitstr[32];
06811 char shadow[DRMS_MAXSERIESNAMELEN];
06812 char tabname[256];
06813
06814 desc = nrecs < 0;
06815
06816 lcseries = strdup(series);
06817
06818 if (lcseries)
06819 {
06820 strtolower(lcseries);
06821 query = malloc(stsz);
06822
06823 if (query)
06824 {
06825 *query = '\0';
06826
06827 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06828 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06829 snprintf(nrecsstr, sizeof(nrecsstr), "%d", abs(nrecs));
06830
06831
06832 qualfields = PrependFields(fields, "T1.", &istat);
06833
06834
06835 if (istat == DRMS_SUCCESS)
06836 {
06837 qualpkeylist = CreatePKeyList(env, series, "T1.", NULL, NULL, NULL, 0, &istat);
06838 }
06839
06840
06841
06842 if (istat == DRMS_SUCCESS)
06843 {
06844 orderpkeylist = CreatePKeyList(env, series, "T1.", desc ? " DESC" : NULL, NULL, NULL, 0, &istat);
06845 }
06846
06847 if (istat == DRMS_SUCCESS)
06848 {
06849 qualpkwhere = PrependWhere(env, pkwhere, series, "T1.", &istat);
06850 }
06851
06852 if (istat == DRMS_SUCCESS)
06853 {
06854 if (GetTempTable(tabname, sizeof(tabname)))
06855 {
06856 istat = DRMS_ERROR_OVERFLOW;
06857 }
06858 }
06859
06860 if (istat == DRMS_SUCCESS)
06861 {
06862
06863 query = base_strcatalloc(query, "CREATE TEMPORARY TABLE ", &stsz);
06864 query = base_strcatalloc(query, tabname, &stsz);
06865 query = base_strcatalloc(query, " AS SELECT T1.recnum, ", &stsz);
06866 query = base_strcatalloc(query, qualpkeylist, &stsz);
06867 query = base_strcatalloc(query, " FROM ", &stsz);
06868 query = base_strcatalloc(query, shadow, &stsz);
06869 query = base_strcatalloc(query, " AS T1 JOIN ", &stsz);
06870 query = base_strcatalloc(query, lcseries, &stsz);
06871 query = base_strcatalloc(query, " AS T2 ON (T1.recnum = T2.recnum) WHERE ", &stsz);
06872 query = base_strcatalloc(query, qualpkwhere, &stsz);
06873 query = base_strcatalloc(query, " AND ", &stsz);
06874 query = base_strcatalloc(query, npkwhere, &stsz);
06875 query = base_strcatalloc(query, " ORDER BY ", &stsz);
06876 query = base_strcatalloc(query, orderpkeylist, &stsz);
06877 query = base_strcatalloc(query, " LIMIT ", &stsz);
06878
06879 if (limit < abs(nrecs))
06880 {
06881 query = base_strcatalloc(query, limitstr, &stsz);
06882 }
06883 else
06884 {
06885 query = base_strcatalloc(query, nrecsstr, &stsz);
06886 }
06887
06888 query = base_strcatalloc(query, ";\n", &stsz);
06889
06890
06891 query = base_strcatalloc(query, "SELECT ", &stsz);
06892 query = base_strcatalloc(query, qualfields, &stsz);
06893 query = base_strcatalloc(query, " FROM ", &stsz);
06894 query = base_strcatalloc(query, lcseries, &stsz);
06895 query = base_strcatalloc(query, " AS T1 WHERE T1.recnum IN (SELECT recnum FROM ", &stsz);
06896 query = base_strcatalloc(query, tabname, &stsz);
06897 query = base_strcatalloc(query, ") ORDER BY ", &stsz);
06898 query = base_strcatalloc(query, qualpkeylist, &stsz);
06899 }
06900
06901 free(qualpkwhere);
06902 qualpkwhere = NULL;
06903 free(orderpkeylist);
06904 orderpkeylist = NULL;
06905 free(qualpkeylist);
06906 qualpkeylist = NULL;
06907 free(qualfields);
06908 qualfields = NULL;
06909 }
06910 else
06911 {
06912 istat = DRMS_ERROR_OUTOFMEMORY;
06913 }
06914
06915 free(lcseries);
06916 lcseries = NULL;
06917 }
06918 else
06919 {
06920 istat = DRMS_ERROR_OUTOFMEMORY;
06921 }
06922
06923 if (status)
06924 {
06925 *status = istat;
06926 }
06927
06928 return query;
06929 }
06930
06931
06932
06933
06934
06935
06936
06937
06938 char *drms_series_n_querystringFL(DRMS_Env_t *env, const char *series, const char *npkwhere, HContainer_t *pkwhereNFL, const char *fields, int nrecs, int limit, HContainer_t *firstlast, int *status)
06939 {
06940 char *lcseries = NULL;
06941 char *query = NULL;
06942 size_t stsz;
06943 char shadow[DRMS_MAXSERIESNAMELEN];
06944 char limitstr[32];
06945 char nrecsstr[32];
06946 char *pkey[DRMS_MAXPRIMIDX];
06947 int npkeys = 0;
06948 int desc;
06949 char *lasttab = NULL;
06950 int iloop;
06951 char *pkeylist = NULL;
06952 char *qualpkeylist = NULL;
06953 int istat = DRMS_SUCCESS;
06954
06955 desc = nrecs < 0;
06956 lcseries = strdup(series);
06957
06958 if (lcseries)
06959 {
06960 strtolower(lcseries);
06961 stsz = 2048;
06962 query = malloc(stsz);
06963
06964 if (query)
06965 {
06966 *query = '\0';
06967
06968 snprintf(shadow, sizeof(shadow), "%s%s", lcseries, kShadowSuffix);
06969 snprintf(limitstr, sizeof(limitstr), "%d", limit);
06970 snprintf(nrecsstr, sizeof(nrecsstr), "%d", abs(nrecs));
06971
06972 if (istat == DRMS_SUCCESS)
06973 {
06974 pkeylist = CreatePKeyList(env, series, NULL, NULL, pkey, &npkeys, 0, &istat);
06975
06976 if (istat == DRMS_SUCCESS)
06977 {
06978 istat = InnerFLSelect(npkeys, firstlast, &stsz, pkey, pkeylist, shadow, pkwhereNFL, &query, &lasttab);
06979 }
06980
06981 if (istat == DRMS_SUCCESS)
06982 {
06983 qualpkeylist = CreatePKeyList(env, series, NULL, desc ? " DESC" : NULL, NULL, NULL, 0, &istat);
06984 }
06985
06986 if (istat == DRMS_SUCCESS)
06987 {
06988
06989
06990
06991
06992 query = base_strcatalloc(query, ";\n", &stsz);
06993
06994 query = base_strcatalloc(query, "SELECT ", &stsz);
06995 query = base_strcatalloc(query, fields, &stsz);
06996 query = base_strcatalloc(query, " FROM ", &stsz);
06997 query = base_strcatalloc(query, lcseries, &stsz);
06998 query = base_strcatalloc(query, " WHERE recnum in (SELECT recnum FROM ", &stsz);
06999 query = base_strcatalloc(query, lasttab, &stsz);
07000 query = base_strcatalloc(query, ")", &stsz);
07001
07002 if (npkwhere && *npkwhere)
07003 {
07004 query = base_strcatalloc(query, " AND ", &stsz);
07005 query = base_strcatalloc(query, npkwhere, &stsz);
07006 }
07007
07008 query = base_strcatalloc(query, " ORDER BY ", &stsz);
07009 query = base_strcatalloc(query, qualpkeylist, &stsz);
07010 query = base_strcatalloc(query, " LIMIT ", &stsz);
07011
07012 if (limit < abs(nrecs))
07013 {
07014 query = base_strcatalloc(query, limitstr, &stsz);
07015 }
07016 else
07017 {
07018 query = base_strcatalloc(query, nrecsstr, &stsz);
07019 }
07020 }
07021
07022
07023 free(qualpkeylist);
07024 qualpkeylist = NULL;
07025
07026 free(lasttab);
07027 lasttab = NULL;
07028
07029 free(pkeylist);
07030 pkeylist = NULL;
07031
07032 for (iloop = 0; iloop < npkeys; iloop++)
07033 {
07034 if (pkey[iloop])
07035 {
07036 free(pkey[iloop]);
07037 pkey[iloop] = NULL;
07038 }
07039 }
07040 }
07041 }
07042 }
07043
07044 if (status)
07045 {
07046 *status = istat;
07047 }
07048
07049 return query;
07050 }
07051
07052 int drms_series_summaryexists(DRMS_Env_t *env, const char *series, int *status)
07053 {
07054 #if (defined TOC && TOC)
07055 int istat = DRMS_SUCCESS;
07056 int tocexists = -1;
07057 int shadowexists = -1;
07058 int summexists = -1;
07059
07060 tocexists = TocExists(env, &istat);
07061
07062 if (istat == DRMS_SUCCESS)
07063 {
07064 if (tocexists)
07065 {
07066 int present = IsSeriesPresent(env, kTableOfCountsNS, kTableOfCountsTab, series, &istat);
07067
07068 if (istat == DRMS_SUCCESS)
07069 {
07070 summexists = present ? 1 : 0;
07071 }
07072 }
07073 else
07074 {
07075 summexists = 0;
07076 }
07077 }
07078
07079 if (istat == DRMS_SUCCESS)
07080 {
07081 if (!summexists)
07082 {
07083 shadowexists = ShadowExists(env, series, &istat);
07084
07085 if (istat == DRMS_SUCCESS)
07086 {
07087 summexists = shadowexists ? 1 : 0;
07088 }
07089 else
07090 {
07091 summexists = -1;
07092 }
07093 }
07094 }
07095
07096 if (status)
07097 {
07098 *status = istat;
07099 }
07100
07101 return summexists;
07102 #else
07103
07104 int istat = DRMS_SUCCESS;
07105 int shadowexists = -1;
07106 int summexists = -1;
07107
07108 shadowexists = ShadowExists(env, series, &istat);
07109
07110 if (istat == DRMS_SUCCESS)
07111 {
07112 summexists = shadowexists ? 1 : 0;
07113 }
07114 else
07115 {
07116 summexists = -1;
07117 }
07118
07119 if (status)
07120 {
07121 *status = istat;
07122 }
07123
07124 return summexists;
07125
07126 #endif
07127 }
07128
07129 int drms_series_canupdatesummaries(DRMS_Env_t *env, const char *series, int *status)
07130 {
07131
07132
07133
07134
07135
07136
07137
07138
07139 return 1;
07140 }
07141
07142
07143 int drms_series_hastemptab(const char *query)
07144 {
07145 int rv = -1;
07146 const char *pat = "CREATE[:space:]+TEMPORARY[:space:]+TABLE[:space:]+shadowtemp";
07147 regex_t regexp;
07148
07149 if (regcomp(®exp, pat, (REG_EXTENDED | REG_ICASE)) != 0)
07150 {
07151 fprintf(stderr, "Bad regular expression '%s'.\n", pat);
07152 }
07153 else
07154 {
07155 if (regexec(®exp, query, 0, NULL, 0) == 0)
07156 {
07157
07158 rv = 1;
07159 }
07160 else
07161 {
07162 rv = 0;
07163 }
07164
07165 regfree(®exp);
07166 }
07167
07168 return rv;
07169 }
07170
07171 int16_t drms_series_getstagingretention(DRMS_SeriesInfo_t *si)
07172 {
07173 if (si && si->seriesname && *si->seriesname)
07174 {
07175 return (int16_t)((si->retention >> 16) & 0x00007FFF);
07176 }
07177
07178 return INT16_MIN;
07179 }
07180
07181 int16_t drms_series_getnewsuretention(DRMS_SeriesInfo_t *si)
07182 {
07183 if (si && si->seriesname && *si->seriesname)
07184 {
07185 return (int16_t)(si->retention & 0x00007FFF);
07186 }
07187
07188 return INT16_MIN;
07189 }