/* * Legal Notice * * This document and associated source code (the "Work") is a part of a * benchmark specification maintained by the TPC. * * The TPC reserves all right, title, and interest to the Work as provided * under U.S. and international laws, including without limitation all patent * and trademark rights therein. * * No Warranty * * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY, * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES, * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE. * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT, * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT * WITH REGARD TO THE WORK. * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT, * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY, * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. * * Contributors: * Gradient Systems */ #include "config.h" #include "porting.h" #include "tpcds_idx.hpp" #include #include #include #ifdef _WIN32 #include #include #include #include #else #include #include #include #endif #ifdef NCR #include #endif #ifndef USE_STDLIB_H #include #endif #include "config.h" #include "date.h" #include "dcomp.h" #include "decimal.h" #include "dist.h" #include "error_msg.h" #include "genrand.h" #include "r_params.h" #ifdef TEST option_t options[] = {{"DISTRIBUTIONS", OPT_STR, 2, "read distributions from file ", NULL, "tester_dist.idx"}, NULL}; char params[2]; struct { char *name; } tdefs[] = {NULL}; #endif /* NOTE: these need to be in sync with a_dist.h */ #define D_NAME_LEN 20 #define FL_LOADED 0x01 static int load_dist(d_idx_t *d); /* * Routine: di_compare() * Purpose: comparison routine for two d_idx_t entries; used by qsort * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int di_compare(const void *op1, const void *op2) { d_idx_t *ie1 = (d_idx_t *)op1, *ie2 = (d_idx_t *)op2; return (strcasecmp(ie1->name, ie2->name)); } /* * Routine: find_dist(char *name) * Purpose: translate from dist_t name to d_idx_t * * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ d_idx_t *find_dist(const char *name) { static int entry_count; static d_idx_t *idx = NULL; d_idx_t key, *id = NULL; int i; FILE *ifp; int32_t temp; /* load the index if this is the first time through */ if (!InitConstants::find_dist_init) { /* make sure that this is read one thread at a time */ if (!InitConstants::find_dist_init) /* make sure no one beat us to it */ { /* open the dist file */ auto read_ptr = tpcds_idx; // if ((ifp = fopen(get_str("DISTRIBUTIONS"), "rb")) == NULL) { // fprintf(stderr, "Error: open of distributions failed: "); // perror(get_str("DISTRIBUTIONS")); // exit(1); // } memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read of index count failed: "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } entry_count = ntohl(temp); read_ptr = tpcds_idx + tpcds_idx_len - (entry_count * IDX_SIZE); // if ((temp = fseek(ifp, -entry_count * IDX_SIZE, SEEK_END)) < 0) { // fprintf(stderr, "Error: lseek to index failed: "); // fprintf(stderr, "attempting to reach %d\nSystem error: ", (int)(-entry_count * IDX_SIZE)); // perror(get_str("DISTRIBUTIONS")); // exit(3); // } idx = (d_idx_t *)malloc(entry_count * sizeof(d_idx_t)); MALLOC_CHECK(idx); for (i = 0; i < entry_count; i++) { memset(idx + i, 0, sizeof(d_idx_t)); // if (fread(idx[i].name, 1, D_NAME_LEN, ifp) < D_NAME_LEN) { // fprintf(stderr, "Error: read index failed (1): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } memcpy(idx[i].name, read_ptr, D_NAME_LEN); read_ptr += D_NAME_LEN; idx[i].name[D_NAME_LEN] = '\0'; memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (2): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].index = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (4): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].offset = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (5): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].str_space = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (6): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].length = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (7): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].w_width = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (8): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].v_width = ntohl(temp); memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read index failed (9): "); // perror(get_str("DISTRIBUTIONS")); // exit(2); // } idx[i].name_space = ntohl(temp); idx[i].dist = NULL; } qsort((void *)idx, entry_count, sizeof(d_idx_t), di_compare); InitConstants::find_dist_init = 1; /* make sure that this is read one thread at a time */ // fclose(ifp); } } /* find the distribution, if it exists and move to it */ strcpy(key.name, name); id = (d_idx_t *)bsearch((void *)&key, (void *)idx, entry_count, sizeof(d_idx_t), di_compare); if (id != NULL) /* found a valid distribution */ if (id->flags != FL_LOADED) /* but it needs to be loaded */ load_dist(id); return (id); } /* * Routine: load_dist(int fd, dist_t *d) * Purpose: load a particular distribution * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ static int load_dist(d_idx_t *di) { int res = 0, i, j; dist_t *d; int32_t temp; FILE *ifp; if (di->flags != FL_LOADED) /* make sure no one beat us to it */ { auto read_ptr = tpcds_idx; // if ((ifp = fopen(get_str("DISTRIBUTIONS"), "rb")) == NULL) { // fprintf(stderr, "Error: open of distributions failed: "); // perror(get_str("DISTRIBUTIONS")); // exit(1); // } read_ptr += di->offset; // if ((temp = fseek(ifp, di->offset, SEEK_SET)) < 0) { // fprintf(stderr, "Error: lseek to distribution failed: "); // perror("load_dist()"); // exit(2); // } di->dist = (dist_t *)malloc(sizeof(struct DIST_T)); MALLOC_CHECK(di->dist); d = di->dist; // fprintf(stderr, "\ndist %s ", di->name); /* load the type information */ d->type_vector = (int *)malloc(sizeof(int32_t) * di->v_width); MALLOC_CHECK(d->type_vector); for (i = 0; i < di->v_width; i++) { memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read of type vector failed for '%s': ", di->name); // perror("load_dist()"); // exit(3); // } d->type_vector[i] = ntohl(temp); // fprintf(stderr, "type %d, ", d->type_vector[i]); } /* load the weights */ d->weight_sets = (int **)malloc(sizeof(int *) * di->w_width); d->maximums = (int *)malloc(sizeof(int32_t) * di->w_width); MALLOC_CHECK(d->weight_sets); MALLOC_CHECK(d->maximums); for (i = 0; i < di->w_width; i++) { *(d->weight_sets + i) = (int *)malloc(di->length * sizeof(int32_t)); MALLOC_CHECK(*(d->weight_sets + i)); d->maximums[i] = 0; for (j = 0; j < di->length; j++) { memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) < 0) { // fprintf(stderr, "Error: read of weights failed: "); // perror("load_dist()"); // exit(3); // } *(*(d->weight_sets + i) + j) = ntohl(temp); /* calculate the maximum weight and convert sets to cummulative */ d->maximums[i] += d->weight_sets[i][j]; d->weight_sets[i][j] = d->maximums[i]; } } /* load the value offsets */ d->value_sets = (int **)malloc(sizeof(int *) * di->v_width); MALLOC_CHECK(d->value_sets); for (i = 0; i < di->v_width; i++) { *(d->value_sets + i) = (int *)malloc(di->length * sizeof(int32_t)); MALLOC_CHECK(*(d->value_sets + i)); for (j = 0; j < di->length; j++) { memcpy(&temp, read_ptr, sizeof(int32_t)); read_ptr += sizeof(int32_t); // if (fread(&temp, 1, sizeof(int32_t), ifp) != sizeof(int32_t)) { // fprintf(stderr, "Error: read of values failed: "); // perror("load_dist()"); // exit(4); // } *(*(d->value_sets + i) + j) = ntohl(temp); } } /* load the column aliases, if they were defined */ if (di->name_space) { d->names = (char *)malloc(di->name_space); MALLOC_CHECK(d->names); memcpy(d->names, read_ptr, di->name_space * sizeof(char)); read_ptr += di->name_space * sizeof(char); // if (fread(d->names, 1, di->name_space * sizeof(char), ifp) < 0) { // fprintf(stderr, "Error: read of names failed: "); // perror("load_dist()"); // exit(599); // } } /* and finally the values themselves */ d->strings = (char *)malloc(sizeof(char) * di->str_space); MALLOC_CHECK(d->strings); memcpy(d->strings, read_ptr, di->str_space * sizeof(char)); read_ptr += di->str_space * sizeof(char); // if (fread(d->strings, 1, di->str_space * sizeof(char), ifp) < 0) { // fprintf(stderr, "Error: read of strings failed: "); // perror("load_dist()"); // exit(5); // } // fclose(ifp); // // fprintf(stderr, "%s {\n", di->name); // // // type_vector // fprintf(stderr, "{"); // // for (int i = 0 ; i < di->v_width; i++) { // fprintf(stderr, "%d", d->type_vector[i]); // // if (i < di->v_width-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // //// weight_sets // fprintf(stderr, "{"); // for (int i = 0 ; i < di->w_width; i++) { // fprintf(stderr, "{"); // // for (int j = 0 ; j < di->length; j++) { // // fprintf(stderr, "%d", d->weight_sets[i][j]); // // // // if (j < di->length-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // if (i < di->w_width-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // maximums // fprintf(stderr, "{"); // // for (int i = 0 ; i < di->w_width; i++) { // fprintf(stderr, "%d", d->maximums[i]); // // if (i < di->w_width-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // // value sets // fprintf(stderr, "{"); // for (int i = 0 ; i < di->v_width; i++) { // fprintf(stderr, "{"); // // for (int j = 0 ; j < di->length; j++) { // // fprintf(stderr, "%d", d->value_sets[i][j]); // // // // if (j < di->length-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // if (i < di->v_width-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // //// strings // // // fprintf(stderr, "{"); // // for (int i = 0 ; i < di->str_space; i++) { // fprintf(stderr, "%d", (int) d->strings[i]); // // if (i < di->str_space-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // // names // // fprintf(stderr, "{"); // // for (int i = 0 ; i < di->name_space; i++) { // fprintf(stderr, "%d", (int) d->names[i]); // // if (i < di->name_space-1) { // fprintf(stderr, ", "); // // } // } // fprintf(stderr, "},"); // // // // // size // fprintf(stderr, "%d}\n", d->size); di->flags = FL_LOADED; } return (res); } /* * Routine: void *dist_op() * Purpose: select a value/weight from a distribution * Algorithm: * Data Structures: * * Params: char *d_name * int vset: which set of values * int wset: which set of weights * Returns: appropriate data type cast as a void * * Called By: * Calls: * Assumptions: * Side Effects: * TODO: 20000317 Need to be sure this is portable to NT and others */ int dist_op(void *dest, int op, const char *d_name, int vset, int wset, int stream) { d_idx_t *d; dist_t *dist; int level, index = 0, dt; char *char_val; int i_res = 1; if ((d = find_dist(d_name)) == NULL) { char msg[80]; sprintf(msg, "Invalid distribution name '%s'", d_name); INTERNAL(msg); assert(d != NULL); } dist = d->dist; if (op == 0) { genrand_integer(&level, DIST_UNIFORM, 1, dist->maximums[wset - 1], 0, stream); while (level > dist->weight_sets[wset - 1][index] && index < d->length) index += 1; dt = vset - 1; if ((index >= d->length) || (dt > d->v_width)) INTERNAL("Distribution overrun"); char_val = dist->strings + dist->value_sets[dt][index]; } else { index = vset - 1; dt = wset - 1; if (index >= d->length || index < 0) { fprintf(stderr, "Runtime ERROR: Distribution over-run/under-run\n"); fprintf(stderr, "Check distribution definitions and usage for %s.\n", d->name); fprintf(stderr, "index = %d, length=%d.\n", index, d->length); exit(1); } char_val = dist->strings + dist->value_sets[dt][index]; } switch (dist->type_vector[dt]) { case TKN_VARCHAR: if (dest) *(char **)dest = (char *)char_val; break; case TKN_INT: i_res = atoi(char_val); if (dest) *(int *)dest = i_res; break; case TKN_DATE: if (dest == NULL) { dest = (date_t *)malloc(sizeof(date_t)); MALLOC_CHECK(dest); } strtodt(*(date_t **)dest, char_val); break; case TKN_DECIMAL: if (dest == NULL) { dest = (decimal_t *)malloc(sizeof(decimal_t)); MALLOC_CHECK(dest); } strtodec(*(decimal_t **)dest, char_val); break; } return ((dest == NULL) ? i_res : index + 1); /* shift back to the 1-based indexing scheme */ } /* * Routine: int dist_weight * Purpose: return the weight of a particular member of a distribution * Algorithm: * Data Structures: * * Params: distribution *d * int index: which "row" * int wset: which set of weights * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: * 20000405 need to add error checking */ int dist_weight(int *dest, const char *d, int index, int wset) { d_idx_t *d_idx; dist_t *dist; int res; if ((d_idx = find_dist(d)) == NULL) { char msg[80]; sprintf(msg, "Invalid distribution name '%s'", d); INTERNAL(msg); } dist = d_idx->dist; assert(index > 0); assert(wset > 0); res = dist->weight_sets[wset - 1][index - 1]; /* reverse the accumulation of weights */ if (index > 1) res -= dist->weight_sets[wset - 1][index - 2]; if (dest == NULL) return (res); *dest = res; return (0); } /* * Routine: int DistNameIndex() * Purpose: return the index of a column alias * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: */ int DistNameIndex(const char *szDist, int nNameType, const char *szName) { d_idx_t *d_idx; dist_t *dist; int res; char *cp = NULL; if ((d_idx = find_dist(szDist)) == NULL) return (-1); dist = d_idx->dist; if (dist->names == NULL) return (-1); res = 0; cp = dist->names; do { if (strcasecmp(szName, cp) == 0) break; cp += strlen(cp) + 1; res += 1; } while (res < (d_idx->v_width + d_idx->w_width)); if (res >= 0) { if ((nNameType == VALUE_NAME) && (res < d_idx->v_width)) return (res + 1); if ((nNameType == WEIGHT_NAME) && (res > d_idx->v_width)) return (res - d_idx->v_width + 1); } return (-1); } /* * Routine: int distsize(char *name) * Purpose: return the size of a distribution * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: * 20000405 need to add error checking */ int distsize(const char *name) { d_idx_t *dist; dist = find_dist(name); if (dist == NULL) return (-1); return (dist->length); } /* * Routine: int IntegrateDist(char *szDistName, int nPct, int nStartIndex, int *nWeightSet) Purpose: return the index of the entry which, starting from *nStartIndex, would create a range comprising nPct of the total contained in *nWeightSet NOTE: the value can "wrap" -- that is, the returned value can be *less than nStartIndex Algorithm: Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: */ int IntegrateDist(const char *szDistName, int nPct, int nStartIndex, int nWeightSet) { d_idx_t *pDistIndex; int nGoal, nSize; if ((nPct <= 0) || (nPct >= 100)) return (QERR_RANGE_ERROR); pDistIndex = find_dist(szDistName); if (pDistIndex == NULL) return (QERR_BAD_NAME); if (nStartIndex > pDistIndex->length) return (QERR_RANGE_ERROR); nGoal = pDistIndex->dist->maximums[nWeightSet]; nGoal = nGoal * nPct / 100; nSize = distsize(szDistName); while (nGoal >= 0) { nStartIndex++; nGoal -= dist_weight(NULL, szDistName, nStartIndex % nSize, nWeightSet); } return (nStartIndex); } /* * Routine: int dist_type(char *name, int nValueSet) * Purpose: return the type of the n-th value set in a distribution * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: */ int dist_type(const char *name, int nValueSet) { d_idx_t *dist; dist = find_dist(name); if (dist == NULL) return (-1); if (nValueSet < 1 || nValueSet > dist->v_width) return (-1); return (dist->dist->type_vector[nValueSet - 1]); } /* * Routine: * Purpose: * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ void dump_dist(const char *name) { d_idx_t *pIndex; int i, j; char *pCharVal = NULL; int nVal; pIndex = find_dist(name); if (pIndex == NULL) ReportErrorNoLine(QERR_BAD_NAME, name, 1); printf("create %s;\n", pIndex->name); printf("set types = ("); for (i = 0; i < pIndex->v_width; i++) { if (i > 0) printf(", "); printf("%s", dist_type(name, i + 1) == 7 ? "int" : "varchar"); } printf(");\n"); printf("set weights = %d;\n", pIndex->w_width); for (i = 0; i < pIndex->length; i++) { printf("add("); for (j = 0; j < pIndex->v_width; j++) { if (j) printf(", "); if (dist_type(name, j + 1) != 7) { dist_member(&pCharVal, name, i + 1, j + 1); printf("\"%s\"", pCharVal); } else { dist_member(&nVal, name, i + 1, j + 1); printf("%d", nVal); } } printf("; "); for (j = 0; j < pIndex->w_width; j++) { if (j) printf(", "); printf("%d", dist_weight(NULL, name, i + 1, j + 1)); } printf(");\n"); } return; } /* * Routine: dist_active(char *szName, int nWeightSet) * Purpose: return number of entries with non-zero weght values * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int dist_active(const char *szName, int nWeightSet) { int nSize, nResult = 0, i; nSize = distsize(szName); for (i = 1; i <= nSize; i++) { if (dist_weight(NULL, szName, i, nWeightSet) != 0) nResult += 1; } return (nResult); } /* * Routine: DistSizeToShiftWidth(char *szDist) * Purpose: Determine the number of bits required to select a member of the * distribution Algorithm: Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int DistSizeToShiftWidth(const char *szDist, int nWeightSet) { int nBits = 1, nTotal = 2, nMax; d_idx_t *d; d = find_dist(szDist); nMax = dist_max(d->dist, nWeightSet); while (nTotal < nMax) { nBits += 1; nTotal <<= 1; } return (nBits); } /* * Routine: * Purpose: * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: None */ int MatchDistWeight(void *dest, const char *szDist, int nWeight, int nWeightSet, int ValueSet) { d_idx_t *d; dist_t *dist; int index = 0, dt, i_res, nRetcode; char *char_val; if ((d = find_dist(szDist)) == NULL) { char msg[80]; sprintf(msg, "Invalid distribution name '%s'", szDist); INTERNAL(msg); } dist = d->dist; nWeight %= dist->maximums[nWeightSet - 1]; while (nWeight > dist->weight_sets[nWeightSet - 1][index] && index < d->length) index += 1; dt = ValueSet - 1; if (index >= d->length) index = d->length - 1; char_val = dist->strings + dist->value_sets[dt][index]; switch (dist->type_vector[dt]) { case TKN_VARCHAR: if (dest) *(char **)dest = (char *)char_val; break; case TKN_INT: i_res = atoi(char_val); if (dest) *(int *)dest = i_res; break; case TKN_DATE: if (dest == NULL) { dest = (date_t *)malloc(sizeof(date_t)); MALLOC_CHECK(dest); } strtodt(*(date_t **)dest, char_val); break; case TKN_DECIMAL: if (dest == NULL) { dest = (decimal_t *)malloc(sizeof(decimal_t)); MALLOC_CHECK(dest); } strtodec(*(decimal_t **)dest, char_val); break; } nRetcode = 1; index = 1; while (index < dist->maximums[nWeightSet - 1]) { nRetcode += 1; index *= 2; } return (nRetcode); } /* * Routine: findDistValue(char *szValue, char *szDistName, int nValueSet) * Purpose: Return the row number where the entry is found * Algorithm: * Data Structures: * * Params: * Returns: * Called By: * Calls: * Assumptions: * Side Effects: * TODO: * 20031024 jms this routine needs to handle all data types, not just varchar */ int findDistValue(const char *szValue, const char *szDistName, int ValueSet) { int nRetValue = 1, nDistMax; char szDistValue[128]; nDistMax = distsize(szDistName); for (nRetValue = 1; nRetValue < nDistMax; nRetValue++) { dist_member(&szDistValue, szDistName, nRetValue, ValueSet); if (strcmp(szValue, szDistValue) == 0) break; } if (nRetValue <= nDistMax) return (nRetValue); return (-1); } #ifdef TEST main() { int i_res; char *c_res; decimal_t dec_res; init_params(); dist_member(&i_res, "test_dist", 1, 1); if (i_res != 10) { printf("dist_member(\"test_dist\", 1, 1): %d != 10\n", i_res); exit(1); } dist_member(&i_res, "test_dist", 1, 2); if (i_res != 60) { printf("dist_member(\"test_dist\", 1, 2): %d != 60\n", i_res); exit(1); } dist_member((void *)&c_res, "test_dist", 1, 3); if (strcmp(c_res, "El Camino")) { printf("dist_member(\"test_dist\", 1, 3): %s != El Camino\n", c_res); exit(1); } dist_member((void *)&dec_res, "test_dist", 1, 4); if (strcmp(dec_res.number, "1") || strcmp(dec_res.fraction, "23")) { printf("dist_member(\"test_dist\", 1, 4): %s.%s != 1.23\n", dec_res.number, dec_res.fraction); exit(1); } dist_weight(&i_res, "test_dist", 2, 2); if (3 != i_res) { printf("dist_weight(\"test_dist\", 2, 2): %d != 3\n", i_res); exit(1); } } #endif /* TEST */