char* TRI_GetContextErrorAql (const char* const query, const size_t line, const size_t column) { const char* p; char* temp; char* result; char c; // note: line numbers reported by bison/flex start at 1, columns start at 0 size_t offset; size_t currentLine = 1; size_t currentColumn = 0; assert(query); p = query; while ((c = *p)) { if (currentLine > line || (currentLine >= line && currentColumn >= column)) { break; } if (c == '\n') { ++p; ++currentLine; currentColumn = 0; } else if (c == '\r') { ++p; ++currentLine; currentColumn = 0; if (*p == '\n') { ++p; } } else { ++currentColumn; ++p; } } // p is pointing at the position in the query the parse error occurred at assert(p >= query); offset = p - query; if (strlen(query) < offset + SNIPPET_LENGTH) { return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, strlen(query) - offset); } temp = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, SNIPPET_LENGTH); if (!temp) { // out of memory return NULL; } result = TRI_Concatenate2StringZ(TRI_UNKNOWN_MEM_ZONE, temp, SNIPPET_SUFFIX); TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, temp); return result; }
void TRI_Insert2ArrayJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t* subobject) { TRI_json_t copy; char* att; size_t length; TRI_ASSERT(object->_type == TRI_JSON_ARRAY); if (subobject == NULL) { return; } if (TRI_ReserveVector(&object->_value._objects, 2) != TRI_ERROR_NO_ERROR) { // TODO: signal OOM here return; } length = strlen(name); att = TRI_DuplicateString2Z(zone, name, length); if (att == NULL) { // TODO: signal OOM here return; } // attribute name InitString(©, att, length); TRI_PushBackVector(&object->_value._objects, ©); // attribute value TRI_PushBackVector(&object->_value._objects, subobject); }
static TRI_aql_bind_parameter_t* CreateParameter (const char* const name, const size_t nameLength, const TRI_json_t* const value) { TRI_aql_bind_parameter_t* parameter; assert(name); assert(value); parameter = (TRI_aql_bind_parameter_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_bind_parameter_t), false); if (parameter == NULL) { return NULL; } parameter->_name = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, name, nameLength); if (parameter->_name == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter); return NULL; } parameter->_value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) value); if (parameter->_value == NULL) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter->_name); TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter); return NULL; } return parameter; }
char* TRI_GetErrorMessageAql (const TRI_aql_error_t* const error) { char* message; char buffer[256]; int code; TRI_ASSERT(error); code = TRI_GetErrorCodeAql(error); if (code == TRI_ERROR_NO_ERROR) { return NULL; } message = error->_message; if (message == NULL) { return NULL; } if (error->_data && (NULL != strstr(message, "%s"))) { int written = snprintf(buffer, sizeof(buffer), message, error->_data); return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, (const char*) &buffer, (size_t) written); } return TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, message); }
void TRI_Insert2ObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t const* subobject) { TRI_ASSERT(object->_type == TRI_JSON_OBJECT); if (subobject == nullptr) { return; } if (TRI_ReserveVector(&object->_value._objects, 2) != TRI_ERROR_NO_ERROR) { // TODO: signal OOM here return; } size_t length = strlen(name); char* att = TRI_DuplicateString2Z(zone, name, length); if (att == nullptr) { // TODO: signal OOM here return; } // create attribute name in place TRI_json_t* next = static_cast<TRI_json_t*>(TRI_NextVector(&object->_value._objects)); // we have made sure above with the reserve call that the vector has enough capacity TRI_ASSERT(next != nullptr); InitString(next, att, length); // attribute value TRI_PushBackVector(&object->_value._objects, subobject); }
char* TRI_RegisterStringAql (TRI_aql_context_t* const context, const char* const value, const size_t length, const bool deescape) { char* copy; if (value == NULL) { ABORT_OOM } if (deescape && length > 0) { size_t outLength; copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, value, length, &outLength); } else { copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, value, length); } if (copy == NULL) { ABORT_OOM } if (TRI_PushBackVectorPointer(&context->_memory._strings, copy) != TRI_ERROR_NO_ERROR) { TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, copy); ABORT_OOM }
int TRI_InitString2CopyJson (TRI_memory_zone_t* zone, TRI_json_t* result, char const* value, size_t length) { char* copy = TRI_DuplicateString2Z(zone, value, length); if (copy == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } InitString(result, copy, length); return TRI_ERROR_NO_ERROR; }
int TRI_InitStringCopyJson (TRI_memory_zone_t* zone, TRI_json_t* result, char const* value, size_t length) { if (value == nullptr) { // initial string should be valid return TRI_ERROR_INTERNAL; } char* copy = TRI_DuplicateString2Z(zone, value, length); if (copy == nullptr) { return TRI_ERROR_OUT_OF_MEMORY; } InitString(result, copy, length); return TRI_ERROR_NO_ERROR; }
TRI_json_t* TRI_CreateString2CopyJson (TRI_memory_zone_t* zone, char const* value, size_t length) { TRI_json_t* result; result = (TRI_json_t*) TRI_Allocate(zone, sizeof(TRI_json_t), false); if (result == NULL) { return NULL; } InitString(result, TRI_DuplicateString2Z(zone, value, length), length); if (result->_value._string.data == NULL) { TRI_Free(zone, result); return NULL; } return result; }
TRI_json_t* TRI_CreateStringCopyJson (TRI_memory_zone_t* zone, char const* value, size_t length) { if (value == nullptr) { // initial string should be valid... return nullptr; } TRI_json_t* result = static_cast<TRI_json_t*>(TRI_Allocate(zone, sizeof(TRI_json_t), false)); if (result != nullptr) { char* copy = TRI_DuplicateString2Z(zone, value, length); if (copy == nullptr) { TRI_Free(zone, result); return nullptr; } InitString(result, copy, length); } return result; }
void TRI_Insert2ArrayJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t* subobject) { TRI_json_t copy; size_t length; assert(object->_type == TRI_JSON_ARRAY); if (subobject == NULL) { return; } length = strlen(name); copy._type = TRI_JSON_STRING; copy._value._string.length = length + 1; copy._value._string.data = TRI_DuplicateString2Z(zone, name, length); // including '\0' TRI_PushBackVector(&object->_value._objects, ©); TRI_PushBackVector(&object->_value._objects, subobject); }
TRI_json_t* TRI_CreateStringCopyJson (TRI_memory_zone_t* zone, char const* value) { TRI_json_t* result; size_t length; length = strlen(value); result = (TRI_json_t*) TRI_Allocate(zone, sizeof(TRI_json_t), false); if (result == NULL) { return NULL; } result->_type = TRI_JSON_STRING; result->_value._string.length = length + 1; result->_value._string.data = TRI_DuplicateString2Z(zone, value, length); if (result->_value._string.data == NULL) { TRI_Free(zone, result); return NULL; } return result; }
static int LoadConfiguration (TRI_vocbase_t* vocbase, TRI_replication_applier_configuration_t* config) { TRI_json_t* json; TRI_json_t* value; char* filename; int res; TRI_DestroyConfigurationReplicationApplier(config); TRI_InitConfigurationReplicationApplier(config); filename = GetConfigurationFilename(vocbase); if (! TRI_ExistsFile(filename)) { TRI_FreeString(TRI_CORE_MEM_ZONE, filename); return TRI_ERROR_FILE_NOT_FOUND; } json = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, NULL); TRI_FreeString(TRI_CORE_MEM_ZONE, filename); if (! TRI_IsArrayJson(json)) { if (json != NULL) { TRI_FreeJson(TRI_CORE_MEM_ZONE, json); } return TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION; } res = TRI_ERROR_NO_ERROR; if (config->_endpoint != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_endpoint); config->_endpoint = NULL; } if (config->_database != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_database); config->_database = NULL; } if (config->_username != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_username); config->_username = NULL; } if (config->_password != NULL) { TRI_FreeString(TRI_CORE_MEM_ZONE, config->_password); config->_password = NULL; } // read the endpoint value = TRI_LookupArrayJson(json, "endpoint"); if (! TRI_IsStringJson(value)) { res = TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION; } else { config->_endpoint = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } // read the database name value = TRI_LookupArrayJson(json, "database"); if (! TRI_IsStringJson(value)) { config->_database = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, vocbase->_name); } else { config->_database = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } // read username / password value = TRI_LookupArrayJson(json, "username"); if (TRI_IsStringJson(value)) { config->_username = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } value = TRI_LookupArrayJson(json, "password"); if (TRI_IsStringJson(value)) { config->_password = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, value->_value._string.data, value->_value._string.length - 1); } value = TRI_LookupArrayJson(json, "requestTimeout"); if (TRI_IsNumberJson(value)) { config->_requestTimeout = value->_value._number; } value = TRI_LookupArrayJson(json, "connectTimeout"); if (TRI_IsNumberJson(value)) { config->_connectTimeout = value->_value._number; } value = TRI_LookupArrayJson(json, "maxConnectRetries"); if (TRI_IsNumberJson(value)) { config->_maxConnectRetries = (uint64_t) value->_value._number; } value = TRI_LookupArrayJson(json, "chunkSize"); if (TRI_IsNumberJson(value)) { config->_chunkSize = (uint64_t) value->_value._number; } value = TRI_LookupArrayJson(json, "autoStart"); if (TRI_IsBooleanJson(value)) { config->_autoStart = value->_value._boolean; } value = TRI_LookupArrayJson(json, "adaptivePolling"); if (TRI_IsBooleanJson(value)) { config->_adaptivePolling = value->_value._boolean; } TRI_FreeJson(TRI_CORE_MEM_ZONE, json); return res; }
static TRI_shape_pid_t FindNameAttributePath (TRI_shaper_t* shaper, char const* name) { TRI_shape_aid_t* aids; TRI_shape_path_t* result; size_t count; size_t len; size_t total; char* buffer; char* end; char* prev; char* ptr; void const* f; void const* p; p = TRI_LookupByKeyAssociativeSynced(&shaper->_attributePathsByName, name); if (p != NULL) { return ((TRI_shape_path_t const*) p)->_pid; } // create a attribute path len = strlen(name); // lock the index and check that the element is still missing TRI_LockMutex(&shaper->_attributePathLock); // if the element appeared, return the pid p = TRI_LookupByKeyAssociativeSynced(&shaper->_attributePathsByName, name); if (p != NULL) { TRI_UnlockMutex(&shaper->_attributePathLock); return ((TRI_shape_path_t const*) p)->_pid; } // split path into attribute pieces count = 0; aids = TRI_Allocate(shaper->_memoryZone, len * sizeof(TRI_shape_aid_t), false); if (aids == NULL) { TRI_UnlockMutex(&shaper->_attributePathLock); LOG_ERROR("out of memory in shaper"); return 0; } buffer = ptr = TRI_DuplicateString2Z(shaper->_memoryZone, name, len); if (buffer == NULL) { TRI_UnlockMutex(&shaper->_attributePathLock); TRI_Free(shaper->_memoryZone, aids); LOG_ERROR("out of memory in shaper"); return 0; } end = buffer + len + 1; prev = buffer; for (; ptr < end; ++ptr) { if (*ptr == '.' || *ptr == '\0') { *ptr = '\0'; if (ptr != prev) { aids[count++] = shaper->findAttributeName(shaper, prev); } prev = ptr + 1; } } TRI_FreeString(shaper->_memoryZone, buffer); // create element total = sizeof(TRI_shape_path_t) + (len + 1) + (count * sizeof(TRI_shape_aid_t)); result = TRI_Allocate(shaper->_memoryZone, total, false); if (result == NULL) { TRI_UnlockMutex(&shaper->_attributePathLock); TRI_Free(shaper->_memoryZone, aids); LOG_ERROR("out of memory in shaper"); return 0; } result->_pid = shaper->_nextPid++; result->_nameLength = len + 1; result->_aidLength = count; memcpy(((char*) result) + sizeof(TRI_shape_path_t), aids, count * sizeof(TRI_shape_aid_t)); memcpy(((char*) result) + sizeof(TRI_shape_path_t) + count * sizeof(TRI_shape_aid_t), name, len + 1); TRI_Free(shaper->_memoryZone, aids); f = TRI_InsertKeyAssociativeSynced(&shaper->_attributePathsByName, name, result); assert(f == NULL); f = TRI_InsertKeyAssociativeSynced(&shaper->_attributePathsByPid, &result->_pid, result); assert(f == NULL); // return pid TRI_UnlockMutex(&shaper->_attributePathLock); return result->_pid; }
char* TRI_GetContextErrorAql (const char* const query, const size_t queryLength, const size_t line, const size_t column) { const char* p; char* q; char* result; char c; // note: line numbers reported by bison/flex start at 1, columns start at 0 size_t offset; size_t currentLine = 1; size_t currentColumn = 0; TRI_ASSERT(query); p = query; while ((c = *p)) { if (currentLine > line || (currentLine >= line && currentColumn >= column)) { break; } if (c == '\n') { ++p; ++currentLine; currentColumn = 0; } else if (c == '\r') { ++p; ++currentLine; currentColumn = 0; if (*p == '\n') { ++p; } } else { ++currentColumn; ++p; } } // p is pointing at the position in the query the parse error occurred at TRI_ASSERT(p >= query); offset = (size_t) (p - query); if (queryLength < offset + SNIPPET_LENGTH) { return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, queryLength - offset); } q = result = static_cast<char*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, SNIPPET_LENGTH + strlen(SNIPPET_SUFFIX) + 1, false)); if (result == NULL) { // out of memory return NULL; } // copy query part memcpy(q, query + offset, SNIPPET_LENGTH); q += SNIPPET_LENGTH; // copy ... memcpy(q, SNIPPET_SUFFIX, strlen(SNIPPET_SUFFIX)); q += strlen(SNIPPET_SUFFIX); *q = '\0'; return result; }
static void PatchVariables (TRI_aql_statement_walker_t* const walker) { TRI_aql_context_t* context = ((aql_optimiser_t*) walker->_data)->_context; TRI_vector_pointer_t* ranges; size_t i, n; ranges = TRI_GetCurrentRangesStatementWalkerAql(walker); if (ranges == NULL) { // no ranges defined, exit early return; } // iterate over all ranges found n = ranges->_length; for (i = 0; i < n; ++i) { TRI_aql_field_access_t* fieldAccess; TRI_aql_variable_t* variable; TRI_aql_node_t* definingNode; TRI_aql_node_t* expressionNode; char* variableName; size_t scopeCount; bool isReference; fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(ranges, i); assert(fieldAccess); assert(fieldAccess->_fullName); assert(fieldAccess->_variableNameLength > 0); variableName = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_fullName, fieldAccess->_variableNameLength); if (variableName == NULL) { // out of memory! TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL); return; } isReference = (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE); variable = TRI_GetVariableStatementWalkerAql(walker, variableName, &scopeCount); TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, variableName); if (variable == NULL) { continue; } if (isReference && scopeCount > 0) { // unfortunately, the referenced variable is in an outer scope, so we cannot use it continue; } // note: we must not modify outer variables of subqueries // get the node that defines the variable definingNode = variable->_definingNode; assert(definingNode != NULL); expressionNode = NULL; switch (definingNode->_type) { case TRI_AQL_NODE_LET: expressionNode = TRI_AQL_NODE_MEMBER(definingNode, 1); break; case TRI_AQL_NODE_FOR: expressionNode = TRI_AQL_NODE_MEMBER(definingNode, 1); break; default: { } } if (expressionNode != NULL) { if (expressionNode->_type == TRI_AQL_NODE_FCALL) { // the defining node is a function call // get the function name TRI_aql_function_t* function = TRI_AQL_NODE_DATA(expressionNode); if (function->optimise != NULL) { // call the function's optimise callback function->optimise(expressionNode, context, fieldAccess); } } if (expressionNode->_type == TRI_AQL_NODE_COLLECTION) { TRI_aql_collection_hint_t* hint = (TRI_aql_collection_hint_t*) (TRI_AQL_NODE_DATA(expressionNode)); // set new value hint->_ranges = TRI_AddAccessAql(context, hint->_ranges, fieldAccess); } } } }