/** * @author Dino Laktašić. * @brief Break conjunctive conditions to individual conditions * (currently not used - commented in main AK_rel_eq_selection function), it can be usefull in some optimization cases * <ol> * <li>For each delimited item (' AND ') insert item to the struct list_node</li> * <li>Remove unused pointers and return the conditions list</li> * </ol> * @param *cond condition expression * @result conditions list */ struct list_node *AK_rel_eq_split_condition(char *cond) { AK_PRO; struct list_node *list_attr = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&list_attr); int token_id = 0; int attr_address = 0; int len_token; char *token_cond, *save_token_cond; //it's much safe to allocate MAX_VARCHAR_LENGHT, and remove all AK_realloc from function char *temp_attr = (char *) AK_calloc(1, sizeof (char)); //memset(temp_attr, '\0', MAX_VARCHAR_LENGHT); char *temp_cond = (char *) AK_calloc(strlen(cond), sizeof (char)); memcpy(temp_cond, cond, strlen(cond)); for ((token_cond = strtok_r(temp_cond, " ", &save_token_cond)); token_cond; (token_cond = strtok_r(NULL, " ", &save_token_cond)), token_id++) { if (token_id < MAX_TOKENS - 1) { len_token = strlen(token_cond); if (strcmp(token_cond, "AND") == 0) { Ak_InsertAtEnd_L3(TYPE_CONDITION, temp_attr, strlen(temp_attr), list_attr); attr_address = 0; AK_free(temp_attr); temp_attr = (char *) AK_calloc(1, sizeof (char)); } else { if (attr_address > 0) { temp_attr = (char *) AK_realloc(temp_attr, attr_address + len_token + 2); //memcpy(temp_attr + attr_address, " ", 1); strcpy(temp_attr + attr_address, " "); //memcpy(temp_attr + ++attr_address, "\0", 1); attr_address++; } else { temp_attr = (char *) AK_realloc(temp_attr, attr_address + len_token + 1); } strcpy(temp_attr + attr_address, token_cond); //memcpy(temp_attr + attr_address, token_cond, len_token); attr_address += len_token; } } } //memcpy(temp_attr + attr_address, "\0", 1); Ak_InsertAtEnd_L3(TYPE_CONDITION, temp_attr, strlen(temp_attr), list_attr); AK_free(temp_cond); AK_free(temp_attr); AK_EPI; return list_attr; }
/** * @author Dino Laktašić. * @brief Function for filtering and returning attributes from condition * @param *cond condition array that contains condition data * @result pointer to array that contains attributes for a given condition */ char *AK_rel_eq_cond_attributes(char *cond) { int next_chr = 0; int next_address = 0; int attr_end = -1; AK_PRO; if (cond == NULL) { AK_EPI; return NULL; } char *temp_cond = (char *) AK_malloc(strlen(cond)); memcpy(temp_cond, cond, strlen(cond)); char *attr = (char *) AK_malloc(sizeof (char)); while (next_chr < strlen(cond)) { if (temp_cond[next_chr] == ATTR_ESCAPE) { next_chr++; if (++attr_end) { attr_end = -1; } else { if (next_address > 0) { memcpy(attr + next_address++, ATTR_DELIMITER, 1); attr = (char *) AK_realloc(attr, next_address + 1); } } } if (!attr_end) { memcpy(attr + next_address++, &temp_cond[next_chr], 1); attr = (char *) AK_realloc(attr, next_address + 1); } next_chr++; } AK_free(temp_cond); if (next_address > 0) { memcpy(attr + next_address, "\0", 1); AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } }
char* AK_get_table_atribute_types(char* tblName){ int len_attr, num_attr, next_attr, attr_type; int next_address = 0; char attr_buffer[4]; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == EXIT_WARNING) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_type = (table_header + next_attr)->type; len_attr = sprintf(attr_buffer,"%d",attr_type); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_buffer, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } AK_EPI; }
/** * @author Dino Laktašić. * @brief Get attributes for a given table and store them to the char array * <ol> * <li>Get the number of attributes in a given table</li> * <li>If there is no attributes return NULL</li> * <li>Get the table header for a given table</li> * <li>Initialize struct list_node</li> * <li>For each attribute in table header, insert attribute in the array</li> * <li>Delimit each new attribute with ";" (ATTR_DELIMITER)</li> * <li>return pointer to char array</li> * </ol> * @param *tblName name of the table * @result pointer to char array */ char *AK_rel_eq_get_atrributes_char(char *tblName) { int len_attr, num_attr, next_attr; int next_address = 0; char *attr_name; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == -1) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_name = (table_header + next_attr)->att_name; len_attr = strlen(attr_name); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_name, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } }
search_result AK_search_unsorted(char *szRelation, search_params *aspParams, int iNum_search_params) { AK_PRO; AK_flush_cache(); int iBlock; AK_mem_block *mem_block = NULL, tmp; int i, j, k; int iTupleMatches; search_result srResult; table_addresses *taAddresses; srResult.aiTuple_addresses = NULL; srResult.iNum_tuple_addresses = 0; srResult.aiSearch_attributes = NULL; srResult.aiBlocks = NULL; if (aspParams == NULL || iNum_search_params == 0){ AK_EPI; return srResult; } taAddresses = AK_get_table_addresses(szRelation); /// iterate through all the blocks for (k = 0; k < MAX_EXTENTS_IN_SEGMENT && taAddresses->address_from[k] > 0; k++) { // 200 == Novak's magic number :) for (iBlock = taAddresses->address_from[k]; iBlock <= taAddresses->address_to[k]; iBlock++) { //mem_block = AK_get_block(iBlock); mem_block = &tmp; mem_block->block = AK_read_block(iBlock); /// count number of attributes in segment/relation srResult.iNum_tuple_attributes = 0; for (i = 0; i < MAX_ATTRIBUTES; i++) { if (mem_block->block->header[i].att_name[0] == FREE_CHAR) break; srResult.iNum_tuple_attributes++; } srResult.aiSearch_attributes = (int *) AK_malloc(iNum_search_params * sizeof (int)); if (srResult.aiSearch_attributes == NULL) { printf("AK_search_unsorted: ERROR. Cannot allocate srResult.aiAttributes_searched.\n"); AK_EPI; exit(EXIT_ERROR); } srResult.iNum_search_attributes = 0; /// determine index of attributes on which search will be performed for (j = 0; j < iNum_search_params; j++) { for (i = 0; i < MAX_ATTRIBUTES; i++) { if (!strcmp(mem_block->block->header[i].att_name, aspParams[j].szAttribute)) { srResult.aiSearch_attributes[j] = i; srResult.iNum_search_attributes++; break; } } } /// if any of the provided attributes are not found in the relation, return empty result if (srResult.iNum_search_attributes != iNum_search_params) return srResult; /// in every tuple, for all required attributes, compare attribute value with searched-for value and store matched tuple addresses for (i = 0; i < DATA_BLOCK_SIZE && mem_block->block->tuple_dict[i].type != FREE_INT; i += srResult.iNum_tuple_attributes) { iTupleMatches = 1; for (j = 0; j < iNum_search_params && iTupleMatches; j++) { switch (aspParams[j].iSearchType) { case SEARCH_PARTICULAR: { size_t iSearchAttributeValueSize = AK_type_size(mem_block->block->header[srResult.aiSearch_attributes[j]].type, (char *) aspParams[j].pData_lower); if (mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].size != iSearchAttributeValueSize || memcmp(mem_block->block->data + mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].address, aspParams[j].pData_lower, iSearchAttributeValueSize)) { iTupleMatches = 0; } } break; case SEARCH_RANGE: { switch (mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].type) { case TYPE_INT: case TYPE_DATE: case TYPE_DATETIME: case TYPE_TIME: { int iAttributeValue = *((int *) (mem_block->block->data + mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].address)); if (iAttributeValue < *((int *) aspParams[j].pData_lower) || iAttributeValue > *((int *) aspParams[j].pData_upper)) { iTupleMatches = 0; } } break; case TYPE_FLOAT: case TYPE_NUMBER: if (*((double *) (mem_block->block->data + mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].address)) < *((double *) aspParams[j].pData_lower) || *((double *) (mem_block->block->data + mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].address)) > *((double *) aspParams[j].pData_upper)) { iTupleMatches = 0; } break; default: // other types unsupported iTupleMatches = 0; } } break; case SEARCH_ALL: // iTupleMatches is already == 1, no action needed break; case SEARCH_NULL: { size_t iSearchAttributeValueSize = AK_type_size(mem_block->block->header[srResult.aiSearch_attributes[j]].type, (char *) aspParams[j].pData_lower); if (mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].type != TYPE_VARCHAR || iSearchAttributeValueSize != strlen("NULL") || memcmp(mem_block->block->data + mem_block->block->tuple_dict[i + srResult.aiSearch_attributes[j]].address, "NULL", strlen("NULL"))) iTupleMatches = 0; } break; default: iTupleMatches = 0; } } if (iTupleMatches) { /*if(DEBUG) { printf("AK_realloc(srResult.aiTuple_addresses = %p, srResult.iNum_tuple_addresses++ * sizeof(int) = %d)\n", srResult.aiTuple_addresses, (srResult.iNum_tuple_addresses + 1) * sizeof(int)); if(srResult.iNum_tuple_addresses == 7) puts("8"); }*/ srResult.iNum_tuple_addresses++; srResult.aiTuple_addresses = (int *) AK_realloc(srResult.aiTuple_addresses, srResult.iNum_tuple_addresses * sizeof (int)); if (srResult.aiTuple_addresses == NULL) { printf("AK_search_unsorted: ERROR. Cannot AK_reallocate srResult.aiTuple_addresses, iteration %d.\n", i); AK_EPI; exit(EXIT_ERROR); } /*if(DEBUG) puts("AK_realloc srResult.aiBlocks");*/ srResult.aiBlocks = (int *) AK_realloc(srResult.aiBlocks, srResult.iNum_tuple_addresses * sizeof (int)); if (srResult.aiBlocks == NULL) { printf("AK_search_unsorted: ERROR. Cannot AK_reallocate srResult.aiBlocks, iteration %d.\n", i); AK_EPI; exit(EXIT_ERROR); } srResult.aiTuple_addresses[srResult.iNum_tuple_addresses - 1] = i; srResult.aiBlocks[srResult.iNum_tuple_addresses - 1] = iBlock; } } } } AK_EPI; return srResult; }