mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/triAGENS/AvocadoDB into devel
Conflicts: Makefile.in
This commit is contained in:
commit
9420b58437
|
@ -51,3 +51,7 @@ stamp-h*
|
|||
config.h
|
||||
3rdParty/libev/libtool
|
||||
out
|
||||
3rdParty/libev/ARCH.x64
|
||||
.v8-build
|
||||
.libev-build
|
||||
Doxygen/js
|
||||
|
|
|
@ -30,7 +30,7 @@ boost
|
|||
|
||||
protected:
|
||||
|
||||
~error_info_base() throw()
|
||||
virtual ~error_info_base() throw()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
#include <boost/fusion/tuple/detail/preprocessed/make_tuple50.hpp>
|
||||
#else
|
||||
#error "FUSION_MAX_VECTOR_SIZE out of bounds for preprocessed headers"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
#include <boost/fusion/tuple/detail/preprocessed/tuple50.hpp>
|
||||
#else
|
||||
#error "FUSION_MAX_VECTOR_SIZE out of bounds for preprocessed headers"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
#include <boost/fusion/tuple/detail/preprocessed/tuple50_fwd.hpp>
|
||||
#else
|
||||
#error "FUSION_MAX_VECTOR_SIZE out of bounds for preprocessed headers"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
#include <boost/fusion/tuple/detail/preprocessed/tuple_tie50.hpp>
|
||||
#else
|
||||
#error "FUSION_MAX_VECTOR_SIZE out of bounds for preprocessed headers"
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace {
|
|||
/// @brief handles control-c
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ControlCTask : public rest::SignalTask {
|
||||
class ControlCTask : public SignalTask {
|
||||
public:
|
||||
ControlCTask (ApplicationServer* server)
|
||||
: Task("Control-C"), SignalTask(), server(server) {
|
||||
|
|
|
@ -35,20 +35,6 @@
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTIONS-- triagens namespace
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace triagens {
|
||||
using namespace std;
|
||||
|
||||
typedef TRI_blob_t blob_t;
|
||||
typedef TRI_datetime_t datetime_t;
|
||||
typedef TRI_date_t date_t;
|
||||
typedef TRI_seconds_t seconds_t;
|
||||
typedef TRI_msec_t msec_t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- C++ header files that are always present on all systems
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -65,6 +51,20 @@ namespace triagens {
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTIONS-- triagens namespace
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace triagens {
|
||||
using namespace std;
|
||||
|
||||
typedef TRI_blob_t blob_t;
|
||||
typedef TRI_datetime_t datetime_t;
|
||||
typedef TRI_date_t date_t;
|
||||
typedef TRI_seconds_t seconds_t;
|
||||
typedef TRI_msec_t msec_t;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- noncopyable class
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -28,6 +28,575 @@
|
|||
|
||||
#include "associative-multi.h"
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ASSOCIATIVE ARRAY
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a new element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void AddNewElement(TRI_multi_array_t* array, void* element) {
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// compute the hash
|
||||
// ...........................................................................
|
||||
|
||||
hash = array->hashElement(array, element);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
|
||||
i = hash % array->_nrAlloc;
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
array->_nrProbesR++;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// add a new element to the associative array
|
||||
// ...........................................................................
|
||||
|
||||
memcpy(array->_table + i * array->_elementSize, element, array->_elementSize);
|
||||
array->_nrUsed++;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief resizes the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ResizeMultiArray (TRI_multi_array_t* array) {
|
||||
char* oldTable;
|
||||
uint64_t oldAlloc;
|
||||
uint64_t j;
|
||||
|
||||
oldTable = array->_table;
|
||||
oldAlloc = array->_nrAlloc;
|
||||
|
||||
array->_nrAlloc = 2 * array->_nrAlloc + 1;
|
||||
array->_nrUsed = 0;
|
||||
array->_nrResizes++;
|
||||
|
||||
array->_table = TRI_Allocate(array->_nrAlloc * array->_elementSize);
|
||||
|
||||
for (j = 0; j < array->_nrAlloc; j++) {
|
||||
array->clearElement(array, array->_table + j * array->_elementSize);
|
||||
}
|
||||
|
||||
for (j = 0; j < oldAlloc; j++) {
|
||||
if (! array->isEmptyElement(array, oldTable + j * array->_elementSize)) {
|
||||
AddNewElement(array, oldTable + j * array->_elementSize);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_Free(oldTable);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitMultiArray(TRI_multi_array_t* array,
|
||||
size_t elementSize,
|
||||
uint64_t (*hashKey) (TRI_multi_array_t*, void*),
|
||||
uint64_t (*hashElement) (TRI_multi_array_t*, void*),
|
||||
void (*clearElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEmptyElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEqualKeyElement) (TRI_multi_array_t*, void*, void*),
|
||||
bool (*isEqualElementElement) (TRI_multi_array_t*, void*, void*)) {
|
||||
char* p;
|
||||
char* e;
|
||||
|
||||
array->hashKey = hashKey;
|
||||
array->hashElement = hashElement;
|
||||
array->clearElement = clearElement;
|
||||
array->isEmptyElement = isEmptyElement;
|
||||
array->isEqualKeyElement = isEqualKeyElement;
|
||||
array->isEqualElementElement = isEqualElementElement;
|
||||
|
||||
array->_elementSize = elementSize;
|
||||
array->_nrAlloc = 10;
|
||||
|
||||
array->_table = TRI_Allocate(array->_elementSize * array->_nrAlloc);
|
||||
|
||||
p = array->_table;
|
||||
e = p + array->_elementSize * array->_nrAlloc;
|
||||
|
||||
for (; p < e; p += array->_elementSize) {
|
||||
array->clearElement(array, p);
|
||||
}
|
||||
|
||||
array->_nrUsed = 0;
|
||||
array->_nrFinds = 0;
|
||||
array->_nrAdds = 0;
|
||||
array->_nrRems = 0;
|
||||
array->_nrResizes = 0;
|
||||
array->_nrProbesF = 0;
|
||||
array->_nrProbesA = 0;
|
||||
array->_nrProbesD = 0;
|
||||
array->_nrProbesR = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyMultiArray (TRI_multi_array_t* array) {
|
||||
TRI_Free(array->_table);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeMultiArray (TRI_multi_array_t* array) {
|
||||
TRI_DestroyMultiArray(array);
|
||||
TRI_Free(array);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByKeyMultiArray (TRI_multi_array_t* array, void* key) {
|
||||
TRI_vector_pointer_t result;
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// initialise the vector which will hold the result if any
|
||||
// ...........................................................................
|
||||
|
||||
TRI_InitVectorPointer(&result);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// compute the hash
|
||||
// ...........................................................................
|
||||
|
||||
hash = array->hashKey(array, key);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
|
||||
array->_nrFinds++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
|
||||
if (array->isEqualKeyElement(array, key, array->_table + i * array->_elementSize)) {
|
||||
TRI_PushBackVectorPointer(&result, array->_table + i * array->_elementSize);
|
||||
}
|
||||
else {
|
||||
array->_nrProbesF++;
|
||||
}
|
||||
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// return whatever we found -- which could be an empty vector list if nothing
|
||||
// matches.
|
||||
// ...........................................................................
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given an element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByElementMultiArray (TRI_multi_array_t* array, void* element) {
|
||||
TRI_vector_pointer_t result;
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// initialise the vector which will hold the result if any
|
||||
// ...........................................................................
|
||||
|
||||
TRI_InitVectorPointer(&result);
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// compute the hash
|
||||
// ...........................................................................
|
||||
|
||||
hash = array->hashElement(array, element);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
|
||||
array->_nrFinds++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
|
||||
if (array->isEqualElementElement(array, element, array->_table + i * array->_elementSize)) {
|
||||
TRI_PushBackVectorPointer(&result, array->_table + i * array->_elementSize);
|
||||
}
|
||||
else {
|
||||
array->_nrProbesF++;
|
||||
}
|
||||
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// return whatever we found -- which could be an empty vector list if nothing
|
||||
// matches. Note that we allow multiple elements (compare with pointer impl).
|
||||
// ...........................................................................
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertElementMultiArray (TRI_multi_array_t* array, void* element, bool overwrite) {
|
||||
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// compute the hash
|
||||
// ...........................................................................
|
||||
|
||||
hash = array->hashElement(array, element);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
|
||||
array->_nrAdds++;
|
||||
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)
|
||||
&& ! array->isEqualElementElement(array, element, array->_table + i * array->_elementSize)) {
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
array->_nrProbesA++;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// If we found an element, return. While we allow duplicate entries in the hash
|
||||
// table, we do not allow duplicate elements. Elements would refer to the
|
||||
// (for example) an actual row in memory. This is different from the
|
||||
// TRI_InsertElementMultiArray function below where we only have keys to
|
||||
// differentiate between elements.
|
||||
// ...........................................................................
|
||||
if (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
if (overwrite) {
|
||||
memcpy(array->_table + i * array->_elementSize, element, array->_elementSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// add a new element to the associative array
|
||||
// ...........................................................................
|
||||
|
||||
memcpy(array->_table + i * array->_elementSize, element, array->_elementSize);
|
||||
array->_nrUsed++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// if we were adding and the table is more than half full, extend it
|
||||
// ...........................................................................
|
||||
|
||||
if (array->_nrAlloc < 2 * array->_nrUsed) {
|
||||
ResizeMultiArray(array);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertKeyMultiArray (TRI_multi_array_t* array, void* key, void* element, bool overwrite) {
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// compute the hash
|
||||
// ...........................................................................
|
||||
|
||||
hash = array->hashKey(array, key);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
|
||||
array->_nrAdds++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
array->_nrProbesA++;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// We do not look for an element (as opposed to the function above). So whether
|
||||
// or not there exists a duplicate we do not care.
|
||||
// ...........................................................................
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// add a new element to the associative array
|
||||
// ...........................................................................
|
||||
|
||||
memcpy(array->_table + i * array->_elementSize, element, array->_elementSize);
|
||||
array->_nrUsed++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// if we were adding and the table is more than half full, extend it
|
||||
// ...........................................................................
|
||||
|
||||
if (array->_nrAlloc < 2 * array->_nrUsed) {
|
||||
ResizeMultiArray(array);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an element from the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveElementMultiArray (TRI_multi_array_t* array, void* element, void* old) {
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
uint64_t k;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// Obtain the hash
|
||||
// ...........................................................................
|
||||
hash = array->hashElement(array, element);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
array->_nrRems++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table
|
||||
// ...........................................................................
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)
|
||||
&& ! array->isEqualElementElement(array, element, array->_table + i * array->_elementSize)) {
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
array->_nrProbesD++;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// if we did not find such an item return false
|
||||
// ...........................................................................
|
||||
if (array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
if (old != NULL) {
|
||||
memset(old, 0, array->_elementSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// remove item
|
||||
// ...........................................................................
|
||||
if (old != NULL) {
|
||||
memcpy(old, array->_table + i * array->_elementSize, array->_elementSize);
|
||||
}
|
||||
|
||||
|
||||
array->clearElement(array, array->_table + i * array->_elementSize);
|
||||
array->_nrUsed--;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// and now check the following places for items to move here
|
||||
// ...........................................................................
|
||||
k = (i + 1) % array->_nrAlloc;
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + k * array->_elementSize)) {
|
||||
uint64_t j = array->hashElement(array, array->_table + k * array->_elementSize) % array->_nrAlloc;
|
||||
|
||||
if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) {
|
||||
memcpy(array->_table + i * array->_elementSize, array->_table + k * array->_elementSize, array->_elementSize);
|
||||
array->clearElement(array, array->_table + k * array->_elementSize);
|
||||
i = k;
|
||||
}
|
||||
|
||||
k = (k + 1) % array->_nrAlloc;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveKeyMultiArray (TRI_multi_array_t* array, void* key, void* old) {
|
||||
uint64_t hash;
|
||||
uint64_t i;
|
||||
uint64_t k;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// generate hash using key
|
||||
// ...........................................................................
|
||||
hash = array->hashKey(array, key);
|
||||
i = hash % array->_nrAlloc;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// update statistics
|
||||
// ...........................................................................
|
||||
array->_nrRems++;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// search the table -- we can only match keys
|
||||
// ...........................................................................
|
||||
while (! array->isEmptyElement(array, array->_table + i * array->_elementSize)
|
||||
&& ! array->isEqualKeyElement(array, key, array->_table + i * array->_elementSize)) {
|
||||
i = (i + 1) % array->_nrAlloc;
|
||||
array->_nrProbesD++;
|
||||
}
|
||||
|
||||
// ...........................................................................
|
||||
// if we did not find such an item return false
|
||||
// ...........................................................................
|
||||
if (array->isEmptyElement(array, array->_table + i * array->_elementSize)) {
|
||||
if (old != NULL) {
|
||||
memset(old, 0, array->_elementSize);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// remove item
|
||||
// ...........................................................................
|
||||
if (old != NULL) {
|
||||
memcpy(old, array->_table + i * array->_elementSize, array->_elementSize);
|
||||
}
|
||||
|
||||
array->clearElement(array, array->_table + i * array->_elementSize);
|
||||
array->_nrUsed--;
|
||||
|
||||
|
||||
// ...........................................................................
|
||||
// and now check the following places for items to move here
|
||||
// ...........................................................................
|
||||
k = (i + 1) % array->_nrAlloc;
|
||||
|
||||
while (! array->isEmptyElement(array, array->_table + k * array->_elementSize)) {
|
||||
uint64_t j = array->hashElement(array, array->_table + k * array->_elementSize) % array->_nrAlloc;
|
||||
|
||||
if ((i < k && !(i < j && j <= k)) || (k < i && !(i < j || j <= k))) {
|
||||
memcpy(array->_table + i * array->_elementSize, array->_table + k * array->_elementSize, array->_elementSize);
|
||||
array->clearElement(array, array->_table + k * array->_elementSize);
|
||||
i = k;
|
||||
}
|
||||
|
||||
k = (k + 1) % array->_nrAlloc;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- ASSOCIATIVE POINTERS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -47,6 +47,40 @@ extern "C" {
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief associative multi array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_multi_array_s {
|
||||
uint64_t (*hashKey) (struct TRI_multi_array_s*, void*);
|
||||
uint64_t (*hashElement) (struct TRI_multi_array_s*, void*);
|
||||
|
||||
void (*clearElement) (struct TRI_multi_array_s*, void*);
|
||||
|
||||
bool (*isEmptyElement) (struct TRI_multi_array_s*, void*);
|
||||
bool (*isEqualKeyElement) (struct TRI_multi_array_s*, void*, void*);
|
||||
bool (*isEqualElementElement) (struct TRI_multi_array_s*, void*, void*);
|
||||
|
||||
uint32_t _elementSize; // the size of the elements which are to be stored in the table
|
||||
|
||||
uint64_t _nrAlloc; // the size of the table
|
||||
uint64_t _nrUsed; // the number of used entries
|
||||
|
||||
|
||||
char* _table; // the table itself
|
||||
|
||||
uint64_t _nrFinds; // statistics: number of lookup calls
|
||||
uint64_t _nrAdds; // statistics: number of insert calls
|
||||
uint64_t _nrRems; // statistics: number of remove calls
|
||||
uint64_t _nrResizes; // statistics: number of resizes
|
||||
|
||||
uint64_t _nrProbesF; // statistics: number of misses while looking up
|
||||
uint64_t _nrProbesA; // statistics: number of misses while inserting
|
||||
uint64_t _nrProbesD; // statistics: number of misses while removing
|
||||
uint64_t _nrProbesR; // statistics: number of misses while adding
|
||||
}
|
||||
TRI_multi_array_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief associative multi array of pointers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -75,10 +109,105 @@ typedef struct TRI_multi_pointer_s {
|
|||
}
|
||||
TRI_multi_pointer_t;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE ARRAY
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialises an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitMultiArray (TRI_multi_array_t*,
|
||||
size_t elementSize,
|
||||
uint64_t (*hashKey) (TRI_multi_array_t*, void*),
|
||||
uint64_t (*hashElement) (TRI_multi_array_t*, void*),
|
||||
void (*clearElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEmptyElement) (TRI_multi_array_t*, void*),
|
||||
bool (*isEqualKeyElement) (TRI_multi_array_t*, void*, void*),
|
||||
bool (*isEqualElementElement) (TRI_multi_array_t*, void*, void*));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyMultiArray (TRI_multi_array_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys an array and frees the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeMultiArray (TRI_multi_array_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Collections
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given a key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByKeyMultiArray (TRI_multi_array_t*, void* key);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookups an element given an element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_vector_pointer_t TRI_LookupByElementMultiArray (TRI_multi_array_t*, void* element);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertElementMultiArray (TRI_multi_array_t*, void* element, bool overwrite);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_InsertKeyMultiArray (TRI_multi_array_t*, void* key, void* element, bool overwrite);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an element from the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveElementMultiArray (TRI_multi_array_t*, void* element, void* old);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief removes an key/element to the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_RemoveKeyMultiArray (TRI_multi_array_t*, void* key, void* old);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MULTI ASSOCIATIVE POINTERS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
#include "BasicsC/strings.h"
|
||||
#include "BasicsC/vector.h"
|
||||
#include "BasicsC/associative.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private types
|
||||
|
@ -90,7 +91,7 @@ static pthread_key_t ErrorKey;
|
|||
/// @brief the error messages
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_vector_string_t ErrorMessages;
|
||||
static TRI_associative_pointer_t ErrorMessages;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -119,6 +120,39 @@ static void CleanupError (void* ptr) {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hash function used to hash error codes (no real hash, uses the error
|
||||
/// code only)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashErrorCode (TRI_associative_pointer_t* array,
|
||||
void const* key) {
|
||||
return (uint64_t) *((int*) key);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hash function used to hash errors messages (not used)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashError (TRI_associative_pointer_t* array,
|
||||
void const* element) {
|
||||
|
||||
TRI_error_t* entry = (TRI_error_t*) element;
|
||||
return (uint64_t) entry->_code;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Comparison function used to determine error equality
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualError (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
TRI_error_t* entry = (TRI_error_t*) element;
|
||||
|
||||
return *((int*) key) == entry->_code;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -168,6 +202,7 @@ int TRI_errno () {
|
|||
char const* TRI_last_error () {
|
||||
int err;
|
||||
int sys;
|
||||
TRI_error_t* entry;
|
||||
|
||||
#if defined(TRI_GCC_THREAD_LOCAL_STORAGE) || defined(TRI_WIN32_THREAD_LOCAL_STORAGE)
|
||||
|
||||
|
@ -186,7 +221,7 @@ char const* TRI_last_error () {
|
|||
}
|
||||
else {
|
||||
err = eptr->_number;
|
||||
err = eptr->_sys;
|
||||
sys = eptr->_sys;
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -197,17 +232,12 @@ char const* TRI_last_error () {
|
|||
return strerror(sys);
|
||||
}
|
||||
|
||||
if (err < (int) ErrorMessages._length) {
|
||||
char const* str = ErrorMessages._buffer[err];
|
||||
|
||||
if (str == NULL) {
|
||||
return "general error";
|
||||
}
|
||||
|
||||
return str;
|
||||
entry = (TRI_error_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&ErrorMessages, (void const*) &err);
|
||||
if (!entry) {
|
||||
return "general error";
|
||||
}
|
||||
|
||||
return "general error";
|
||||
return entry->_message;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -229,6 +259,7 @@ int TRI_set_errno (int error) {
|
|||
#elif defined(TRI_HAVE_POSIX_THREADS)
|
||||
|
||||
tri_error_t* eptr;
|
||||
int copyErrno = errno;
|
||||
|
||||
eptr = pthread_getspecific(ErrorKey);
|
||||
|
||||
|
@ -240,7 +271,7 @@ int TRI_set_errno (int error) {
|
|||
eptr->_number = error;
|
||||
|
||||
if (error == TRI_ERROR_SYS_ERROR) {
|
||||
eptr->_sys = errno;
|
||||
eptr->_sys = copyErrno;
|
||||
}
|
||||
else {
|
||||
eptr->_sys = 0;
|
||||
|
@ -258,11 +289,26 @@ int TRI_set_errno (int error) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_set_errno_string (int error, char const* msg) {
|
||||
if (error >= (int) ErrorMessages._length) {
|
||||
TRI_ResizeVectorString(&ErrorMessages, error + 1);
|
||||
TRI_error_t* entry;
|
||||
|
||||
if (TRI_LookupByKeyAssociativePointer(&ErrorMessages, (void const*) &error)) {
|
||||
// logic error, error number is redeclared
|
||||
printf("Error: duplicate declaration of error code %i in %s:%i\n",
|
||||
error,
|
||||
__FILE__,
|
||||
__LINE__);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ErrorMessages._buffer[error] = TRI_DuplicateString(msg);
|
||||
entry = (TRI_error_t*) TRI_Allocate(sizeof(TRI_error_t));
|
||||
if (entry) {
|
||||
entry->_code = error;
|
||||
entry->_message = TRI_DuplicateString(msg);
|
||||
TRI_InsertKeyAssociativePointer(&ErrorMessages,
|
||||
&error,
|
||||
entry,
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -291,7 +337,11 @@ void TRI_InitialiseError () {
|
|||
return;
|
||||
}
|
||||
|
||||
TRI_InitVectorString(&ErrorMessages);
|
||||
TRI_InitAssociativePointer(&ErrorMessages,
|
||||
HashErrorCode,
|
||||
HashError,
|
||||
EqualError,
|
||||
0);
|
||||
|
||||
TRI_set_errno_string(0, "no error");
|
||||
TRI_set_errno_string(1, "failed");
|
||||
|
@ -319,11 +369,23 @@ void TRI_InitialiseError () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ShutdownError () {
|
||||
size_t i;
|
||||
|
||||
if (! Initialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_DestroyVectorString(&ErrorMessages);
|
||||
for (i = 0; i < ErrorMessages._nrAlloc; i++) {
|
||||
TRI_error_t* entry = ErrorMessages._table[i];
|
||||
if (entry) {
|
||||
if (entry->_message) {
|
||||
TRI_Free(entry->_message);
|
||||
}
|
||||
TRI_Free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_DestroyAssociativePointer(&ErrorMessages);
|
||||
|
||||
Initialised = false;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,29 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ErrorHandling
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief error code/message container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_error_s {
|
||||
int _code;
|
||||
char* _message;
|
||||
}
|
||||
TRI_error_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -354,10 +354,14 @@ TRI_vector_string_t TRI_FilesDirectory (char const* path) {
|
|||
struct _finddata_t fd;
|
||||
intptr_t handle;
|
||||
char* filter;
|
||||
|
||||
|
||||
TRI_InitVectorString(&result);
|
||||
|
||||
filter = TRI_Concatenate2String(path, "\\*");
|
||||
if (!filter) {
|
||||
return result;
|
||||
}
|
||||
|
||||
handle = _findfirst(filter, &fd);
|
||||
TRI_FreeString(filter);
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FSRT_INSTANCE
|
||||
#define FSRT_INSTANCE
|
||||
#define FSRT_INSTANCE Single
|
||||
#define FSRT_HAS_PREFIX 0
|
||||
#else
|
||||
#define FSRT_HAS_PREFIX 1
|
||||
|
|
|
@ -94,6 +94,27 @@ uint64_t TRI_FnvHashString (char const* buffer) {
|
|||
return nHashVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief computes a FNV hash for strings with a length
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t TRI_FnvHashBlock (uint64_t hash, char const* buffer, size_t length) {
|
||||
uint64_t nMagicPrime;
|
||||
size_t j;
|
||||
|
||||
nMagicPrime = 0x00000100000001b3ULL;
|
||||
|
||||
for (j = 0; j < length; ++j) {
|
||||
hash ^= buffer[j];
|
||||
hash *= nMagicPrime;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint64_t TRI_FnvHashBlockInitial (void) {
|
||||
return (0xcbf29ce484222325ULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hash functions
|
||||
/// @brief hash functions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- FNV
|
||||
// --SECTION-- (FNV-1a Fowler–Noll–Vo hash function) FNV
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -65,6 +65,13 @@ uint64_t TRI_FnvHashPointer (void const*, size_t);
|
|||
|
||||
uint64_t TRI_FnvHashString (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief computes a FNV hash for blocks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
uint64_t TRI_FnvHashBlock (uint64_t, char const*, size_t);
|
||||
uint64_t TRI_FnvHashBlockInitial (void);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -151,6 +151,11 @@ TRI_json_t* TRI_CreateNullJson () {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_NULL;
|
||||
|
||||
return result;
|
||||
|
@ -164,6 +169,11 @@ TRI_json_t* TRI_CreateBooleanJson (bool value) {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_BOOLEAN;
|
||||
result->_value._boolean = value;
|
||||
|
||||
|
@ -178,6 +188,11 @@ TRI_json_t* TRI_CreateNumberJson (double value) {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_NUMBER;
|
||||
result->_value._number = value;
|
||||
|
||||
|
@ -204,6 +219,11 @@ TRI_json_t* TRI_CreateStringJson (char* value) {
|
|||
length = strlen(value);
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_STRING;
|
||||
result->_value._string.length = length + 1;
|
||||
result->_value._string.data = value;
|
||||
|
@ -222,10 +242,20 @@ TRI_json_t* TRI_CreateStringCopyJson (char const* value) {
|
|||
length = strlen(value);
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_STRING;
|
||||
result->_value._string.length = length + 1;
|
||||
result->_value._string.data = TRI_DuplicateString2(value, length);
|
||||
|
||||
if (result->_value._string.data == NULL) {
|
||||
TRI_Free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -237,6 +267,11 @@ TRI_json_t* TRI_CreateString2Json (char* value, size_t length) {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_STRING;
|
||||
result->_value._string.length = length + 1;
|
||||
result->_value._string.data = value;
|
||||
|
@ -252,10 +287,20 @@ TRI_json_t* TRI_CreateString2CopyJson (char const* value, size_t length) {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_STRING;
|
||||
result->_value._string.length = length + 1;
|
||||
result->_value._string.data = TRI_DuplicateString2(value, length);
|
||||
|
||||
if (result->_value._string.data == NULL) {
|
||||
TRI_Free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -267,6 +312,11 @@ TRI_json_t* TRI_CreateListJson () {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_LIST;
|
||||
TRI_InitVector(&result->_value._objects, sizeof(TRI_json_t));
|
||||
|
||||
|
@ -281,6 +331,11 @@ TRI_json_t* TRI_CreateArrayJson () {
|
|||
TRI_json_t* result;
|
||||
|
||||
result = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result->_type = TRI_JSON_ARRAY;
|
||||
TRI_InitVector(&result->_value._objects, sizeof(TRI_json_t));
|
||||
|
||||
|
@ -321,12 +376,10 @@ void TRI_DestroyJson (TRI_json_t* object) {
|
|||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_json_t* v = TRI_AtVector(&object->_value._objects, i);
|
||||
|
||||
TRI_DestroyJson(v);
|
||||
}
|
||||
|
||||
TRI_DestroyVector(&object->_value._objects);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -375,6 +428,8 @@ void TRI_PushBack2ListJson (TRI_json_t* list, TRI_json_t* object) {
|
|||
assert(list->_type == TRI_JSON_LIST);
|
||||
|
||||
TRI_PushBackVector(&list->_value._objects, object);
|
||||
|
||||
TRI_Free(object);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -393,6 +448,11 @@ void TRI_InsertArrayJson (TRI_json_t* object, char const* name, TRI_json_t* subo
|
|||
copy._value._string.length = length + 1;
|
||||
copy._value._string.data = TRI_DuplicateString2(name, length); // including '\0'
|
||||
|
||||
if (copy._value._string.data == NULL) {
|
||||
// OOM
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_PushBackVector(&object->_value._objects, ©);
|
||||
|
||||
TRI_CopyToJson(©, subobject);
|
||||
|
@ -415,8 +475,15 @@ void TRI_Insert2ArrayJson (TRI_json_t* object, char const* name, TRI_json_t* sub
|
|||
copy._value._string.length = length + 1;
|
||||
copy._value._string.data = TRI_DuplicateString2(name, length); // including '\0'
|
||||
|
||||
if (copy._value._string.data == NULL) {
|
||||
// OOM
|
||||
return;
|
||||
}
|
||||
|
||||
TRI_PushBackVector(&object->_value._objects, ©);
|
||||
TRI_PushBackVector(&object->_value._objects, subobject);
|
||||
|
||||
TRI_Free(subobject);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -508,6 +575,10 @@ bool TRI_SaveJson (char const* filename, TRI_json_t const* object) {
|
|||
|
||||
tmp = TRI_Concatenate2String(filename, ".tmp");
|
||||
|
||||
if (tmp == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
fd = TRI_CREATE(tmp, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
|
||||
|
||||
if (fd < 0) {
|
||||
|
@ -624,6 +695,11 @@ TRI_json_t* TRI_CopyJson (TRI_json_t* src) {
|
|||
TRI_json_t* dst;
|
||||
|
||||
dst = (TRI_json_t*) TRI_Allocate(sizeof(TRI_json_t));
|
||||
|
||||
if (dst == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_CopyToJson(dst, src);
|
||||
|
||||
return dst;
|
||||
|
|
|
@ -71,6 +71,12 @@
|
|||
|
||||
#undef TRI_ENABLE_TIMING
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief memory allocation failures
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#undef TRI_ENABLE_MEMFAIL
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -27,6 +27,35 @@
|
|||
|
||||
#include "BasicsC/common.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup Memory
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Init flag for deliberate out-of-memory cases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
static bool Initialised = false;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Probability for deliberate out-of-memory cases
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
static double MemFailProbability;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -36,6 +65,29 @@
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Enable deliberate out-of-memory cases for TRI_Allocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
void TRI_ActivateMemFailures (double probability) {
|
||||
srand(32452843 + time(NULL) * 49979687);
|
||||
MemFailProbability = probability;
|
||||
Initialised = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Deactivate deliberate out-of-memory cases for TRI_Allocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
void TRI_DeactiveMemFailures (void) {
|
||||
Initialised = false;
|
||||
MemFailProbability = 0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for allocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -43,12 +95,31 @@
|
|||
void* TRI_Allocate (uint64_t n) {
|
||||
char* m;
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
// if configured with --enable-memfail, we can make calls to malloc fail
|
||||
// deliberately. This makes testing memory bottlenecks easier.
|
||||
if (Initialised) {
|
||||
if (RAND_MAX * MemFailProbability >= rand ()) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m = malloc((size_t) n);
|
||||
memset(m, 0, (size_t) n);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for reallocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_Reallocate (void* m, uint64_t n) {
|
||||
return realloc(m, n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for deallocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -45,12 +45,33 @@ extern "C" {
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief out-of-memory simulator configuration functions for debugging
|
||||
///
|
||||
/// Functions are only available if configured with --enable-memfail.
|
||||
/// Otherwise, they are replaced with empty macros.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef TRI_ENABLE_MEMFAIL
|
||||
void TRI_ActivateMemFailures (double probability);
|
||||
void TRI_DeactivateMemFailures (void);
|
||||
#else
|
||||
#define TRI_ActiveMemFailures(p) ;
|
||||
#define TRI_DeactivateMemFailures() ;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for allocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_Allocate (uint64_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for reallocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_Reallocate (void*, uint64_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief basic memory management for deallocate
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -176,6 +176,15 @@ TRI_process_info_t TRI_ProcessInfo (TRI_pid_t pid) {
|
|||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
TRI_process_info_t TRI_ProcessInfo (TRI_pid_t pid) {
|
||||
TRI_process_info_t result;
|
||||
|
||||
memset(&result, 0, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1,20 +1,10 @@
|
|||
> curl --data '@'- -X POST --dump - http://localhost:8529/_document/examples
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
content-type: text/plain;charset=utf-8
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13658604"
|
||||
location: /_document/9496015:13658604
|
||||
content-length: 0
|
||||
|
||||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X GET --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13658604"
|
||||
content-length: 43
|
||||
etag: "13658605"
|
||||
|
||||
{"Hallo":"World","_id":"9496015:13658604"}
|
||||
{ "Hallo" : "World",
|
||||
"_id" : "9496015:13658604",
|
||||
"_rev" : 13658605 }
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "14252313"
|
||||
content-length: 43
|
||||
|
||||
> curl --data @- -X PUT --header 'etag: "13865833"' --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl --data @- -X PUT --header 'etag: "13865833"'
|
||||
> --dump - http://localhost:8529/collection/9496015/13658604
|
||||
{ "Hallo" : "Me" }
|
||||
|
||||
HTTP/1.1 409 Conflict
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 101
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658604 is been altered", "code" : 409}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015:13658604 has been altered",
|
||||
"code" : 409}
|
||||
|
||||
> curl --data @- -X PUT --header 'etag: "13865833"' --dump - http://localhost:8529/_document/9496015:13658604?policy=last
|
||||
> curl --data @- -X PUT --header 'etag: "13865833"'
|
||||
> --dump - http://localhost:8529/collection/9496015:13658604?policy=last
|
||||
{ "Hallo" : "Me" }
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
|
|
|
@ -1,20 +1,12 @@
|
|||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "14755542"
|
||||
content-length: 27
|
||||
|
||||
{,"_id":"9496015:13658604"}
|
||||
|
||||
> curl --data @- -X PUT --dump - http://localhost:8529/_document/9496015:13658604?_rev=1234567
|
||||
> curl --data @- -X PUT
|
||||
> --dump - http://localhost:8529/collection/9496015:13658604?_rev=1234567
|
||||
{}
|
||||
|
||||
HTTP/1.1 409 Conflict
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 101
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658604 is been altered", "code" : 409}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015/13658604 is been altered",
|
||||
"code" : 409 }
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "14755542"
|
||||
content-length: 27
|
||||
|
||||
{,"_id":"9496015:13658604"}
|
||||
|
||||
> curl -X DELETE --header 'etag: "13865833"' --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X DELETE --header 'etag: "13865833"'
|
||||
> --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 409 Conflict
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 101
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658604 is been altered", "code" : 409}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015/13658604 has been altered",
|
||||
"code" : 409 }
|
||||
|
|
|
@ -1,17 +1,6 @@
|
|||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "14755542"
|
||||
content-length: 27
|
||||
|
||||
{"_id":"9496015:13658604"}
|
||||
|
||||
> curl -X DELETE --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X DELETE --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 204 No Content
|
||||
content-type: text/plain;charset=utf-8
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 0
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
> curl -X DELETE --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X DELETE --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 404 Not Found
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 95
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658604 not found", "code" : 404}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015/13658604 not found",
|
||||
"code" : 404 }
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
> curl --dump - http://localhost:8529/collection/145169/2176785
|
||||
HTTP/1.1 404 Not Found
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
|
||||
{ "error" : true,
|
||||
"message" : "collection /collection/145169 not found",
|
||||
"code" : 404 }
|
|
@ -0,0 +1,10 @@
|
|||
> curl -X GET --dump - http://localhost:8529/collection/example/9496015:13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13658605"
|
||||
|
||||
{ "Hallo" : "World",
|
||||
"_id" : "9496015:13658604",
|
||||
"_rev" : 13658605 }
|
|
@ -0,0 +1,7 @@
|
|||
> curl -X HEAD --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13658605"
|
||||
content-length: 0
|
|
@ -1,8 +1,9 @@
|
|||
> curl --dump - http://localhost:8529/_document/145168:2176785
|
||||
> curl --dump - http://localhost:8529/collection/145168/2176785
|
||||
HTTP/1.1 404 Not Found
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 94
|
||||
|
||||
{ "error" : true, "message" : "document /_document/145168:2176785 not found", "code" : 404}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/145168/2176785 not found",
|
||||
"code" : 404 }
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
> curl -X GET --dump - http://localhost:8529/collection/173560
|
||||
HTTP/1.1 200 OK
|
||||
connection: Keep-Alive
|
||||
content-type: application/json
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
|
||||
{ "documents" : [
|
||||
"/collection/173560/1973117",
|
||||
"/collection/173560/1854703",
|
||||
"/collection/173560/1946150",
|
||||
"/collection/173560/2075398",
|
||||
"/collection/173560/1680888"
|
||||
]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
> curl --data '@'- -X POST --dump - http://localhost:8529/_document/9496015
|
||||
> curl --data @- -X POST --dump - http://localhost:8529/collection/9496015
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
|
@ -6,5 +6,5 @@ content-type: text/plain;charset=utf-8
|
|||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13323664"
|
||||
location: /_document/9496015:13323664
|
||||
location: /collection/9496015/13323664
|
||||
content-length: 0
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
> curl --data '@'- -X POST --dump - http://localhost:8529/_document/9496016
|
||||
> curl --data @- -X POST --dump - http://localhost:8529/collection/9496016
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 404 Not Found
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 90
|
||||
|
||||
{ "error" : true, "message" : "collection /_collection/9496016 not found", "code" : 404}
|
||||
{ "error" : true,
|
||||
"message" : "collection /collection/9496016 not found",
|
||||
"code" : 404}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
> curl --data '@'- -X POST --dump - http://localhost:8529/_document/9496015
|
||||
> curl --data @- -X POST --dump - http://localhost:8529/collection/9496015
|
||||
{ Hallo }
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 71
|
||||
|
||||
{ "error" : true, "message" : "expecting attribute name", "code" : 400}
|
||||
{ "error" : true,
|
||||
"message" : "expecting attribute name",
|
||||
"code" : 400}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
> curl --data '@'- -X POST --dump - http://localhost:8529/_document/examples
|
||||
> curl --data @- -X POST --dump - http://localhost:8529/collection/examples
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
|
@ -6,5 +6,5 @@ content-type: text/plain;charset=utf-8
|
|||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13389200"
|
||||
location: /_document/9496015:13389200
|
||||
location: /collection/9496015/13389200
|
||||
content-length: 0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
> curl --data @- -X PUT --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl --data @- -X PUT --dump - http://localhost:8529/collection/9496015/13658604
|
||||
{ "Hallo" : "You" }
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
|
@ -8,12 +8,13 @@ server: triagens GmbH High-Performance HTTP Server
|
|||
etag: "13865832"
|
||||
content-length: 0
|
||||
|
||||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X GET --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13865832"
|
||||
content-length: 41
|
||||
|
||||
{"Hallo":"You","_id":"9496015:13658604"}
|
||||
{ "Hallo" : "You",
|
||||
"_id" : "9496015:13658604",
|
||||
"_rev" : 13865832 }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
> curl --data @- -X PUT --dump - http://localhost:8529/_document/9496015:13658605
|
||||
> curl --data @- -X PUT --dump - http://localhost:8529/collection/9496015/13658605
|
||||
{}
|
||||
|
||||
HTTP/1.1 404 Not Found
|
||||
|
@ -7,4 +7,6 @@ connection: Keep-Alive
|
|||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 95
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658605 not found", "code" : 404}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015/13658605 not found",
|
||||
"code" : 404 }
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
> curl -X GET --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl -X GET --dump - http://localhost:8529/collection/9496015/13658604
|
||||
HTTP/1.1 200 OK
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
etag: "13865832"
|
||||
content-length: 41
|
||||
|
||||
{"Hallo":"You","_id":"9496015:13658604"}
|
||||
{ "Hallo" : "You",
|
||||
"_id" : "9496015:13658604"
|
||||
"_rev" : 13865832 }
|
||||
|
||||
>curl --data @- -X PUT --header 'etag: "13865832"' --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl --data @- -X PUT --header 'etag: "13865832"'
|
||||
> --dump - http://localhost:8529/collection/9496015/13658604
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 204 No Content
|
||||
|
@ -18,13 +20,15 @@ server: triagens GmbH High-Performance HTTP Server
|
|||
etag: "14252313"
|
||||
content-length: 0
|
||||
|
||||
> curl --data @- -X PUT --header 'etag: "13865832"' --dump - http://localhost:8529/_document/9496015:13658604
|
||||
> curl --data @- -X PUT --header 'etag: "13865832"'
|
||||
> --dump - http://localhost:8529/_document/9496015/13658604
|
||||
{ "Hallo" : "World" }
|
||||
|
||||
HTTP/1.1 409 Conflict
|
||||
content-type: application/json
|
||||
connection: Keep-Alive
|
||||
server: triagens GmbH High-Performance HTTP Server
|
||||
content-length: 101
|
||||
|
||||
{ "error" : true, "message" : "document /_document/9496015:13658604 is been altered", "code" : 409}
|
||||
{ "error" : true,
|
||||
"message" : "document /collection/9496015/13658604 has been altered",
|
||||
"code" : 409 }
|
||||
|
|
|
@ -1 +1 @@
|
|||
{collection-name} {collection-alias}
|
||||
collection-name collection-alias
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
users u
|
||||
locations locs
|
||||
visitors v
|
||||
`select` s
|
||||
`select` `select`
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
avocado> db.examples.all().next();
|
||||
{ "age" : 4, "name" : "Name4", "_id" : "148759:2114839" }
|
||||
avocado> db.five.all().next();
|
||||
{ _id : 159896:1798296, _rev : 1798296, doc : 3 }
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
FROM users u
|
||||
WITHIN d = ( [ users.x, users.y ], [ 10.3, 40.5 ], 10000 )
|
||||
|
||||
FROM users u
|
||||
WITHIN d = ( users.x, users.y , 10.3, 40.5 , 10000 )
|
||||
|
||||
FROM users u
|
||||
WITHIN d = ( [ users.x, users.y ], [ 10.3, 40.5 ], 25 )
|
||||
|
||||
FROM users u
|
||||
WITHIN d = ( users.x, users.y, 10.3, 40.5, 25 )
|
|
@ -0,0 +1,5 @@
|
|||
FROM collection-name collection-alias
|
||||
WITHIN geo-alias = ( document-coordinate, reference-coordinate, radius )
|
||||
|
||||
FROM collection-name collection-alias
|
||||
NEAR geo-alias = ( document-coordinate, reference-coordinate, number-of-documents )
|
|
@ -1,3 +1,7 @@
|
|||
SELECT { name : u.name, latitude : locs.latitude ? locs.latitude : null, longitude : locs.longitude ? locs.longitude : null }
|
||||
FROM users u
|
||||
LEFT JOIN locations locs ON (u.id == locs.uid)
|
||||
|
||||
SELECT { name : u.name, latitude : locs.latitude ? locs.latitude : null, longitude : locs.longitude ? locs.longitude : null }
|
||||
FROM locations locs
|
||||
RIGHT JOIN users u ON (u.id == locs.uid)
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
SELECT { name: u.name } FROM users u WHERE u.name == 'Fox'
|
|
@ -0,0 +1,5 @@
|
|||
avocado> id = db.examples.save({ Hallo : "World" });
|
||||
"148759:5437094"
|
||||
|
||||
avocado> doc = db.examples.document(id);
|
||||
{ "Hallo" : "World", "_id" : "148759:5437094", "_rev" : 5437095 }
|
|
@ -0,0 +1,2 @@
|
|||
avocado> db.five.all().limit(2).count(true);
|
||||
2
|
|
@ -0,0 +1,2 @@
|
|||
avocado> edges.edges-collection.edges("195189:1702517");
|
||||
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]
|
|
@ -0,0 +1,2 @@
|
|||
avocado> edges.edges-collection.inEdges("195189:1833589");
|
||||
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]
|
|
@ -0,0 +1,2 @@
|
|||
avocado> edges.edges-collection.inEdges("195189:1702517");
|
||||
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]
|
|
@ -0,0 +1,14 @@
|
|||
avocado> db.geo.ensureGeoIndex("loc");
|
||||
162534834
|
||||
|
||||
avocado> for (i = -90; i <= 90; i += 10)
|
||||
.......> for (j = -180; j <= 180; j += 10)
|
||||
.......> db.geo.save({ name : "Name/" + i + "/" + j,
|
||||
.......> loc: [ i, j ] });
|
||||
|
||||
avocado> db.geo.count();
|
||||
703
|
||||
|
||||
avocado> db.geo.near(0,0).limit(2).toArray();
|
||||
[ { _id : 131840:24773376, _rev : 24773376, name : Name/0/0, loc : [ 0, 0 ] },
|
||||
{ _id : 131840:22348544, _rev : 22348544, name : Name/-10/0, loc : [ -10, 0 ] } ]
|
|
@ -0,0 +1,3 @@
|
|||
avocado> db.geo.near(0,0).distance().limit(2).toArray();
|
||||
[ { _id : 131840:24773376, _rev : 24773376, distance : 0, name : Name/0/0, loc : [ 0, 0 ] },
|
||||
{ _id : 131840:22348544, _rev : 22348544, distance : 1111949.3, name : Name/-10/0, loc : [ -10, 0 ] } ]
|
|
@ -0,0 +1,27 @@
|
|||
avocado> for (i = -90; i <= 90; i += 10)
|
||||
.......> for (j = -180; j <= 180; j += 10)
|
||||
.......> db.complex.save({ name : "Name/" + i + "/" + j,
|
||||
.......> home : [ i, j ],
|
||||
.......> work : [ -i, -j ] });
|
||||
|
||||
avocado> db.complex.near(0, 170).limit(5);
|
||||
exception in file '/simple-query' at 1018,5: an geo-index must be known
|
||||
|
||||
avocado> db.complex.ensureGeoIndex("home");
|
||||
avocado> db.complex.near(0, 170).limit(5).toArray();
|
||||
[ { _id : 48834092:74655276, _rev : 74655276, name : Name/0/170, home : [ 0, 170 ], work : [ 0, -170 ] },
|
||||
{ _id : 48834092:74720812, _rev : 74720812, name : Name/0/180, home : [ 0, 180 ], work : [ 0, -180 ] },
|
||||
{ _id : 48834092:77080108, _rev : 77080108, name : Name/10/170, home : [ 10, 170 ], work : [ -10, -170 ] },
|
||||
{ _id : 48834092:72230444, _rev : 72230444, name : Name/-10/170, home : [ -10, 170 ], work : [ 10, -170 ] },
|
||||
{ _id : 48834092:72361516, _rev : 72361516, name : Name/0/-180, home : [ 0, -180 ], work : [ 0, 180 ] } ]
|
||||
|
||||
avocado> db.complex.geo("work").near(0, 170).limit(5);
|
||||
exception in file '/simple-query' at 1018,5: an geo-index must be known
|
||||
|
||||
avocado> db.complex.ensureGeoIndex("work");
|
||||
avocado> db.complex.geo("work").near(0, 170).limit(5).toArray();
|
||||
[ { _id : 48834092:72427052, _rev : 72427052, name : Name/0/-170, home : [ 0, -170 ], work : [ 0, 170 ] },
|
||||
{ _id : 48834092:72361516, _rev : 72361516, name : Name/0/-180, home : [ 0, -180 ], work : [ 0, 180 ] },
|
||||
{ _id : 48834092:70002220, _rev : 70002220, name : Name/-10/-170, home : [ -10, -170 ], work : [ 10, 170 ] },
|
||||
{ _id : 48834092:74851884, _rev : 74851884, name : Name/10/-170, home : [ 10, -170 ], work : [ -10, 170 ] },
|
||||
{ _id : 48834092:74720812, _rev : 74720812, name : Name/0/180, home : [ 0, 180 ], work : [ 0, -180 ] } ]
|
|
@ -0,0 +1,10 @@
|
|||
avocado> db.geo.within(0, 0, 2000 * 1000).distance().toArray();
|
||||
[ { _id : 131840:24773376, _rev : 24773376, distance : 0, name : Name/0/0, loc : [ 0, 0 ] },
|
||||
{ _id : 131840:24707840, _rev : 24707840, distance : 1111949.3, name : Name/0/-10, loc : [ 0, -10 ] },
|
||||
{ _id : 131840:24838912, _rev : 24838912, distance : 1111949.3, name : Name/0/10, loc : [ 0, 10 ] },
|
||||
{ _id : 131840:22348544, _rev : 22348544, distance : 1111949.3, name : Name/-10/0, loc : [ -10, 0 ] },
|
||||
{ _id : 131840:27198208, _rev : 27198208, distance : 1111949.3, name : Name/10/0, loc : [ 10, 0 ] },
|
||||
{ _id : 131840:22414080, _rev : 22414080, distance : 1568520.6, name : Name/-10/10, loc : [ -10, 10 ] },
|
||||
{ _id : 131840:27263744, _rev : 27263744, distance : 1568520.6, name : Name/10/10, loc : [ 10, 10 ] },
|
||||
{ _id : 131840:22283008, _rev : 22283008, distance : 1568520.6, name : Name/-10/-10, loc : [ -10, -10 ] },
|
||||
{ _id : 131840:27132672, _rev : 27132672, distance : 1568520.6, name : Name/10/-10, loc : [ 10, -10 ] } ]
|
|
@ -0,0 +1,14 @@
|
|||
avocado> db.five.all().toArray();
|
||||
[ { _id : 159896:1798296, _rev : 1798296, doc : 3 },
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 },
|
||||
{ _id : 159896:1863832, _rev : 1863832, doc : 4 },
|
||||
{ _id : 159896:1667224, _rev : 1667224, doc : 1 },
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]
|
||||
|
||||
avocado> db.five.all().limit(2).toArray();
|
||||
[ { _id : 159896:1798296, _rev : 1798296, doc : 3 },
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 } ]
|
||||
|
||||
avocado> db.five.all().limit(-2);
|
||||
[ { _id : 159896:1667224, _rev : 1667224, doc : 1 },
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]
|
|
@ -0,0 +1,6 @@
|
|||
avocado> db.five.all().toArray();
|
||||
[ { _id : 159896:1798296, _rev : 1798296, doc : 3 },
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 },
|
||||
{ _id : 159896:1863832, _rev : 1863832, doc : 4 },
|
||||
{ _id : 159896:1667224, _rev : 1667224, doc : 1 },
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]
|
|
@ -0,0 +1,7 @@
|
|||
avocado> var a = db.five.all();
|
||||
avocado> while (a.hasNext()) print(a.next());
|
||||
{ _id : 159896:1798296, _rev : 1798296, doc : 3 }
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 }
|
||||
{ _id : 159896:1863832, _rev : 1863832, doc : 4 }
|
||||
{ _id : 159896:1667224, _rev : 1667224, doc : 1 }
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 }
|
|
@ -0,0 +1,2 @@
|
|||
avocado> db.five.all().next();
|
||||
{ _id : 159896:1798296, _rev : 1798296, doc : 3 }
|
|
@ -0,0 +1,2 @@
|
|||
avocado> db.five.all().nextRef();
|
||||
159896:1798296
|
|
@ -0,0 +1,7 @@
|
|||
avocado> var a = db.five.all();
|
||||
avocado> while (a.hasNext()) print(a.next());
|
||||
{ _id : 159896:1798296, _rev : 1798296, doc : 3 }
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 }
|
||||
{ _id : 159896:1863832, _rev : 1863832, doc : 4 }
|
||||
{ _id : 159896:1667224, _rev : 1667224, doc : 1 }
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 }
|
|
@ -0,0 +1,10 @@
|
|||
avocado> db.five.all().toArray();
|
||||
[ { _id : 159896:1798296, _rev : 1798296, doc : 3 },
|
||||
{ _id : 159896:1732760, _rev : 1732760, doc : 2 },
|
||||
{ _id : 159896:1863832, _rev : 1863832, doc : 4 },
|
||||
{ _id : 159896:1667224, _rev : 1667224, doc : 1 },
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]
|
||||
|
||||
avocado> db.five.all().skip(3).toArray();
|
||||
[ { _id : 159896:1667224, _rev : 1667224, doc : 1 },
|
||||
{ _id : 159896:1929368, _rev : 1929368, doc : 5 } ]
|
|
@ -0,0 +1,2 @@
|
|||
avocado> db.five.all().limit(2).count();
|
||||
5
|
|
@ -8,5 +8,6 @@ pandoc -f markdown -t markdown -o $OUTPUT.tmp $INPUT || exit 1
|
|||
cat $OUTPUT.tmp \
|
||||
| sed -e 's:\(GET\|PUT\|DELETE\|POST\) /\\_:\1 /_:g' \
|
||||
| sed -e 's:^/\\_:/_:g' \
|
||||
| sed -e 's:<tt>\*:<tt>_:g' \
|
||||
> $OUTPUT || exit 1
|
||||
rm -f $OUTPUT.tmp
|
||||
|
|
|
@ -126,8 +126,10 @@ replDict["e_row"] = ""
|
|||
|
||||
replDict["s_sect1"] = ""
|
||||
replDict["s_sect2"] = ""
|
||||
replDict["s_sect3"] = ""
|
||||
replDict["e_sect1"] = ""
|
||||
replDict["e_sect2"] = ""
|
||||
replDict["e_sect3"] = ""
|
||||
|
||||
replDict["s_table"] = "\n{| %s\n" % table_format
|
||||
replDict["e_table"] = "\n|}\n"
|
||||
|
@ -135,9 +137,11 @@ replDict["e_table"] = "\n|}\n"
|
|||
replDict["s_title_1"] = "# "
|
||||
replDict["s_title_2"] = "## "
|
||||
replDict["s_title_3"] = "### "
|
||||
replDict["s_title_4"] = "#### "
|
||||
replDict["e_title_1"] = "\n\n"
|
||||
replDict["e_title_2"] = "\n\n"
|
||||
replDict["e_title_3"] = "\n\n"
|
||||
replDict["e_title_4"] = "\n\n"
|
||||
|
||||
replDict["s_ulink"] = "["
|
||||
replDict["e_ulink"] = "]"
|
||||
|
@ -183,12 +187,14 @@ gencDict["row"] = True
|
|||
|
||||
gencDict["sect1"] = False
|
||||
gencDict["sect2"] = False
|
||||
gencDict["sect3"] = False
|
||||
|
||||
gencDict["table"] = True
|
||||
|
||||
gencDict["title_1"] = True
|
||||
gencDict["title_2"] = True
|
||||
gencDict["title_3"] = True
|
||||
gencDict["title_4"] = True
|
||||
|
||||
gencDict["ulink"] = True
|
||||
|
||||
|
@ -225,7 +231,7 @@ path = []
|
|||
gencode = []
|
||||
|
||||
################################################################################
|
||||
#### @brief titel level (sect1, sect2)
|
||||
#### @brief titel level (sect1, sect2, sect3)
|
||||
################################################################################
|
||||
|
||||
titlevel = 1
|
||||
|
@ -271,6 +277,7 @@ def start_element(name, attrs):
|
|||
|
||||
if name == "sect1": titlevel = 2
|
||||
elif name == "sect2": titlevel = 3
|
||||
elif name == "sect3": titlevel = 4
|
||||
elif name == "entry": tabentry = True
|
||||
elif name == "verbatim": verbatim = True
|
||||
elif name == "itemizedlist": listlevel = listlevel + 1
|
||||
|
@ -293,7 +300,7 @@ def start_element(name, attrs):
|
|||
genc = gencDict["%s" % name]
|
||||
#endif
|
||||
|
||||
if name == "sect1" or name == "sect2":
|
||||
if name == "sect1" or name == "sect2" or name == "sect3":
|
||||
text += "<a name=\"%s\"></a>\n\n" % convert_link(attrs['id'], True)
|
||||
|
||||
gencode.append(genc)
|
||||
|
@ -331,6 +338,7 @@ def end_element(name):
|
|||
|
||||
if name == "sect1": titlevel = 1
|
||||
elif name == "sect2": titlevel = 2
|
||||
elif name == "sect3": titlevel = 3
|
||||
elif name == "listitem": listitem = False
|
||||
elif name == "entry": tabentry = False
|
||||
elif name == "verbatim": verbatim = False
|
||||
|
|
|
@ -206,6 +206,7 @@ ALIASES += CMDOPT{1}="<tt><b>\1</b></tt>"
|
|||
ALIASES += CA{1}="<var>\1</var>"
|
||||
ALIASES += CO{1}="<tt>\1</tt>"
|
||||
ALIASES += REST{1}="<tt><b>\1</b></tt>"
|
||||
ALIASES += EXAMPLES="<b>Examples</b><br>"
|
||||
|
||||
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
|
||||
# sources only. Doxygen will then generate output that is more tailored for C.
|
||||
|
|
|
@ -216,13 +216,15 @@ void dummy_251 ();
|
|||
/// <li>@ref JSModuleInternalLoad "internal.load"</li>
|
||||
/// <li>@ref JSModuleInternalLogLevel "internal.log"</li>
|
||||
/// <li>@ref JSModuleInternalLogLevel "internal.logLevel"</li>
|
||||
/// <li>@ref JSModuleInternalOutput "internal.output"</li>
|
||||
/// <li>@ref JSModuleInternalProcessStat "internal.processStat"</li>
|
||||
/// <li>@ref JSModuleInternalRead "internal.read"</li>
|
||||
/// <li>@ref JSModuleInternalSPrintF "internal.sprintf"</li>
|
||||
/// <li>@ref JSModuleInternalTime "internal.time"</li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_265 ();
|
||||
void dummy_267 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleInternal Module "internal"
|
||||
|
@ -245,6 +247,9 @@ void dummy_265 ();
|
|||
/// @anchor JSModuleInternalLogLevel
|
||||
/// @copydetails JS_LogLevel
|
||||
///
|
||||
/// @anchor JSModuleInternalOutput
|
||||
/// @copydetails JS_Output
|
||||
///
|
||||
/// @anchor JSModuleInternalRead
|
||||
/// @copydetails JS_Read
|
||||
///
|
||||
|
@ -255,21 +260,21 @@ void dummy_265 ();
|
|||
/// @copydetails JS_Time
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_296 ();
|
||||
void dummy_301 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleInternal
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_301 ();
|
||||
void dummy_306 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief internal module
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void dummy_316 ();
|
||||
void dummy_322 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads a file
|
||||
|
@ -297,13 +302,13 @@ void JSF_internal_loadFile (int path) {}
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_376 ();
|
||||
void dummy_382 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "console"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_380 ();
|
||||
void dummy_386 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleConsoleTOC
|
||||
|
@ -317,7 +322,7 @@ void dummy_380 ();
|
|||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_392 ();
|
||||
void dummy_398 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleConsole Module "console"
|
||||
|
@ -345,14 +350,14 @@ void dummy_392 ();
|
|||
/// @copydetails JSF_CONSOLE_WARN
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_418 ();
|
||||
void dummy_424 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleConsole
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_423 ();
|
||||
void dummy_429 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logs debug message
|
||||
|
@ -426,13 +431,13 @@ void JSF_CONSOLE_WARN () {}
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void dummy_522 ();
|
||||
void dummy_528 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_526 ();
|
||||
void dummy_532 ();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -49,7 +49,7 @@ void dummy_39 ();
|
|||
/// Only available in shell mode.
|
||||
///
|
||||
/// Prints the arguments. If an argument is an object having a
|
||||
/// function @FN{PRINT}, then this function is called. Otherwise @FN{toJson} is
|
||||
/// function @FN{_PRINT}, then this function is called. Otherwise @FN{toJson} is
|
||||
/// used. A final newline is printed
|
||||
///
|
||||
/// @verbinclude fluent40
|
||||
|
@ -92,11 +92,12 @@ void dummy_124 ();
|
|||
/// @brief JSON representation of an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_Array_prototype_PRINT (int seen, int path, int names) {}
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_147 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -120,7 +121,8 @@ void dummy_160 ();
|
|||
/// @brief prints a function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_Function_prototype_PRINT (int ) {}
|
||||
|
||||
void dummy_168 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -376,7 +376,8 @@ void dummy_435 ();
|
|||
/// @brief edge printing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_Edge_prototype_PRINT (int seen, int path, int names) {}
|
||||
|
||||
void dummy_448 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -672,7 +673,8 @@ void dummy_879 ();
|
|||
/// @brief vertex representation
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_Vertex_prototype_PRINT (int seen, int path, int names) {}
|
||||
|
||||
void dummy_892 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
@ -833,7 +835,6 @@ void JSF_iterator (int ) {}
|
|||
|
||||
|
||||
|
||||
void JSF_this_PRINT (int seen, int path, int names) {}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -856,7 +857,6 @@ void JSF_iterator (int ) {}
|
|||
|
||||
|
||||
|
||||
void JSF_this_PRINT (int seen, int path, int names) {}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -927,7 +927,8 @@ void JSF_Graph_prototype_constructEdge (int id) {}
|
|||
/// @brief graph printing
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_Graph_prototype_PRINT (int seen, int path, int names) {}
|
||||
|
||||
void dummy_1256 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
||||
/// Copyright 2011-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
|
@ -22,36 +22,109 @@
|
|||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. Frank Celler
|
||||
/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany
|
||||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_28 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleAvocadoTOC
|
||||
///
|
||||
/// <ol>
|
||||
/// <li>@ref JSModuleAvocadoDefineHttpSystemAction "avocado.defineHttpSystemAction"</li>
|
||||
/// </ol>
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_36 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page JSModuleAvocado Module "avocado"
|
||||
///
|
||||
/// The following functions are used avocadoly.
|
||||
///
|
||||
/// <hr>
|
||||
/// @copydoc JSModuleAvocadoTOC
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor JSModuleAvocadoDefineHttpSystemAction
|
||||
/// @copydetails JS_DefineSystemAction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_49 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module
|
||||
// --SECTION-- Module "internal"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_32 ();
|
||||
void dummy_53 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleInternal
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_37 ();
|
||||
void dummy_58 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief internal module
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void dummy_46 ();
|
||||
void dummy_67 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_50 ();
|
||||
void dummy_71 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "avocado"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_75 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleAvocado
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_80 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief avocado module
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_92 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_96 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- Module "simple-query"
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_100 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8ModuleSimpleQuery
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void dummy_112 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_116 ();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -59,34 +59,44 @@ void dummy_51 ();
|
|||
/// @brief prints a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_AvocadoFluentQuery_prototype_PRINT (int ) {}
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_79 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief prints a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_AvocadoFluentQuery2_prototype_PRINT (int ) {}
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_107 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief prints a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSF_AvocadoCursor_prototype_PRINT (int ) {}
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_135 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief prints a shaped json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void dummy_148 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_139 ();
|
||||
void dummy_152 ();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -25,20 +25,21 @@
|
|||
/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_28 ();
|
||||
|
||||
void dummy_30 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- administration actions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_32 ();
|
||||
void dummy_34 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ActionsAdmin
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_37 ();
|
||||
void dummy_39 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all collections
|
||||
|
@ -61,12 +62,13 @@ void dummy_37 ();
|
|||
/// @verbinclude rest15
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSA_collections () {}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void dummy_87 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief loads a collection
|
||||
///
|
||||
|
@ -77,9 +79,10 @@ void JSA_collections () {}
|
|||
/// @verbinclude restX
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSA_collection_load () {}
|
||||
|
||||
|
||||
void dummy_115 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief information about a collection
|
||||
///
|
||||
|
@ -90,22 +93,24 @@ void JSA_collection_load () {}
|
|||
/// @verbinclude rest16
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSA_collection_info () {}
|
||||
|
||||
|
||||
void dummy_147 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all documents
|
||||
///
|
||||
/// @REST{GET /_system/documents}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSA_documents () {}
|
||||
|
||||
void dummy_166 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_168 ();
|
||||
void dummy_170 ();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -25,20 +25,21 @@
|
|||
/// @author Copyright 2011, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_28 ();
|
||||
|
||||
void dummy_30 ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- administration actions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void dummy_32 ();
|
||||
void dummy_34 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup ActionsAdmin
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_37 ();
|
||||
void dummy_39 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all indexes of a collection
|
||||
|
@ -48,14 +49,15 @@ void dummy_37 ();
|
|||
/// Returns information about all indexes of a collection of the database.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void JSA_collection_indexes () {}
|
||||
|
||||
|
||||
void dummy_68 ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void dummy_70 ();
|
||||
void dummy_72 ();
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
|
|
|
@ -92,11 +92,11 @@ namespace triagens {
|
|||
|
||||
// directly execute the handler within the scheduler thread
|
||||
if (handler->isDirect()) {
|
||||
Handler::status_e status = handleRequestDirectly(task, handler);
|
||||
Handler::status_e status = this->handleRequestDirectly(task, handler);
|
||||
|
||||
if (status != Handler::HANDLER_REQUEUE) {
|
||||
done = true;
|
||||
destroyHandler(handler);
|
||||
this->destroyHandler(handler);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
|
@ -109,7 +109,7 @@ namespace triagens {
|
|||
|
||||
if (atask == 0) {
|
||||
LOGGER_WARNING << "task is indirect, but not asynchronous";
|
||||
destroyHandler(handler);
|
||||
this->destroyHandler(handler);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
@ -127,7 +127,7 @@ namespace triagens {
|
|||
else {
|
||||
LOGGER_WARNING << "no dispatcher is known";
|
||||
|
||||
destroyHandler(handler);
|
||||
this->destroyHandler(handler);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief geo index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author R. A. Parker
|
||||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
///// @brief geo index
|
||||
/////
|
||||
///// @file
|
||||
/////
|
||||
///// DISCLAIMER
|
||||
/////
|
||||
///// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
/////
|
||||
///// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
///// you may not use this file except in compliance with the License.
|
||||
///// You may obtain a copy of the License at
|
||||
/////
|
||||
///// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/////
|
||||
///// Unless required by applicable law or agreed to in writing, software
|
||||
///// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
///// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
///// See the License for the specific language governing permissions and
|
||||
///// limitations under the License.
|
||||
/////
|
||||
///// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
/////
|
||||
///// @author R. A. Parker
|
||||
///// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* GeoIndex.c - GeoIndex algorithms */
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief geo index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author R. A. Parker
|
||||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
///// @brief geo index
|
||||
/////
|
||||
///// @file
|
||||
/////
|
||||
///// DISCLAIMER
|
||||
/////
|
||||
///// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
/////
|
||||
///// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
///// you may not use this file except in compliance with the License.
|
||||
///// You may obtain a copy of the License at
|
||||
/////
|
||||
///// http://www.apache.org/licenses/LICENSE-2.0
|
||||
/////
|
||||
///// Unless required by applicable law or agreed to in writing, software
|
||||
///// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
///// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
///// See the License for the specific language governing permissions and
|
||||
///// limitations under the License.
|
||||
/////
|
||||
///// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
/////
|
||||
///// @author R. A. Parker
|
||||
///// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* GeoIndex.h - header file for GeoIndex algorithms */
|
||||
|
@ -37,6 +37,10 @@
|
|||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* first the things that a user might want to change */
|
||||
|
||||
/* a GeoString - a signed type of at least 64 bits */
|
||||
|
@ -113,4 +117,8 @@ void GeoIndex_INDEXDUMP(GeoIndex * gi, FILE * f);
|
|||
int GeoIndex_INDEXVALID(GeoIndex * gi);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* end of GeoIndex.h */
|
||||
|
|
|
@ -0,0 +1,651 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief geo index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright by triAGENS GmbH - All rights reserved.
|
||||
///
|
||||
/// The Programs (which include both the software and documentation)
|
||||
/// contain proprietary information of triAGENS GmbH; they are
|
||||
/// provided under a license agreement containing restrictions on use and
|
||||
/// disclosure and are also protected by copyright, patent and other
|
||||
/// intellectual and industrial property laws. Reverse engineering,
|
||||
/// disassembly or decompilation of the Programs, except to the extent
|
||||
/// required to obtain interoperability with other independently created
|
||||
/// software or as specified by law, is prohibited.
|
||||
///
|
||||
/// The Programs are not intended for use in any nuclear, aviation, mass
|
||||
/// transit, medical, or other inherently dangerous applications. It shall
|
||||
/// be the licensee's responsibility to take all appropriate fail-safe,
|
||||
/// backup, redundancy, and other measures to ensure the safe use of such
|
||||
/// applications if the Programs are used for such purposes, and triAGENS
|
||||
/// GmbH disclaims liability for any damages caused by such use of
|
||||
/// the Programs.
|
||||
///
|
||||
/// This software is the confidential and proprietary information of
|
||||
/// triAGENS GmbH. You shall not disclose such confidential and
|
||||
/// proprietary information and shall use it only in accordance with the
|
||||
/// terms of the license agreement you entered into with triAGENS GmbH.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. O
|
||||
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hashindex.h"
|
||||
|
||||
static bool isEqualJsonJson (const TRI_json_t* left, const TRI_json_t* right) {
|
||||
|
||||
if (left == NULL && right == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (left == NULL && right != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left != NULL && right == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left->_type != right->_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (left->_type) {
|
||||
|
||||
case TRI_JSON_UNUSED: {
|
||||
return true;
|
||||
}
|
||||
|
||||
case TRI_JSON_NULL: {
|
||||
return true;
|
||||
}
|
||||
|
||||
case TRI_JSON_BOOLEAN: {
|
||||
return ( left->_value._boolean == right->_value._boolean );
|
||||
}
|
||||
|
||||
case TRI_JSON_NUMBER: {
|
||||
return ( left->_value._number == right->_value._number );
|
||||
}
|
||||
|
||||
|
||||
case TRI_JSON_STRING: {
|
||||
if (left->_value._string.length == right->_value._string.length) {
|
||||
return (memcmp(left->_value._string.data, right->_value._string.data,
|
||||
left->_value._string.length) == 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
case TRI_JSON_ARRAY: {
|
||||
// order not defined here -- need special case here
|
||||
if (left->_value._objects._length != right->_value._objects._length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < left->_value._objects._length; ++j) {
|
||||
if (!isEqualJsonJson( (TRI_json_t*)(TRI_AtVector(&(left->_value._objects),j)),
|
||||
(TRI_json_t*)(TRI_AtVector(&(right->_value._objects),j))
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case TRI_JSON_LIST: {
|
||||
|
||||
if (left->_value._objects._length != right->_value._objects._length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < left->_value._objects._length; ++j) {
|
||||
if (!isEqualJsonJson( (TRI_json_t*)(TRI_AtVector(&(left->_value._objects),j)),
|
||||
(TRI_json_t*)(TRI_AtVector(&(right->_value._objects),j))
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // end of switch statement
|
||||
assert(false);
|
||||
return false;
|
||||
} // end of function isEqualJsonJson
|
||||
|
||||
|
||||
static bool isEqualShapedJsonShapedJson (const TRI_shaped_json_t* left, const TRI_shaped_json_t* right) {
|
||||
|
||||
int result;
|
||||
|
||||
if (left == NULL && right == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (left == NULL && right != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left != NULL && right == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (left->_data.length != right->_data.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ( memcmp(left->_data.data,right->_data.data, left->_data.length) == 0);
|
||||
} // end of function isEqualShapedJsonShapedJson
|
||||
|
||||
|
||||
static uint64_t hashJson (const size_t hash, const TRI_json_t* data) {
|
||||
|
||||
size_t newHash;
|
||||
|
||||
if (data == NULL) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
switch (data->_type) {
|
||||
|
||||
case TRI_JSON_UNUSED: {
|
||||
return hash;
|
||||
}
|
||||
|
||||
case TRI_JSON_NULL: {
|
||||
return hash;
|
||||
}
|
||||
|
||||
case TRI_JSON_BOOLEAN: {
|
||||
return TRI_FnvHashBlock(hash, (const char*)(&(data->_value._boolean)), sizeof(bool));
|
||||
// return TRI_BlockCrc32(hash, (const char*)(&(data->_value._boolean)), sizeof(bool));
|
||||
}
|
||||
|
||||
case TRI_JSON_NUMBER: {
|
||||
return TRI_FnvHashBlock(hash, (const char*)(&(data->_value._number)), sizeof(double));
|
||||
//return TRI_BlockCrc32(hash, (const char*)(&(data->_value._number)), sizeof(double));
|
||||
}
|
||||
|
||||
case TRI_JSON_STRING: {
|
||||
if (data->_value._string.length > 0) {
|
||||
return TRI_FnvHashBlock(hash, data->_value._string.data, data->_value._string.length);
|
||||
//return TRI_BlockCrc32(hash, data->_value._string.data, data->_value._string.length);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
case TRI_JSON_ARRAY: {
|
||||
// order not defined here -- need special case here
|
||||
if (data->_value._objects._length > 0) {
|
||||
newHash = hash;
|
||||
for (size_t j = 0; j < data->_value._objects._length; ++j) {
|
||||
newHash = hashJson(newHash, (TRI_json_t*)(TRI_AtVector(&(data->_value._objects),j)) );
|
||||
}
|
||||
return newHash;
|
||||
}
|
||||
else {
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
case TRI_JSON_LIST: {
|
||||
if (data->_value._objects._length > 0) {
|
||||
newHash = hash;
|
||||
for (size_t j = 0; j < data->_value._objects._length; ++j) {
|
||||
newHash = hashJson(newHash, (TRI_json_t*)(TRI_AtVector(&(data->_value._objects),j)) );
|
||||
}
|
||||
return newHash;
|
||||
}
|
||||
else {
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
} // end of switch statement
|
||||
assert(false);
|
||||
return hash;
|
||||
} // end of function isEqualJsonJson
|
||||
|
||||
|
||||
static uint64_t hashShapedJson (const uint64_t hash, const TRI_shaped_json_t* shapedJson) {
|
||||
return TRI_FnvHashBlock(hash, shapedJson->_data.data, shapedJson->_data.length);
|
||||
} // end of function hashShapedJson
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// marks an element in the unique assoc array as being 'cleared' or 'empty'
|
||||
// .............................................................................
|
||||
static void clearElement(struct TRI_associative_array_s* associativeArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
if (element != NULL) {
|
||||
hElement->data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// returns true if an element in the unique assoc array is 'empty'
|
||||
// .............................................................................
|
||||
static bool isEmptyElement (struct TRI_associative_array_s* associativeArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
if (element != NULL) {
|
||||
if (hElement->data == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Determines if two elements of the unique assoc array are equal
|
||||
// Two elements are 'equal' if the shaped json content is equal.
|
||||
// .............................................................................
|
||||
static bool isEqualElementElement (struct TRI_associative_array_s* associativeArray,
|
||||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hLeftElement->numFields != hRightElement->numFields) {
|
||||
return false; // should never happen
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < hLeftElement->numFields; j++) {
|
||||
if (!isEqualShapedJsonShapedJson((j + hLeftElement->fields), (j + hRightElement->fields))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Determines if two elements of the unique assoc array are equal
|
||||
// Two elements are 'equal' if the shaped json content is equal.
|
||||
// .............................................................................
|
||||
static bool isEqualKeyElement (struct TRI_associative_array_s* associativeArray,
|
||||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hLeftElement->numFields != hRightElement->numFields) {
|
||||
return false; // should never happen
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < hLeftElement->numFields; j++) {
|
||||
if (!isEqualShapedJsonShapedJson((j + hLeftElement->fields), (j + hRightElement->fields))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// The actual hashing occurs here
|
||||
// .............................................................................
|
||||
static uint64_t hashElement (struct TRI_associative_array_s* associativeArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
uint64_t hash = TRI_FnvHashBlockInitial();
|
||||
for (size_t j = 0; j < hElement->numFields; j++) {
|
||||
hash = hashShapedJson(hash, (j + hElement->fields) );
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t hashKey (struct TRI_associative_array_s* associativeArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
uint64_t hash = TRI_FnvHashBlockInitial();
|
||||
for (size_t j = 0; j < hElement->numFields; j++) {
|
||||
hash = hashShapedJson(hash, (j + hElement->fields) );
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Creates a new associative array
|
||||
// .............................................................................
|
||||
|
||||
HashIndex* HashIndex_new() {
|
||||
HashIndex* hashIndex;
|
||||
|
||||
hashIndex = TRI_Allocate(sizeof(HashIndex));
|
||||
if (hashIndex == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashIndex->unique = true;
|
||||
hashIndex->assocArray.uniqueArray = TRI_Allocate(sizeof(TRI_associative_array_t));
|
||||
if (hashIndex->assocArray.uniqueArray == NULL) {
|
||||
TRI_Free(hashIndex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_InitAssociativeArray(hashIndex->assocArray.uniqueArray,
|
||||
sizeof(HashIndexElement),
|
||||
hashKey,
|
||||
hashElement,
|
||||
clearElement,
|
||||
isEmptyElement,
|
||||
isEqualKeyElement,
|
||||
isEqualElementElement);
|
||||
|
||||
return hashIndex;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Adds (inserts) a data element into the associative array (hash index)
|
||||
// ...............................................................................
|
||||
|
||||
int HashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
result = TRI_InsertElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, false);
|
||||
if (result) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Locates an entry within the unique associative array
|
||||
// ...............................................................................
|
||||
|
||||
HashIndexElements* HashIndex_find(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
HashIndexElement* result;
|
||||
HashIndexElements* results;
|
||||
|
||||
results = TRI_Allocate(sizeof(HashIndexElements));
|
||||
|
||||
result = (HashIndexElement*) (TRI_FindByElementAssociativeArray(hashIndex->assocArray.uniqueArray, element));
|
||||
|
||||
if (result != NULL) {
|
||||
results->_elements = TRI_Allocate(sizeof(HashIndexElement) * 1); // unique hash index maximum number is 1
|
||||
results->_elements[0] = *result;
|
||||
results->_numElements = 1;
|
||||
}
|
||||
else {
|
||||
results->_elements = NULL;
|
||||
results->_numElements = 0;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// An alias for addIndex
|
||||
// ...............................................................................
|
||||
|
||||
int HashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
return HashIndex_add(hashIndex,element);
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Removes an entry from the associative array
|
||||
// ...............................................................................
|
||||
|
||||
bool HashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
|
||||
result = TRI_RemoveElementAssociativeArray(hashIndex->assocArray.uniqueArray, element, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// updates and entry from the associative array, first removes beforeElement,
|
||||
// then adds the afterElement
|
||||
// ...............................................................................
|
||||
|
||||
bool HashIndex_update(HashIndex* hashIndex, const HashIndexElement* beforeElement,
|
||||
const HashIndexElement* afterElement) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Multi-hash non-unique hash indexes
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Marks an entry in the non-unique associative array as being 'cleared'.
|
||||
// .............................................................................
|
||||
static void multiClearElement(struct TRI_multi_array_s* multiArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
if (element != NULL) {
|
||||
hElement->data = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Determines if an entry in the associative array is marked as being empty (cleared)
|
||||
// .............................................................................
|
||||
static bool isMultiEmptyElement (struct TRI_multi_array_s* multiArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
if (element != NULL) {
|
||||
if (hElement->data == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Returns true if document pointers are the same, otherwise returns false
|
||||
// .............................................................................
|
||||
static bool isMultiEqualElementElement (struct TRI_multi_array_s* multiArray,
|
||||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
int result;
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (hLeftElement->data == hRightElement->data);
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Returns true if the "key" matches that of the element
|
||||
// .............................................................................
|
||||
static bool isMultiEqualKeyElement (struct TRI_multi_array_s* multiArray,
|
||||
void* leftElement, void* rightElement) {
|
||||
HashIndexElement* hLeftElement = (HashIndexElement*)(leftElement);
|
||||
HashIndexElement* hRightElement = (HashIndexElement*)(rightElement);
|
||||
int result;
|
||||
|
||||
if (leftElement == NULL || rightElement == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hLeftElement->numFields != hRightElement->numFields) {
|
||||
return false; // should never happen
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < hLeftElement->numFields; j++) {
|
||||
TRI_shaped_json_t* left = (j + hLeftElement->fields);
|
||||
TRI_shaped_json_t* right = (j + hRightElement->fields);
|
||||
if (!isEqualShapedJsonShapedJson(left, right)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// The actual hashing occurs here
|
||||
// .............................................................................
|
||||
static uint64_t multiHashElement (struct TRI_multi_array_s* multiArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
uint64_t hash = TRI_FnvHashBlockInitial();
|
||||
for (size_t j = 0; j < hElement->numFields; j++) {
|
||||
hash = hashShapedJson(hash, (j + hElement->fields) );
|
||||
//printf("%s:%u:%u:%f\n",__FILE__,__LINE__,hash, *((double*)((j + hElement->fields)->_data.data)));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
static uint64_t multiHashKey (struct TRI_multi_array_s* multiArray, void* element) {
|
||||
HashIndexElement* hElement = (HashIndexElement*)(element);
|
||||
uint64_t hash = TRI_FnvHashBlockInitial();
|
||||
for (size_t j = 0; j < hElement->numFields; j++) {
|
||||
hash = hashShapedJson(hash, (j + hElement->fields) );
|
||||
//printf("%s:%u:%u:%f\n",__FILE__,__LINE__,hash, *((double*)((j + hElement->fields)->_data.data)));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// .............................................................................
|
||||
// Creates a new multi associative array
|
||||
// .............................................................................
|
||||
|
||||
HashIndex* MultiHashIndex_new() {
|
||||
HashIndex* hashIndex;
|
||||
|
||||
hashIndex = TRI_Allocate(sizeof(HashIndex));
|
||||
if (hashIndex == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hashIndex->unique = false;
|
||||
hashIndex->assocArray.nonUniqueArray = TRI_Allocate(sizeof(TRI_multi_array_t));
|
||||
if (hashIndex->assocArray.nonUniqueArray == NULL) {
|
||||
TRI_Free(hashIndex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_InitMultiArray(hashIndex->assocArray.nonUniqueArray,
|
||||
sizeof(HashIndexElement),
|
||||
multiHashKey,
|
||||
multiHashElement,
|
||||
multiClearElement,
|
||||
isMultiEmptyElement,
|
||||
isMultiEqualKeyElement,
|
||||
isMultiEqualElementElement);
|
||||
|
||||
return hashIndex;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Adds (inserts) a data element into the associative array (hash index)
|
||||
// ...............................................................................
|
||||
|
||||
int MultiHashIndex_add(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
result = TRI_InsertElementMultiArray(hashIndex->assocArray.nonUniqueArray, element, false);
|
||||
if (result) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Locates an entry within the associative array
|
||||
// ...............................................................................
|
||||
|
||||
HashIndexElements* MultiHashIndex_find(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
TRI_vector_pointer_t result;
|
||||
HashIndexElements* results;
|
||||
size_t j;
|
||||
|
||||
results = TRI_Allocate(sizeof(HashIndexElements));
|
||||
|
||||
// .............................................................................
|
||||
// We can only use the LookupByKey method for non-unique hash indexes, since
|
||||
// we want more than one result returned!
|
||||
// .............................................................................
|
||||
result = TRI_LookupByKeyMultiArray (hashIndex->assocArray.nonUniqueArray, element);
|
||||
|
||||
|
||||
if (result._length == 0) {
|
||||
results->_elements = NULL;
|
||||
results->_numElements = 0;
|
||||
}
|
||||
else {
|
||||
results->_numElements = result._length;
|
||||
results->_elements = TRI_Allocate(sizeof(HashIndexElement) * result._length);
|
||||
for (j = 0; j < result._length; ++j) {
|
||||
results->_elements[j] = *((HashIndexElement*)(result._buffer[j]));
|
||||
}
|
||||
}
|
||||
TRI_DestroyVectorPointer(&result);
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// An alias for addIndex
|
||||
// ...............................................................................
|
||||
|
||||
int MultiHashIndex_insert(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
return MultiHashIndex_add(hashIndex,element);
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// Removes an entry from the associative array
|
||||
// ...............................................................................
|
||||
|
||||
bool MultiHashIndex_remove(HashIndex* hashIndex, HashIndexElement* element) {
|
||||
bool result;
|
||||
result = TRI_RemoveElementMultiArray(hashIndex->assocArray.nonUniqueArray, element, NULL);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ...............................................................................
|
||||
// updates and entry from the associative array, first removes beforeElement,
|
||||
// then adds the afterElement
|
||||
// ...............................................................................
|
||||
|
||||
bool MultiHashIndex_update(HashIndex* hashIndex, HashIndexElement* beforeElement,
|
||||
HashIndexElement* afterElement) {
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief unique hash index
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright by triAGENS GmbH - All rights reserved.
|
||||
///
|
||||
/// The Programs (which include both the software and documentation)
|
||||
/// contain proprietary information of triAGENS GmbH; they are
|
||||
/// provided under a license agreement containing restrictions on use and
|
||||
/// disclosure and are also protected by copyright, patent and other
|
||||
/// intellectual and industrial property laws. Reverse engineering,
|
||||
/// disassembly or decompilation of the Programs, except to the extent
|
||||
/// required to obtain interoperability with other independently created
|
||||
/// software or as specified by law, is prohibited.
|
||||
///
|
||||
/// The Programs are not intended for use in any nuclear, aviation, mass
|
||||
/// transit, medical, or other inherently dangerous applications. It shall
|
||||
/// be the licensee's responsibility to take all appropriate fail-safe,
|
||||
/// backup, redundancy, and other measures to ensure the safe use of such
|
||||
/// applications if the Programs are used for such purposes, and triAGENS
|
||||
/// GmbH disclaims liability for any damages caused by such use of
|
||||
/// the Programs.
|
||||
///
|
||||
/// This software is the confidential and proprietary information of
|
||||
/// triAGENS GmbH. You shall not disclose such confidential and
|
||||
/// proprietary information and shall use it only in accordance with the
|
||||
/// terms of the license agreement you entered into with triAGENS GmbH.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Dr. O
|
||||
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BasicsC/common.h>
|
||||
#include <BasicsC/associative.h>
|
||||
#include <BasicsC/associative-multi.h>
|
||||
#include <BasicsC/hashes.h>
|
||||
#include "ShapedJson/shaped-json.h"
|
||||
|
||||
// ...............................................................................
|
||||
// Define the structure of a unique or non-unique hashindex
|
||||
// ...............................................................................
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
TRI_associative_array_t* uniqueArray;
|
||||
TRI_multi_array_t* nonUniqueArray;
|
||||
} assocArray;
|
||||
bool unique;
|
||||
} HashIndex;
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t numFields; // the number of fields
|
||||
TRI_shaped_json_t* fields; // list of shaped json objects the blob of data within will be hashed
|
||||
void* data; // master document pointer
|
||||
} HashIndexElement;
|
||||
|
||||
typedef struct {
|
||||
size_t _numElements;
|
||||
HashIndexElement* _elements; // simple list of elements
|
||||
} HashIndexElements;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Unique hash indexes
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
HashIndex* HashIndex_new (void);
|
||||
|
||||
int HashIndex_add (HashIndex*, HashIndexElement*);
|
||||
|
||||
HashIndexElements* HashIndex_find (HashIndex*, HashIndexElement*);
|
||||
|
||||
int HashIndex_insert (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool HashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool HashIndex_update (HashIndex*, const HashIndexElement*, const HashIndexElement*);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
// Multi-hash non-unique hash indexes
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
HashIndex* MultiHashIndex_new (void);
|
||||
|
||||
int MultiHashIndex_add (HashIndex*, HashIndexElement*);
|
||||
|
||||
HashIndexElements* MultiHashIndex_find (HashIndex*, HashIndexElement*);
|
||||
|
||||
int MultiHashIndex_insert (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool MultiHashIndex_remove (HashIndex*, HashIndexElement*);
|
||||
|
||||
bool MultiHashIndex_update (HashIndex*, HashIndexElement*, HashIndexElement*);
|
|
@ -111,10 +111,11 @@ namespace triagens {
|
|||
switch (request->requestType()) {
|
||||
case HttpRequest::HTTP_REQUEST_GET:
|
||||
case HttpRequest::HTTP_REQUEST_DELETE:
|
||||
case HttpRequest::HTTP_REQUEST_HEAD:
|
||||
bodyLength = request->contentLength();
|
||||
|
||||
if (bodyLength > 0) {
|
||||
LOGGER_DEBUG << "received http GET/DELETE request with body length, this should not happen";
|
||||
LOGGER_DEBUG << "received http GET/DELETE/HEAD request with body length, this should not happen";
|
||||
readRequestBody = true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -144,7 +144,31 @@ namespace triagens {
|
|||
}
|
||||
}
|
||||
|
||||
if (! prefix.empty()) {
|
||||
if (prefix.empty()) {
|
||||
LOGGER_TRACE << "no prefix handler found, trying catch all";
|
||||
|
||||
i = ii.find("/");
|
||||
if (i != ii.end()) {
|
||||
LOGGER_TRACE << "found catch all handler '/'";
|
||||
|
||||
size_t l = 1;
|
||||
size_t n = path.find_first_of('/', l);
|
||||
|
||||
while (n != string::npos) {
|
||||
request->addSuffix(path.substr(l, n - l));
|
||||
l = n + 1;
|
||||
n = path.find_first_of('/', l);
|
||||
}
|
||||
|
||||
if (l < path.size()) {
|
||||
request->addSuffix(path.substr(l));
|
||||
}
|
||||
prefix = "/";
|
||||
request->setRequestPath(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
LOGGER_TRACE << "found prefix match '" << prefix << "'";
|
||||
|
||||
size_t l = prefix.size() + 1;
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
|
||||
# $Id$
|
||||
|
||||
PortSystem 1.0
|
||||
|
||||
name AvocadoDB
|
||||
version 0.1.2
|
||||
categories databases
|
||||
platforms darwin
|
||||
license Apache License, version 2.0
|
||||
maintainers triagens.de:f.celler
|
||||
|
||||
description a NoSQL document store that grows with your project
|
||||
|
||||
long_description Our mission: projects are different, project requirements \
|
||||
change. We want to offer with AvocadoDB a most universally \
|
||||
applicable nosql database which can be used in a maximum \
|
||||
number of different use cases. In buzzword bingo language: \
|
||||
we want to become the MySql in nosql – without MySql’s \
|
||||
annoyances of course. \
|
||||
(See the WWW page for details.)
|
||||
|
||||
supported_archs i386 x86_64
|
||||
|
||||
homepage http://www.avocadodb.org
|
||||
|
||||
fetch.type git
|
||||
git.url https://github.com/triAGENS/AvocadoDB
|
||||
git.branch v0.1.2
|
||||
|
||||
depends_build port:bison \
|
||||
port:flex
|
||||
|
||||
configure.args --enable-all-in-one \
|
||||
--enable-bison \
|
||||
--enable-flex \
|
||||
--disable-dbdir
|
||||
|
||||
build.target all
|
||||
|
||||
################################################################################
|
||||
|
||||
set dbgroup avocado
|
||||
set dbuser avocado
|
||||
|
||||
set dbdir ${prefix}/var/avocado
|
||||
|
||||
set sbindir ${prefix}/sbin
|
||||
|
||||
set etcbase ${prefix}/etc/voc
|
||||
set etcdir ${etcbase}/avocado
|
||||
|
||||
set logbase ${prefix}/var/log/voc
|
||||
set logdir ${logbase}/avocado
|
||||
|
||||
################################################################################
|
||||
|
||||
post-destroot {
|
||||
addgroup ${dbgroup}
|
||||
adduser ${dbuser} gid=[existsgroup ${dbgroup}]
|
||||
|
||||
xinstall -d -m 1777 \
|
||||
${destroot}${etcbase}
|
||||
|
||||
xinstall -d -m 755 -o ${dbuser} -g ${dbgroup} \
|
||||
${destroot}${etcdir}
|
||||
|
||||
xinstall -m 644 -o ${dbuser} -g ${dbgroup} \
|
||||
${worksrcpath}/Installation/MacOSX/MacPorts/avocado.conf \
|
||||
${destroot}${prefix}/etc/voc/avocado.conf.sample
|
||||
|
||||
xinstall -d -m 1777 \
|
||||
${destroot}${logbase}
|
||||
|
||||
xinstall -d -m 755 -o ${dbuser} -g ${dbgroup} \
|
||||
${destroot}${logdir}
|
||||
|
||||
xinstall -d -m 755 -o ${dbuser} -g ${dbgroup} \
|
||||
${destroot}${dbdir}
|
||||
|
||||
xinstall -d -m 755 \
|
||||
${destroot}${prefix}/Library/LaunchDaemons
|
||||
|
||||
xinstall -m 644 \
|
||||
${worksrcpath}/Installation/MacOSX/MacPorts/org.avocadodb.plist \
|
||||
${destroot}${prefix}/Library/LaunchDaemons/org.avocadodb.plist.sample
|
||||
|
||||
destroot.keepdirs-append \
|
||||
${destroot}${logdir} \
|
||||
${destroot}${dbdir}
|
||||
|
||||
reinplace "s|/usr/sbin|${sbindir}/|g" ${destroot}${prefix}/Library/LaunchDaemons/org.avocadodb.plist.sample
|
||||
reinplace "s|/etc|${etcdir}|g" ${destroot}${prefix}/Library/LaunchDaemons/org.avocadodb.plist.sample
|
||||
|
||||
reinplace "s|/var/log|${logdir}|g" ${destroot}${prefix}/etc/voc/avocado.conf.sample
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
post-activate {
|
||||
if {![file exists ${prefix}/Library/LaunchDaemons/org.avocadodb.plist]} {
|
||||
file copy ${prefix}/Library/LaunchDaemons/org.avocadodb.plist.sample \
|
||||
${prefix}/Library/LaunchDaemons/org.avocadodb.plist
|
||||
}
|
||||
|
||||
if {![file exists ${prefix}/etc/voc/avocado.conf]} {
|
||||
file copy ${prefix}/etc/voc/avocado.conf.sample \
|
||||
${prefix}/etc/voc/avocado.conf
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
notes "
|
||||
To start up the AvocadoDB server instance, use
|
||||
|
||||
sudo launchctl load ${prefix}/Library/LaunchDaemons/org.avocadodb.plist
|
||||
|
||||
The server will response on port 8529 to client request and you can use
|
||||
|
||||
http://localhost:8530/
|
||||
|
||||
to access the administration interface.
|
||||
|
||||
To stop up the AvocadoDB server instance, use
|
||||
|
||||
sudo launchctl unload ${prefix}/Library/LaunchDaemons/org.avocadodb.plist
|
||||
|
||||
Please note that this is a very early version if AvocadoDB. There will be
|
||||
bugs and we'd realy appreciate it if you report them:
|
||||
|
||||
https://github.com/triAGENS/AvocadoDB/issues
|
||||
|
||||
You find the configuration file at
|
||||
|
||||
${prefix}/etc/voc/avocado.conf
|
||||
"
|
|
@ -0,0 +1,11 @@
|
|||
[server]
|
||||
http-port = localhost:8529
|
||||
admin-port = localhost:8530
|
||||
|
||||
[action]
|
||||
threads = 4
|
||||
|
||||
[log]
|
||||
level = info
|
||||
severity = human
|
||||
file = /var/log/voc/avocado.log
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Disabled</key>
|
||||
<false/>
|
||||
|
||||
<key>Label</key>
|
||||
<string>org.avocadodb</string>
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/usr/sbin/avocado</string>
|
||||
<string>-c</string>
|
||||
<string>/etc/voc/avocado.conf</string>
|
||||
</array>
|
||||
|
||||
<key>UserName</key>
|
||||
<string>avocado</string>
|
||||
|
||||
<key>GroupName</key>
|
||||
<string>avocado</string>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
|
@ -46,7 +46,7 @@ namespace triagens {
|
|||
class HttpRequest;
|
||||
|
||||
namespace InputParser {
|
||||
class ObjectDescriptionImpl;
|
||||
struct ObjectDescriptionImpl;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @ingroup Utilities
|
||||
|
|
|
@ -838,6 +838,7 @@ static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
|
|||
static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
|
||||
#endif
|
||||
|
||||
#define YY_NO_INPUT
|
||||
#ifndef YY_NO_INPUT
|
||||
/* %if-c-only Standard (non-C++) definition */
|
||||
/* %not-for-header */
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace triagens { namespace json_parser {
|
|||
{
|
||||
return
|
||||
(pos1.filename == pos2.filename
|
||||
|| pos1.filename && pos2.filename && *pos1.filename == *pos2.filename)
|
||||
|| (pos1.filename && pos2.filename && *pos1.filename == *pos2.filename))
|
||||
&& pos1.line == pos2.line && pos1.column == pos2.column;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,17 +4,38 @@
|
|||
## LIBEV
|
||||
################################################################################
|
||||
|
||||
if ENABLE_64BIT
|
||||
LIBEV_BUILD_VERSION=ARCH.x64
|
||||
endif
|
||||
|
||||
if ENABLE_32BIT
|
||||
LIBEV_BUILD_VERSION=ARCH.ia32
|
||||
endif
|
||||
|
||||
if ENABLE_FORCE_32BIT
|
||||
LIBEV_CFLAGS_32=-m32 -O2 -g
|
||||
LIBEV_LDFLAGS_32=-m32
|
||||
else
|
||||
LIBEV_CFLAGS_32=-O2 -g
|
||||
LIBEV_LDFLAGS_32=
|
||||
endif
|
||||
|
||||
BUILT_SOURCES += @LIBEV_LIBS@
|
||||
|
||||
@LIBEV_LIBS@:
|
||||
@LIBEV_LIBS@: .libev-build
|
||||
|
||||
.libev-build:
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------------------------"
|
||||
@echo "BUILDING LIBEV"
|
||||
@echo "--------------------------------------------------------------------------------"
|
||||
@echo
|
||||
|
||||
cd @top_srcdir@/3rdParty/libev && ./configure --disable-shared
|
||||
cd @top_srcdir@/3rdParty/libev && make
|
||||
mkdir @top_srcdir@/3rdParty/libev/$(LIBEV_BUILD_VERSION) || true
|
||||
cd @top_srcdir@/3rdParty/libev/$(LIBEV_BUILD_VERSION) && CFLAGS="$(LIBEV_CFLAGS_32)" orig_CFLAGS="$(LIBEV_CFLAGS_32)" LDFLAGS="$(LIBEV_LDFLAGS_32)" ../configure --disable-shared
|
||||
cd @top_srcdir@/3rdParty/libev/$(LIBEV_BUILD_VERSION) && make
|
||||
|
||||
touch .libev-build
|
||||
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------------------------"
|
||||
|
@ -34,9 +55,11 @@ if ENABLE_32BIT
|
|||
V8_BUILD_VERSION=ia32
|
||||
endif
|
||||
|
||||
BUILT_SOURCES += $(V8_LIBS)
|
||||
BUILT_SOURCES += @V8_LIBS@
|
||||
|
||||
$(V8_LIBS):
|
||||
@V8_LIBS@: .v8-build
|
||||
|
||||
.v8-build:
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------------------------"
|
||||
@echo "BUILDING V8"
|
||||
|
@ -45,10 +68,13 @@ $(V8_LIBS):
|
|||
|
||||
if ENABLE_DARWIN
|
||||
cd @top_srcdir@/3rdParty/V8 && scons snapshot=off library=static mode=release arch=$(V8_BUILD_VERSION)
|
||||
cd @top_srcdir@/3rdParty/V8 && mv libv8.a libv8_$(V8_BUILD_VERSION).a
|
||||
else
|
||||
cd @top_srcdir@/3rdParty/V8 && make library=static snapshot=off $(V8_BUILD_VERSION).release
|
||||
endif
|
||||
|
||||
touch .v8-build
|
||||
|
||||
@echo
|
||||
@echo "--------------------------------------------------------------------------------"
|
||||
@echo "BUILD V8 FINISHED"
|
||||
|
|
44
Makefile.am
44
Makefile.am
|
@ -1,15 +1,39 @@
|
|||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
AM_CFLAGS =
|
||||
AM_CXXFLAGS =
|
||||
AM_CPPFLAGS = -D_SYSCONFDIR_='"${sysconfdir}"' -D_PKGDATADIR_='"${pkgdatadir}"' -D_DATABASEDIR_='"${localstatedir}/${PACKAGE_TARNAME}"'
|
||||
AM_LDFLAGS =
|
||||
AM_CPPFLAGS = \
|
||||
-D_SYSCONFDIR_='"${sysconfdir}"' \
|
||||
-D_PKGDATADIR_='"${pkgdatadir}"' \
|
||||
-D_DATABASEDIR_='"${localstatedir}/${PACKAGE_TARNAME}"' \
|
||||
@BOOST_CPPFLAGS@ \
|
||||
@LIBEV_CPPFLAGS@ \
|
||||
@MATH_CPPFLAGS@ \
|
||||
@NCURSES_CPPFLAGS@ \
|
||||
@OPENSSL_CPPFLAGS@ \
|
||||
@READLINE_CPPFLAGS@ \
|
||||
@V8_CPPFLAGS@
|
||||
|
||||
AM_LDFLAGS = \
|
||||
@BOOST_LDFLAGS@ \
|
||||
@LIBEV_LDFLAGS@ \
|
||||
@MATH_LDFLAGS@ \
|
||||
@NCURSES_LDFLAGS@ \
|
||||
@OPENSSL_LDFLAGS@ \
|
||||
@READLINE_LDFLAGS@ \
|
||||
@V8_LDFLAGS@
|
||||
|
||||
LIBS = \
|
||||
@BOOST_LIBS@ \
|
||||
@LIBEV_LIBS@ \
|
||||
@MATH_LIBS@ \
|
||||
@NCURSES_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@READLINE_LIBS@ \
|
||||
@V8_LIBS@
|
||||
|
||||
BUILT_SOURCES =
|
||||
CLEANUP =
|
||||
LIBS =
|
||||
|
||||
noinst_LIBRARIES = libavocadodb.a
|
||||
bin_PROGRAMS = avocado
|
||||
sbin_PROGRAMS = avocado
|
||||
|
||||
nobase_pkgdata_DATA = \
|
||||
$(shell find @srcdir@/js/system -name "*.js" -print) \
|
||||
|
@ -21,11 +45,13 @@ nobase_pkgdata_DATA = \
|
|||
$(shell find @srcdir@/html -name "*.js" -print) \
|
||||
$(shell find @srcdir@/html -name "*.png" -print)
|
||||
|
||||
if ENABLE_INSTALL_DBDIR
|
||||
install-data-local:
|
||||
test -d @localstatedir@//${PACKAGE_TARNAME} || mkdir -p @localstatedir@//${PACKAGE_TARNAME}
|
||||
test -d @localstatedir@/${PACKAGE_TARNAME} || mkdir -p @localstatedir@/${PACKAGE_TARNAME}
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
## avocado
|
||||
## avocadodb
|
||||
################################################################################
|
||||
|
||||
include Makefile.files
|
||||
|
|
|
@ -38,7 +38,7 @@ Doxygen/xml/%.md: Doxygen/xml/%.xml
|
|||
.PHONY: doxygen
|
||||
|
||||
doxygen: Doxygen/avocado.doxy $(DOXYGEN)
|
||||
doxygen Doxygen/avocado.doxy
|
||||
doxygen Doxygen/avocado.doxy > /dev/null
|
||||
|
||||
################################################################################
|
||||
## wiki
|
||||
|
@ -54,6 +54,6 @@ wiki: $(WIKI)
|
|||
## CLEANUP
|
||||
################################################################################
|
||||
|
||||
CLEANUP += $(DOXYGEN) $(WIKI)
|
||||
CLEANUP += $(DOXYGEN) $(WIKI) $(subst Doxygen/xml,Doxygen/wiki,$(WIKI))
|
||||
|
||||
|
||||
|
|
116
Makefile.files
116
Makefile.files
|
@ -4,17 +4,7 @@
|
|||
## avocadodb
|
||||
################################################################################
|
||||
|
||||
libavocadodb_a_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
@BOOST_CPPFLAGS@ \
|
||||
@LIBEV_CPPFLAGS@ \
|
||||
@MATH_CPPFLAGS@ \
|
||||
@NCURSES_CPPFLAGS@ \
|
||||
@OPENSSL_CPPFLAGS@ \
|
||||
@READLINE_CPPFLAGS@ \
|
||||
@V8_CPPFLAGS@
|
||||
|
||||
libavocadodb_a_SOURCES = \
|
||||
avocado_SOURCES = \
|
||||
Admin/ApplicationAdminServer.cpp \
|
||||
Admin/RestAdminBaseHandler.cpp \
|
||||
Admin/RestAdminFeConfigurationHandler.cpp \
|
||||
|
@ -74,6 +64,7 @@ libavocadodb_a_SOURCES = \
|
|||
Dispatcher/Job.cpp \
|
||||
GeneralServer/GeneralFigures.cpp \
|
||||
GeoIndex/GeoIndex.c \
|
||||
HashIndex/hashindex.c \
|
||||
HttpServer/ApplicationHttpServer.cpp \
|
||||
HttpServer/ApplicationHttpServerImpl.cpp \
|
||||
HttpServer/HttpCommTask.cpp \
|
||||
|
@ -98,6 +89,11 @@ libavocadodb_a_SOURCES = \
|
|||
Logger/LoggerStream.cpp \
|
||||
Logger/LoggerTiming.cpp \
|
||||
ProgramOptions/program-options.c \
|
||||
QL/ast-query.c \
|
||||
QL/formatter.c \
|
||||
QL/optimize.c \
|
||||
QL/parser.c \
|
||||
QL/tokens.c \
|
||||
Rest/AddressPort.cpp \
|
||||
Rest/AnyServer.cpp \
|
||||
Rest/HttpRequest.cpp \
|
||||
|
@ -105,6 +101,16 @@ libavocadodb_a_SOURCES = \
|
|||
Rest/Initialise.cpp \
|
||||
Rest/SslInterface.cpp \
|
||||
Rest/Url.cpp \
|
||||
RestHandler/RestActionHandler.cpp \
|
||||
RestHandler/RestCollectionHandler.cpp \
|
||||
RestHandler/RestSystemActionHandler.cpp \
|
||||
RestHandler/RestVocbaseBaseHandler.cpp \
|
||||
RestServer/ActionDispatcherThread.cpp \
|
||||
RestServer/AvocadoHttpServer.cpp \
|
||||
RestServer/AvocadoServer.cpp \
|
||||
RestServer/JSLoader.cpp \
|
||||
RestServer/SystemActionDispatcherThread.cpp \
|
||||
RestServer/avocado.cpp \
|
||||
ResultGenerator/HtmlResultGenerator.cpp \
|
||||
ResultGenerator/Initialise.cpp \
|
||||
ResultGenerator/JsonResultGenerator.cpp \
|
||||
|
@ -127,12 +133,14 @@ libavocadodb_a_SOURCES = \
|
|||
ShapedJson/json-shaper.c \
|
||||
ShapedJson/shape-accessor.c \
|
||||
ShapedJson/shaped-json.c \
|
||||
SkipLists/skiplist.c \
|
||||
SkipLists/skiplistIndex.c \
|
||||
V8/v8-actions.cpp \
|
||||
V8/v8-conv.cpp \
|
||||
V8/v8-json.cpp \
|
||||
V8/v8-line-editor.cpp \
|
||||
V8/v8-shell.cpp \
|
||||
V8/v8-utils.cpp \
|
||||
V8/v8-conv.cpp \
|
||||
V8/v8-line-editor.cpp \
|
||||
V8/v8-vocbase.cpp \
|
||||
Variant/VariantArray.cpp \
|
||||
Variant/VariantBlob.cpp \
|
||||
|
@ -154,79 +162,30 @@ libavocadodb_a_SOURCES = \
|
|||
Variant/VariantUInt64.cpp \
|
||||
Variant/VariantUInt8.cpp \
|
||||
Variant/VariantVector.cpp \
|
||||
VocBase/data-feeder.c \
|
||||
VocBase/join-execute.c \
|
||||
VocBase/order.c \
|
||||
VocBase/barrier.c \
|
||||
VocBase/blob-collection.c \
|
||||
VocBase/collection.c \
|
||||
VocBase/compactor.c \
|
||||
VocBase/data-feeder.c \
|
||||
VocBase/datafile.c \
|
||||
VocBase/document-collection.c \
|
||||
VocBase/fluent-query.c \
|
||||
VocBase/select-result.c \
|
||||
VocBase/join.c \
|
||||
VocBase/query.c \
|
||||
VocBase/headers.c \
|
||||
VocBase/index.c \
|
||||
VocBase/result-set.c \
|
||||
VocBase/join-execute.c \
|
||||
VocBase/join.c \
|
||||
VocBase/order.c \
|
||||
VocBase/query-base.c \
|
||||
VocBase/query-error.c \
|
||||
VocBase/query-javascript.c \
|
||||
VocBase/query-node.c \
|
||||
VocBase/query-parse.c \
|
||||
VocBase/query.c \
|
||||
VocBase/select-result.c \
|
||||
VocBase/shadow-data.c \
|
||||
VocBase/simple-collection.c \
|
||||
VocBase/synchroniser.c \
|
||||
VocBase/voc-shaper.c \
|
||||
VocBase/vocbase.c \
|
||||
QL/ParserWrapper.cpp \
|
||||
QL/ast-node.c \
|
||||
QL/ast-query.c \
|
||||
QL/error.c \
|
||||
QL/formatter.c \
|
||||
QL/javascripter.c \
|
||||
QL/optimize.c \
|
||||
QL/parser-context.c \
|
||||
QL/parser.c \
|
||||
QL/tokens.c
|
||||
|
||||
avocado_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
@BOOST_CPPFLAGS@ \
|
||||
@LIBEV_CPPFLAGS@ \
|
||||
@MATH_CPPFLAGS@ \
|
||||
@NCURSES_CPPFLAGS@ \
|
||||
@OPENSSL_CPPFLAGS@ \
|
||||
@READLINE_CPPFLAGS@ \
|
||||
@V8_CPPFLAGS@
|
||||
|
||||
avocado_LDFLAGS = \
|
||||
-L. \
|
||||
@BOOST_LDFLAGS@ \
|
||||
@LIBEV_LDFLAGS@ \
|
||||
@MATH_LDFLAGS@ \
|
||||
@NCURSES_LDFLAGS@ \
|
||||
@OPENSSL_LDFLAGS@ \
|
||||
@READLINE_LDFLAGS@ \
|
||||
@V8_LDFLAGS@
|
||||
|
||||
avocado_LDADD = \
|
||||
-lavocadodb \
|
||||
@BOOST_LIBS@ \
|
||||
@LIBEV_LIBS@ \
|
||||
@MATH_LIBS@ \
|
||||
@NCURSES_LIBS@ \
|
||||
@OPENSSL_LIBS@ \
|
||||
@READLINE_LIBS@ \
|
||||
@V8_LIBS@
|
||||
|
||||
avocado_DEPENDENCIES = @builddir@/libavocadodb.a
|
||||
|
||||
avocado_SOURCES = \
|
||||
RestHandler/RestActionHandler.cpp \
|
||||
RestHandler/RestDocumentHandler.cpp \
|
||||
RestHandler/RestSystemActionHandler.cpp \
|
||||
RestHandler/RestVocbaseBaseHandler.cpp \
|
||||
RestServer/ActionDispatcherThread.cpp \
|
||||
RestServer/AvocadoHttpServer.cpp \
|
||||
RestServer/AvocadoServer.cpp \
|
||||
RestServer/JSLoader.cpp \
|
||||
RestServer/SystemActionDispatcherThread.cpp \
|
||||
RestServer/avocado.cpp
|
||||
VocBase/vocbase.c
|
||||
|
||||
################################################################################
|
||||
## JavaScript source code as header
|
||||
|
@ -241,7 +200,6 @@ JAVASCRIPT_HEADER = \
|
|||
js/server/js-json.h \
|
||||
js/server/js-shell.h
|
||||
|
||||
|
||||
BUILT_SOURCES += $(JAVASCRIPT_HEADER)
|
||||
|
||||
################################################################################
|
||||
|
@ -291,6 +249,7 @@ DOXYGEN = \
|
|||
Doxygen/js/bootstrap/print.c \
|
||||
Doxygen/js/modules/graph.c \
|
||||
Doxygen/js/modules/jsunity.c \
|
||||
Doxygen/js/modules/simple-query.c \
|
||||
Doxygen/js/server/modules.c \
|
||||
Doxygen/js/server/actions.c \
|
||||
Doxygen/js/server/json.c \
|
||||
|
@ -324,11 +283,10 @@ WIKI = \
|
|||
Doxygen/xml/JSModules.md \
|
||||
Doxygen/xml/JavaScriptFunc.md \
|
||||
Doxygen/xml/JavaScriptFuncIndex.md \
|
||||
Doxygen/xml/Pagination.md \
|
||||
Doxygen/xml/RefManual.md \
|
||||
Doxygen/xml/RestDocument.md \
|
||||
Doxygen/xml/RestInterface.md \
|
||||
Doxygen/xml/RestSystem.md \
|
||||
Doxygen/xml/SimpleQueries.md \
|
||||
Doxygen/xml/StartStop.md \
|
||||
Doxygen/xml/UserManual.md \
|
||||
Doxygen/xml/jsUnity.md
|
||||
|
|
5189
Makefile.in
5189
Makefile.in
File diff suppressed because it is too large
Load Diff
|
@ -1348,9 +1348,7 @@ bool TRI_ParseArgumentsProgramOptions (TRI_program_options_t * options,
|
|||
int argc,
|
||||
char ** argv) {
|
||||
extern char *optarg;
|
||||
extern int opterr;
|
||||
extern int optind;
|
||||
extern int optopt;
|
||||
|
||||
TRI_string_buffer_t buffer;
|
||||
TRI_PO_item_t * item;
|
||||
|
|
|
@ -1,416 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief QL parser wrapper and utility classes
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ParserWrapper.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace triagens::avocado;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ParseError
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a new parse error instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError::ParseError (const string& message, const size_t line, const size_t column) :
|
||||
_message(message), _line(line), _column(column) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destroy the instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError::~ParseError () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the parse error as a formatted string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string ParseError::getDescription () const {
|
||||
ostringstream errorMessage;
|
||||
errorMessage << "Parse error at " << _line << "," << _column << ": " << _message;
|
||||
|
||||
return errorMessage.str();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ParserWrapper
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a new instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParserWrapper::ParserWrapper (const char *query) :
|
||||
_query(query), _parseError(0), _isParsed(false) {
|
||||
_context = (QL_parser_context_t*) TRI_Allocate(sizeof(QL_parser_context_t));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destroy the instance and free all associated memory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParserWrapper::~ParserWrapper () {
|
||||
if (_context != 0) {
|
||||
QLParseFree(_context);
|
||||
}
|
||||
if (_parseError) {
|
||||
delete _parseError;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parse the query passed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ParserWrapper::parse () {
|
||||
if (_context == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_query == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_isParsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_isParsed = true;
|
||||
|
||||
if (!QLParseInit(_context, _query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (QLparse(_context)) {
|
||||
// parse error
|
||||
QL_error_state_t *errorState = &_context->_lexState._errorState;
|
||||
_parseError= new ParseError(errorState->_message, errorState->_line, errorState->_column);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!QLParseValidate(_context, _context->_query->_select._base)) {
|
||||
QL_error_state_t *errorState = &_context->_lexState._errorState;
|
||||
_parseError= new ParseError(errorState->_message, errorState->_line, errorState->_column);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!QLParseValidate(_context, _context->_query->_where._base)) {
|
||||
QL_error_state_t *errorState = &_context->_lexState._errorState;
|
||||
_parseError= new ParseError(errorState->_message, errorState->_line, errorState->_column);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get a parse error that may have occurred
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError* ParserWrapper::getParseError () {
|
||||
return _parseError;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the type of the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_type_e ParserWrapper::getQueryType () {
|
||||
if (!_isParsed) {
|
||||
return QLQueryTypeUndefined;
|
||||
}
|
||||
|
||||
return _context->_query->_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a select clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_select_t* ParserWrapper::getSelect () {
|
||||
TRI_qry_select_t* select = 0;
|
||||
|
||||
if (!_isParsed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
QLOptimizeExpression(_context->_query->_select._base);
|
||||
QL_ast_query_select_type_e selectType = QLOptimizeGetSelectType(_context->_query);
|
||||
|
||||
if (selectType == QLQuerySelectTypeSimple) {
|
||||
select = TRI_CreateQuerySelectDocument();
|
||||
}
|
||||
else if (selectType == QLQuerySelectTypeEvaluated) {
|
||||
QL_javascript_conversion_t *selectJs = QLJavascripterInit();
|
||||
if (selectJs != 0) {
|
||||
TRI_AppendStringStringBuffer(selectJs->_buffer, "(function($) { return ");
|
||||
QLJavascripterConvert(selectJs, _context->_query->_select._base);
|
||||
TRI_AppendStringStringBuffer(selectJs->_buffer, " })");
|
||||
select = TRI_CreateQuerySelectGeneral(selectJs->_buffer->_buffer);
|
||||
// TODO: REMOVE ME
|
||||
// std::cout << "SELECT: " << selectJs->_buffer->_buffer << "\n";
|
||||
QLJavascripterFree(selectJs);
|
||||
}
|
||||
}
|
||||
|
||||
return select;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the alias of the primary collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* ParserWrapper::getPrimaryAlias () {
|
||||
if (_isParsed) {
|
||||
return QLAstQueryGetPrimaryAlias(_context->_query);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the name of the primary collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* ParserWrapper::getPrimaryName () {
|
||||
if (_isParsed) {
|
||||
return QLAstQueryGetPrimaryName(_context->_query);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create joins
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_select_join_t* ParserWrapper::getJoins () {
|
||||
TRI_select_join_t* join = 0;
|
||||
char *collectionName;
|
||||
char *collectionAlias;
|
||||
|
||||
if (!_isParsed ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
join = TRI_CreateSelectJoin();
|
||||
if (!join) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QL_ast_node_t *node = (QL_ast_node_t *) _context->_query->_from._base;
|
||||
node = (QL_ast_node_t *) node->_next;
|
||||
//QL_formatter_t f;
|
||||
//f.indentLevel = 0;
|
||||
//QLFormatterDump(_context->_query->_from._base, &f, 0);
|
||||
|
||||
assert(node != 0);
|
||||
|
||||
// primary table
|
||||
QL_ast_node_t *lhs = (QL_ast_node_t *) node->_lhs;
|
||||
QL_ast_node_t *rhs = (QL_ast_node_t *) node->_rhs;
|
||||
collectionName = lhs->_value._stringValue;
|
||||
collectionAlias = rhs->_value._stringValue;
|
||||
|
||||
TRI_AddPartSelectJoin(join, JOIN_TYPE_PRIMARY, NULL, collectionName, collectionAlias);
|
||||
|
||||
while (node->_next) {
|
||||
node = (QL_ast_node_t *) node->_next;
|
||||
QL_ast_node_t *ref = (QL_ast_node_t *) node->_lhs;
|
||||
QL_ast_node_t *condition = (QL_ast_node_t *) node->_rhs;
|
||||
|
||||
QLOptimizeExpression(condition);
|
||||
QL_ast_query_where_type_e conditionType = QLOptimizeGetWhereType(condition);
|
||||
|
||||
TRI_qry_where_t* joinWhere = 0;
|
||||
|
||||
if (conditionType == QLQueryWhereTypeAlwaysTrue) {
|
||||
// join condition is always true
|
||||
joinWhere = TRI_CreateQueryWhereBoolean(true);
|
||||
}
|
||||
else if (conditionType == QLQueryWhereTypeAlwaysFalse) {
|
||||
// join condition is always false
|
||||
joinWhere = TRI_CreateQueryWhereBoolean(false);
|
||||
}
|
||||
else {
|
||||
// where condition must be evaluated for each result
|
||||
QL_javascript_conversion_t *conditionJs = QLJavascripterInit();
|
||||
if (conditionJs != 0) {
|
||||
TRI_AppendStringStringBuffer(conditionJs->_buffer, "(function($) { return (");
|
||||
QLJavascripterConvert(conditionJs, condition);
|
||||
TRI_AppendStringStringBuffer(conditionJs->_buffer, "); })");
|
||||
joinWhere = TRI_CreateQueryWhereGeneral(conditionJs->_buffer->_buffer);
|
||||
QLJavascripterFree(conditionJs);
|
||||
}
|
||||
}
|
||||
|
||||
collectionName = ((QL_ast_node_t *) (ref->_lhs))->_value._stringValue;
|
||||
collectionAlias = ((QL_ast_node_t *) (ref->_rhs))->_value._stringValue;
|
||||
|
||||
if (node->_type == QLNodeJoinList) {
|
||||
TRI_AddPartSelectJoin(join, JOIN_TYPE_LIST, joinWhere, collectionName, collectionAlias);
|
||||
}
|
||||
else if (node->_type == QLNodeJoinInner) {
|
||||
TRI_AddPartSelectJoin(join, JOIN_TYPE_INNER, joinWhere, collectionName, collectionAlias);
|
||||
}
|
||||
else if (node->_type == QLNodeJoinLeft || node->_type == QLNodeJoinRight) {
|
||||
TRI_AddPartSelectJoin(join, JOIN_TYPE_OUTER, joinWhere, collectionName, collectionAlias);
|
||||
}
|
||||
}
|
||||
|
||||
return join;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a where clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_where_t* ParserWrapper::getWhere () {
|
||||
TRI_qry_where_t* where = 0;
|
||||
|
||||
if (!_isParsed) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QLOptimizeExpression(_context->_query->_where._base);
|
||||
// TODO: REMOVE ME
|
||||
// QL_formatter_t f;
|
||||
// f.indentLevel = 0;
|
||||
// QLFormatterDump(_context->_query->_where._base, &f, 0);
|
||||
|
||||
_context->_query->_where._type = QLOptimizeGetWhereType(_context->_query->_where._base);
|
||||
|
||||
if (_context->_query->_where._type == QLQueryWhereTypeAlwaysTrue) {
|
||||
// where condition is always true
|
||||
where = TRI_CreateQueryWhereBoolean(true);
|
||||
}
|
||||
else if (_context->_query->_where._type == QLQueryWhereTypeAlwaysFalse) {
|
||||
// where condition is always false
|
||||
where = TRI_CreateQueryWhereBoolean(false);
|
||||
}
|
||||
else {
|
||||
// where condition must be evaluated for each result
|
||||
QL_javascript_conversion_t *whereJs = QLJavascripterInit();
|
||||
if (whereJs != 0) {
|
||||
TRI_AppendStringStringBuffer(whereJs->_buffer, "(function($) { return (");
|
||||
QLJavascripterConvert(whereJs, _context->_query->_where._base);
|
||||
TRI_AppendStringStringBuffer(whereJs->_buffer, "); })");
|
||||
where = TRI_CreateQueryWhereGeneral(whereJs->_buffer->_buffer);
|
||||
// TODO: REMOVE ME
|
||||
// std::cout << "WHERE: " << whereJs->_buffer->_buffer << "\n";
|
||||
QLJavascripterFree(whereJs);
|
||||
}
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create an order clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_order_t* ParserWrapper::getOrder () {
|
||||
TRI_qry_order_t* order = 0;
|
||||
|
||||
if (!_isParsed ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_context->_query->_order._base) {
|
||||
QLOptimizeOrder(_context->_query->_order._base);
|
||||
QL_javascript_conversion_t *orderJs = QLJavascripterInit();
|
||||
if (orderJs != 0) {
|
||||
TRI_AppendStringStringBuffer(orderJs->_buffer, "(function($){var lhs,rhs;");
|
||||
QLJavascripterConvertOrder(orderJs, (QL_ast_node_t *) _context->_query->_order._base->_next);
|
||||
TRI_AppendStringStringBuffer(orderJs->_buffer, "})");
|
||||
order = TRI_CreateQueryOrderGeneral(orderJs->_buffer->_buffer);
|
||||
// TODO: REMOVE ME
|
||||
// std::cout << "ORDER: " << orderJs->_buffer->_buffer << "\n";
|
||||
QLJavascripterFree(orderJs);
|
||||
}
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the skip value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_size_t ParserWrapper::getSkip () {
|
||||
TRI_voc_size_t skip = 0;
|
||||
|
||||
if (_isParsed) {
|
||||
if (_context->_query->_limit._isUsed) {
|
||||
skip = (TRI_voc_size_t) _context->_query->_limit._offset;
|
||||
}
|
||||
else {
|
||||
skip = TRI_QRY_NO_SKIP;
|
||||
}
|
||||
}
|
||||
|
||||
return skip;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the limit value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_ssize_t ParserWrapper::getLimit () {
|
||||
TRI_voc_ssize_t limit = 0;
|
||||
|
||||
if (_isParsed) {
|
||||
if (_context->_query->_limit._isUsed) {
|
||||
limit = (TRI_voc_ssize_t) _context->_query->_limit._count;
|
||||
}
|
||||
else {
|
||||
limit = TRI_QRY_NO_LIMIT;
|
||||
}
|
||||
}
|
||||
|
||||
return limit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
|
@ -1,247 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief QL parser wrapper and utility classes
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2004-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2011-2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_QL_PARSERWRAPPER_H
|
||||
#define TRIAGENS_QL_PARSERWRAPPER 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "QL/ast-node.h"
|
||||
#include "QL/ast-query.h"
|
||||
#include "QL/parser-context.h"
|
||||
#include "QL/optimize.h"
|
||||
#include "QL/formatter.h"
|
||||
#include "QL/javascripter.h"
|
||||
|
||||
#include "VocBase/query.h"
|
||||
#include "VocBase/join.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace triagens {
|
||||
namespace avocado {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ParseError
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parse error container
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ParseError {
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destroy the instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError(const string&, const size_t, const size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destroy the instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~ParseError();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the parse error as a formatted string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string getDescription() const;
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parse error as created by Bison
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string _message;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Line in which the error occurred
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t _line;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Column in which the error occurred
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t _column;
|
||||
};
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ParserWrapper
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parser wrapper
|
||||
///
|
||||
/// This is a simple wrapper around the C level parser functions. The wrapper
|
||||
/// cares about memory allocation and deallocation and provides access to the
|
||||
/// parse results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ParserWrapper {
|
||||
public:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a new instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParserWrapper (const char*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Destroy the instance and free all associated memory
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
~ParserWrapper ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parse the query passed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool parse ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get a parse error that may have occurred
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError* getParseError ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the type of the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_type_e getQueryType ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a select clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_select_t* getSelect ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the alias of the primary collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* getPrimaryAlias ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the name of the primary collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* getPrimaryName ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create joins
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_select_join_t* getJoins ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a where clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_where_t* getWhere ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create an order clause
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_qry_order_t* getOrder ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the skip value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_size_t getSkip ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Get the limit value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_ssize_t getLimit ();
|
||||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Query string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char* _query;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Parser context. This is a struct that is used extensively by the
|
||||
/// parser. It contains a pointer to the flex lexer, a pointer to the query's
|
||||
/// AST root nodes and state information for memory management (GC)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_parser_context_t* _context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Pointer to a parse error
|
||||
///
|
||||
/// The parse error object is automatically created during parsing if a parse
|
||||
/// error occurs. It will be freed automatically when the parser is destroyed.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ParseError* _parseError;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Flag if parsing has already taken place
|
||||
///
|
||||
/// Using this flag duplicate parsing and all of its issues can be avoided
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool _isParsed;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
427
QL/ast-node.c
427
QL/ast-node.c
|
@ -1,427 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief AST node declarations
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "QL/ast-node.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get text/label for a node based on its type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const char* QLAstNodeGetName (const QL_ast_node_type_e type) {
|
||||
switch (type) {
|
||||
case QLNodeContainerList:
|
||||
return "list container";
|
||||
case QLNodeContainerOrderElement:
|
||||
return "order element container";
|
||||
case QLNodeContainerMemberAccess:
|
||||
return "member access";
|
||||
case QLNodeContainerTernarySwitch:
|
||||
return "ternary operator switch";
|
||||
|
||||
case QLNodeJoinList:
|
||||
return "join: list";
|
||||
case QLNodeJoinInner:
|
||||
return "join: inner";
|
||||
case QLNodeJoinLeft:
|
||||
return "join: left";
|
||||
case QLNodeJoinRight:
|
||||
return "join: right";
|
||||
|
||||
case QLNodeValueUndefined:
|
||||
return "value: undefined";
|
||||
case QLNodeValueNull:
|
||||
return "value: null";
|
||||
case QLNodeValueBool:
|
||||
return "value: bool";
|
||||
case QLNodeValueString:
|
||||
return "value: string";
|
||||
case QLNodeValueNumberInt:
|
||||
return "value: number (int)";
|
||||
case QLNodeValueNumberDouble:
|
||||
case QLNodeValueNumberDoubleString:
|
||||
return "value: number (double)";
|
||||
case QLNodeValueArray:
|
||||
return "value: array";
|
||||
case QLNodeValueDocument:
|
||||
return "value: document";
|
||||
case QLNodeValueParameterNumeric:
|
||||
return "value: numeric parameter";
|
||||
case QLNodeValueParameterNamed:
|
||||
return "value: named parameter";
|
||||
case QLNodeValueIdentifier:
|
||||
return "value: identifier";
|
||||
case QLNodeValueNamedValue:
|
||||
return "value: named value";
|
||||
case QLNodeValueOrderDirection:
|
||||
return "value: orderdirection";
|
||||
|
||||
case QLNodeReferenceCollection:
|
||||
return "reference: collection";
|
||||
case QLNodeReferenceCollectionAlias:
|
||||
return "reference: collection alias";
|
||||
|
||||
case QLNodeUnaryOperatorPlus:
|
||||
return "unary: plus";
|
||||
case QLNodeUnaryOperatorMinus:
|
||||
return "unary: minus";
|
||||
case QLNodeUnaryOperatorNot:
|
||||
return "unary: not";
|
||||
|
||||
case QLNodeBinaryOperatorIn:
|
||||
return "binary: in";
|
||||
case QLNodeBinaryOperatorAnd:
|
||||
return "binary: and";
|
||||
case QLNodeBinaryOperatorOr:
|
||||
return "binary: or";
|
||||
case QLNodeBinaryOperatorIdentical:
|
||||
return "binary: identical";
|
||||
case QLNodeBinaryOperatorUnidentical:
|
||||
return "binary: unidentical";
|
||||
case QLNodeBinaryOperatorEqual:
|
||||
return "binary: equal";
|
||||
case QLNodeBinaryOperatorUnequal:
|
||||
return "binary: unequal";
|
||||
case QLNodeBinaryOperatorLess:
|
||||
return "binary: less";
|
||||
case QLNodeBinaryOperatorGreater:
|
||||
return "binary: greater";
|
||||
case QLNodeBinaryOperatorLessEqual:
|
||||
return "binary: lessequal";
|
||||
case QLNodeBinaryOperatorGreaterEqual:
|
||||
return "binary: greaterequal";
|
||||
case QLNodeBinaryOperatorAdd:
|
||||
return "binary: add";
|
||||
case QLNodeBinaryOperatorSubtract:
|
||||
return "binary: subtract";
|
||||
case QLNodeBinaryOperatorMultiply:
|
||||
return "binary: multiply";
|
||||
case QLNodeBinaryOperatorDivide:
|
||||
return "binary: divide";
|
||||
case QLNodeBinaryOperatorModulus:
|
||||
return "binary: modulus";
|
||||
|
||||
case QLNodeControlFunctionCall:
|
||||
return "function call";
|
||||
case QLNodeControlTernary:
|
||||
return "ternary operator";
|
||||
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the type group of a node based on its type
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_node_type_group_e QLAstNodeGetTypeGroup (const QL_ast_node_type_e type) {
|
||||
switch (type) {
|
||||
case QLNodeContainerList:
|
||||
case QLNodeContainerOrderElement:
|
||||
case QLNodeContainerMemberAccess:
|
||||
case QLNodeContainerTernarySwitch:
|
||||
return QLNodeGroupContainer;
|
||||
|
||||
case QLNodeJoinList:
|
||||
case QLNodeJoinInner:
|
||||
case QLNodeJoinLeft:
|
||||
case QLNodeJoinRight:
|
||||
return QLNodeGroupJoin;
|
||||
|
||||
case QLNodeValueUndefined:
|
||||
case QLNodeValueNull:
|
||||
case QLNodeValueBool:
|
||||
case QLNodeValueString:
|
||||
case QLNodeValueNumberInt:
|
||||
case QLNodeValueNumberDouble:
|
||||
case QLNodeValueNumberDoubleString:
|
||||
case QLNodeValueArray:
|
||||
case QLNodeValueDocument:
|
||||
case QLNodeValueParameterNumeric:
|
||||
case QLNodeValueParameterNamed:
|
||||
case QLNodeValueIdentifier:
|
||||
case QLNodeValueOrderDirection:
|
||||
return QLNodeGroupValue;
|
||||
|
||||
case QLNodeReferenceCollection:
|
||||
case QLNodeReferenceCollectionAlias:
|
||||
return QLNodeGroupReference;
|
||||
|
||||
case QLNodeUnaryOperatorPlus:
|
||||
case QLNodeUnaryOperatorMinus:
|
||||
case QLNodeUnaryOperatorNot:
|
||||
return QLNodeGroupUnaryOperator;
|
||||
|
||||
case QLNodeBinaryOperatorIn:
|
||||
case QLNodeBinaryOperatorAnd:
|
||||
case QLNodeBinaryOperatorOr:
|
||||
case QLNodeBinaryOperatorIdentical:
|
||||
case QLNodeBinaryOperatorUnidentical:
|
||||
case QLNodeBinaryOperatorEqual:
|
||||
case QLNodeBinaryOperatorUnequal:
|
||||
case QLNodeBinaryOperatorLess:
|
||||
case QLNodeBinaryOperatorGreater:
|
||||
case QLNodeBinaryOperatorLessEqual:
|
||||
case QLNodeBinaryOperatorGreaterEqual:
|
||||
case QLNodeBinaryOperatorAdd:
|
||||
case QLNodeBinaryOperatorSubtract:
|
||||
case QLNodeBinaryOperatorMultiply:
|
||||
case QLNodeBinaryOperatorDivide:
|
||||
case QLNodeBinaryOperatorModulus:
|
||||
return QLNodeGroupBinaryOperator;
|
||||
|
||||
case QLNodeControlFunctionCall:
|
||||
case QLNodeControlTernary:
|
||||
return QLNodeGroupControl;
|
||||
|
||||
default:
|
||||
return QLNodeGroupUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the label string for a unary operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstNodeGetUnaryOperatorString (const QL_ast_node_type_e type) {
|
||||
switch (type) {
|
||||
case QLNodeUnaryOperatorPlus:
|
||||
return "+";
|
||||
case QLNodeUnaryOperatorMinus:
|
||||
return "-";
|
||||
case QLNodeUnaryOperatorNot:
|
||||
return "!";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the label string for a binary operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstNodeGetBinaryOperatorString (const QL_ast_node_type_e type) {
|
||||
switch (type) {
|
||||
case QLNodeBinaryOperatorAnd:
|
||||
return "&&";
|
||||
case QLNodeBinaryOperatorOr:
|
||||
return "||";
|
||||
case QLNodeBinaryOperatorIdentical:
|
||||
return "===";
|
||||
case QLNodeBinaryOperatorUnidentical:
|
||||
return "!==";
|
||||
case QLNodeBinaryOperatorEqual:
|
||||
return "==";
|
||||
case QLNodeBinaryOperatorUnequal:
|
||||
return "!=";
|
||||
case QLNodeBinaryOperatorLess:
|
||||
return "<";
|
||||
case QLNodeBinaryOperatorGreater:
|
||||
return ">";
|
||||
case QLNodeBinaryOperatorLessEqual:
|
||||
return "<=";
|
||||
case QLNodeBinaryOperatorGreaterEqual:
|
||||
return ">=";
|
||||
case QLNodeBinaryOperatorAdd:
|
||||
return "+";
|
||||
case QLNodeBinaryOperatorSubtract:
|
||||
return "-";
|
||||
case QLNodeBinaryOperatorMultiply:
|
||||
return "*";
|
||||
case QLNodeBinaryOperatorDivide:
|
||||
return "/";
|
||||
case QLNodeBinaryOperatorModulus:
|
||||
return "%";
|
||||
case QLNodeBinaryOperatorIn:
|
||||
return " in ";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a value node
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsValueNode (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeValueUndefined:
|
||||
case QLNodeValueNull:
|
||||
case QLNodeValueBool:
|
||||
case QLNodeValueString:
|
||||
case QLNodeValueNumberInt:
|
||||
case QLNodeValueNumberDouble:
|
||||
case QLNodeValueNumberDoubleString:
|
||||
case QLNodeValueArray:
|
||||
case QLNodeValueDocument:
|
||||
case QLNodeValueParameterNumeric:
|
||||
case QLNodeValueParameterNamed:
|
||||
case QLNodeValueIdentifier:
|
||||
case QLNodeValueNamedValue:
|
||||
case QLNodeValueOrderDirection:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a logical operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsArithmeticOperator (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeBinaryOperatorAdd:
|
||||
case QLNodeBinaryOperatorSubtract:
|
||||
case QLNodeBinaryOperatorMultiply:
|
||||
case QLNodeBinaryOperatorDivide:
|
||||
case QLNodeBinaryOperatorModulus:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a unary operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsUnaryOperator (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeUnaryOperatorPlus:
|
||||
case QLNodeUnaryOperatorMinus:
|
||||
case QLNodeUnaryOperatorNot:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a binary operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsBinaryOperator (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeBinaryOperatorIn:
|
||||
case QLNodeBinaryOperatorAnd:
|
||||
case QLNodeBinaryOperatorOr:
|
||||
case QLNodeBinaryOperatorIdentical:
|
||||
case QLNodeBinaryOperatorUnidentical:
|
||||
case QLNodeBinaryOperatorEqual:
|
||||
case QLNodeBinaryOperatorUnequal:
|
||||
case QLNodeBinaryOperatorLess:
|
||||
case QLNodeBinaryOperatorGreater:
|
||||
case QLNodeBinaryOperatorLessEqual:
|
||||
case QLNodeBinaryOperatorGreaterEqual:
|
||||
case QLNodeBinaryOperatorAdd:
|
||||
case QLNodeBinaryOperatorSubtract:
|
||||
case QLNodeBinaryOperatorMultiply:
|
||||
case QLNodeBinaryOperatorDivide:
|
||||
case QLNodeBinaryOperatorModulus:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is the ternary operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsTernaryOperator (const QL_ast_node_t* node) {
|
||||
return (node->_type == QLNodeControlTernary);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a logical operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsLogicalOperator (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeBinaryOperatorAnd:
|
||||
case QLNodeBinaryOperatorOr:
|
||||
case QLNodeUnaryOperatorNot:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a relational operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsRelationalOperator (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeBinaryOperatorIdentical:
|
||||
case QLNodeBinaryOperatorUnidentical:
|
||||
case QLNodeBinaryOperatorEqual:
|
||||
case QLNodeBinaryOperatorUnequal:
|
||||
case QLNodeBinaryOperatorLess:
|
||||
case QLNodeBinaryOperatorGreater:
|
||||
case QLNodeBinaryOperatorLessEqual:
|
||||
case QLNodeBinaryOperatorGreaterEqual:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return whether a node is a constant
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstNodeIsBooleanizable (const QL_ast_node_t* node) {
|
||||
switch (node->_type) {
|
||||
case QLNodeValueBool:
|
||||
// case QLNodeValueString: // TODO
|
||||
case QLNodeValueNumberInt:
|
||||
case QLNodeValueNumberDouble:
|
||||
case QLNodeValueNumberDoubleString:
|
||||
case QLNodeValueNull:
|
||||
// case QLNodeValueArray: // TODO
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
482
QL/ast-query.c
482
QL/ast-query.c
|
@ -27,7 +27,6 @@
|
|||
|
||||
#include "QL/ast-query.h"
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -51,8 +50,9 @@ static uint64_t HashKey (TRI_associative_pointer_t* array, void const* key) {
|
|||
/// @brief Hash function used to hash elements in the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashElement (TRI_associative_pointer_t* array, void const* element) {
|
||||
QL_ast_query_collection_t *collection = (QL_ast_query_collection_t*) element;
|
||||
static uint64_t HashCollectionElement (TRI_associative_pointer_t* array,
|
||||
void const* element) {
|
||||
QL_ast_query_collection_t* collection = (QL_ast_query_collection_t*) element;
|
||||
|
||||
return TRI_FnvHashString(collection->_alias);
|
||||
}
|
||||
|
@ -61,13 +61,41 @@ static uint64_t HashElement (TRI_associative_pointer_t* array, void const* eleme
|
|||
/// @brief Comparison function used to determine hash key equality
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualKeyElement (TRI_associative_pointer_t* array, void const* key, void const* element) {
|
||||
static bool EqualCollectionKeyElement (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
char const* k = (char const*) key;
|
||||
QL_ast_query_collection_t *collection = (QL_ast_query_collection_t*) element;
|
||||
QL_ast_query_collection_t* collection = (QL_ast_query_collection_t*) element;
|
||||
|
||||
return TRI_EqualString(k, collection->_alias);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hash function used to hash geo restrictions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint64_t HashRestrictionElement (TRI_associative_pointer_t* array,
|
||||
void const* element) {
|
||||
QL_ast_query_geo_restriction_t* restriction =
|
||||
(QL_ast_query_geo_restriction_t*) element;
|
||||
|
||||
return TRI_FnvHashString(restriction->_alias);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Comparison function used to determine hash key equality
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EqualRestrictionKeyElement (TRI_associative_pointer_t* array,
|
||||
void const* key,
|
||||
void const* element) {
|
||||
char const* k = (char const*) key;
|
||||
QL_ast_query_geo_restriction_t* restriction =
|
||||
(QL_ast_query_geo_restriction_t*) element;
|
||||
|
||||
return TRI_EqualString(k, restriction->_alias);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -86,16 +114,22 @@ static bool EqualKeyElement (TRI_associative_pointer_t* array, void const* key,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryInit (QL_ast_query_t* query) {
|
||||
query->_type = QLQueryTypeUndefined;
|
||||
query->_from._base = 0;
|
||||
query->_where._base = 0;
|
||||
query->_order._base = 0;
|
||||
query->_type = QLQueryTypeUndefined;
|
||||
query->_from._base = NULL;
|
||||
query->_where._base = NULL;
|
||||
query->_order._base = NULL;
|
||||
query->_limit._isUsed = false;
|
||||
|
||||
TRI_InitAssociativePointer(&query->_from._collections,
|
||||
HashKey,
|
||||
HashElement,
|
||||
EqualKeyElement,
|
||||
HashCollectionElement,
|
||||
EqualCollectionKeyElement,
|
||||
0);
|
||||
|
||||
TRI_InitAssociativePointer(&query->_geo._restrictions,
|
||||
HashKey,
|
||||
HashRestrictionElement,
|
||||
EqualRestrictionKeyElement,
|
||||
0);
|
||||
}
|
||||
|
||||
|
@ -104,28 +138,109 @@ void QLAstQueryInit (QL_ast_query_t* query) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryFree (QL_ast_query_t* query) {
|
||||
QL_ast_query_collection_t* collection;
|
||||
QL_ast_query_geo_restriction_t* restriction;
|
||||
size_t i;
|
||||
void* ptr;
|
||||
|
||||
// destroy all elements in collection array
|
||||
for (i = 0; i < query->_from._collections._nrAlloc; i++) {
|
||||
ptr = query->_from._collections._table[i];
|
||||
|
||||
if (ptr != 0) {
|
||||
TRI_Free(ptr);
|
||||
collection = (QL_ast_query_collection_t*) query->_from._collections._table[i];
|
||||
if (collection) {
|
||||
TRI_Free(collection);
|
||||
}
|
||||
}
|
||||
|
||||
// destroy array itself
|
||||
// destroy collection array itself
|
||||
TRI_DestroyAssociativePointer(&query->_from._collections);
|
||||
|
||||
|
||||
// destroy all elements in restrictions array
|
||||
for (i = 0; i < query->_geo._restrictions._nrAlloc; i++) {
|
||||
restriction = (QL_ast_query_geo_restriction_t*) query->_geo._restrictions._table[i];
|
||||
if (restriction) {
|
||||
QLAstQueryFreeRestriction(restriction);
|
||||
}
|
||||
}
|
||||
// destroy restrictions array
|
||||
TRI_DestroyAssociativePointer(&query->_geo._restrictions);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the ref count for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t QLAstQueryGetRefCount (QL_ast_query_t* query, const char* alias) {
|
||||
QL_ast_query_collection_t* collection = (QL_ast_query_collection_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias);
|
||||
|
||||
if (collection != 0) {
|
||||
return collection->_refCount;
|
||||
}
|
||||
|
||||
// return a number > 0 if collection not found so nothing happens with it
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Increment ref count for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryAddRefCount (QL_ast_query_t* query, const char* alias) {
|
||||
QL_ast_query_collection_t* collection = (QL_ast_query_collection_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias);
|
||||
|
||||
if (collection != 0) {
|
||||
++collection->_refCount;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Check if a collection was defined in a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryIsValidAlias (QL_ast_query_t* query, const char* alias) {
|
||||
return (0 != TRI_LookupByKeyAssociativePointer (&query->_from._collections, alias));
|
||||
bool QLAstQueryIsValidAlias (QL_ast_query_t* query,
|
||||
const char* alias,
|
||||
const size_t order) {
|
||||
if (0 != TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (0 != TRI_LookupByKeyAssociativePointer(&query->_geo._restrictions, alias));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Check if a collection was defined in a query, taking order of
|
||||
/// declaration into account
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryIsValidAliasOrdered (QL_ast_query_t* query,
|
||||
const char* alias,
|
||||
const size_t order) {
|
||||
QL_ast_query_collection_t* collection;
|
||||
|
||||
collection = (QL_ast_query_collection_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias);
|
||||
|
||||
if (!collection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (collection->_declarationOrder <= order);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the collection name for its alias
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstQueryGetCollectionNameForAlias (QL_ast_query_t* query,
|
||||
const char* alias) {
|
||||
QL_ast_query_collection_t* collection;
|
||||
|
||||
collection = (QL_ast_query_collection_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&query->_from._collections, alias);
|
||||
if (!collection) {
|
||||
return NULL;
|
||||
}
|
||||
return collection->_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -134,50 +249,50 @@ bool QLAstQueryIsValidAlias (QL_ast_query_t* query, const char* alias) {
|
|||
|
||||
bool QLAstQueryAddCollection (QL_ast_query_t* query,
|
||||
const char* name,
|
||||
const char* alias,
|
||||
const bool isPrimary) {
|
||||
QL_ast_query_collection_t *collection;
|
||||
QL_ast_query_collection_t *previous;
|
||||
const char* alias) {
|
||||
QL_ast_query_collection_t* collection;
|
||||
void* previous;
|
||||
size_t num;
|
||||
|
||||
previous = (QL_ast_query_collection_t *) TRI_LookupByKeyAssociativePointer (&query->_from._collections, alias);
|
||||
|
||||
if (previous != 0) {
|
||||
// element is already present - return an error
|
||||
previous = (void*) TRI_LookupByKeyAssociativePointer(&query->_from._collections,
|
||||
alias);
|
||||
if (previous) {
|
||||
// alias has already been declared for another collection - return an error
|
||||
return false;
|
||||
}
|
||||
|
||||
collection = (QL_ast_query_collection_t *) TRI_Allocate(sizeof(QL_ast_query_collection_t));
|
||||
if (collection == 0) {
|
||||
previous = (void*) TRI_LookupByKeyAssociativePointer(&query->_geo._restrictions,
|
||||
alias);
|
||||
if (previous) {
|
||||
// alias has already been declared for a geo restriction - return an error
|
||||
return false;
|
||||
}
|
||||
|
||||
collection->_name = (char *) name;
|
||||
collection->_alias = (char *) alias;
|
||||
collection->_isPrimary = isPrimary;
|
||||
|
||||
TRI_InsertKeyAssociativePointer(&query->_from._collections, collection->_alias, collection, true);
|
||||
collection = (QL_ast_query_collection_t *)
|
||||
TRI_Allocate(sizeof(QL_ast_query_collection_t));
|
||||
if (!collection) {
|
||||
return false;
|
||||
}
|
||||
|
||||
num = query->_from._collections._nrUsed;
|
||||
|
||||
collection->_name = (char*) name;
|
||||
collection->_alias = (char*) alias;
|
||||
// first collection added is always the primary collection
|
||||
collection->_isPrimary = (num == 0);
|
||||
collection->_refCount = 0; // will be used later when optimizing joins
|
||||
collection->_declarationOrder = num + 1;
|
||||
collection->_geoRestriction = NULL;
|
||||
|
||||
TRI_InsertKeyAssociativePointer(&query->_from._collections,
|
||||
collection->_alias,
|
||||
collection,
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the name of the primary collection used in the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstQueryGetPrimaryName (const QL_ast_query_t* query) {
|
||||
size_t i;
|
||||
QL_ast_query_collection_t *collection;
|
||||
|
||||
for (i = 0; i < query->_from._collections._nrAlloc; i++) {
|
||||
collection = query->_from._collections._table[i];
|
||||
if (collection != 0 && collection->_isPrimary) {
|
||||
return collection->_name;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the alias of the primary collection used in the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -196,6 +311,269 @@ char* QLAstQueryGetPrimaryAlias (const QL_ast_query_t* query) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a geo restriction prototype
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_geo_restriction_t* QLAstQueryCreateRestriction (void) {
|
||||
QL_ast_query_geo_restriction_t* restriction;
|
||||
|
||||
restriction = (QL_ast_query_geo_restriction_t*)
|
||||
TRI_Allocate(sizeof(QL_ast_query_geo_restriction_t));
|
||||
if (!restriction) {
|
||||
return NULL;
|
||||
}
|
||||
restriction->_alias = NULL;
|
||||
restriction->_compareLat._collection = NULL;
|
||||
restriction->_compareLat._field = NULL;
|
||||
restriction->_compareLon._collection = NULL;
|
||||
restriction->_compareLon._field = NULL;
|
||||
|
||||
return restriction;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clone a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_geo_restriction_t* QLAstQueryCloneRestriction
|
||||
(const QL_ast_query_geo_restriction_t* source) {
|
||||
QL_ast_query_geo_restriction_t* dest;
|
||||
|
||||
if (!source) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dest = QLAstQueryCreateRestriction();
|
||||
if (!dest) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dest->_type = source->_type;
|
||||
dest->_alias = TRI_DuplicateString(source->_alias);
|
||||
dest->_compareLat._collection = TRI_DuplicateString(source->_compareLat._collection);
|
||||
dest->_compareLat._field = TRI_DuplicateString(source->_compareLat._field);
|
||||
dest->_compareLon._collection = TRI_DuplicateString(source->_compareLon._collection);
|
||||
dest->_compareLon._field = TRI_DuplicateString(source->_compareLon._field);
|
||||
dest->_lat = source->_lat;
|
||||
dest->_lon = source->_lon;
|
||||
dest->_arg = source->_arg;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryFreeRestriction (QL_ast_query_geo_restriction_t* restriction) {
|
||||
if (restriction->_compareLat._collection) {
|
||||
TRI_Free(restriction->_compareLat._collection);
|
||||
}
|
||||
if (restriction->_compareLat._field) {
|
||||
TRI_Free(restriction->_compareLat._field);
|
||||
}
|
||||
if (restriction->_compareLon._collection) {
|
||||
TRI_Free(restriction->_compareLon._collection);
|
||||
}
|
||||
if (restriction->_compareLon._field) {
|
||||
TRI_Free(restriction->_compareLon._field);
|
||||
}
|
||||
TRI_Free(restriction);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryAddGeoRestriction (QL_ast_query_t* query,
|
||||
const TRI_query_node_t* collectionNode,
|
||||
const TRI_query_node_t* restrictionNode) {
|
||||
TRI_query_node_t* valueNode;
|
||||
QL_ast_query_collection_t* collection;
|
||||
QL_ast_query_geo_restriction_t* restriction;
|
||||
TRI_string_buffer_t* fieldName;
|
||||
char* alias;
|
||||
char* collectionAlias;
|
||||
void* previous;
|
||||
|
||||
if (!collectionNode || !restrictionNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
alias = restrictionNode->_lhs->_value._stringValue;
|
||||
assert(alias);
|
||||
|
||||
previous = (void*) TRI_LookupByKeyAssociativePointer(&query->_from._collections,
|
||||
alias);
|
||||
if (previous) {
|
||||
// alias is already used for another collection
|
||||
return false;
|
||||
}
|
||||
|
||||
previous = (void*) TRI_LookupByKeyAssociativePointer(&query->_geo._restrictions,
|
||||
alias);
|
||||
if (previous) {
|
||||
// alias is already used for another geo restriction
|
||||
return false;
|
||||
}
|
||||
|
||||
collectionAlias = ((TRI_query_node_t*) collectionNode->_rhs)->_value._stringValue;
|
||||
assert(collectionAlias);
|
||||
|
||||
collection = (QL_ast_query_collection_t*)
|
||||
TRI_LookupByKeyAssociativePointer(&query->_from._collections, collectionAlias);
|
||||
|
||||
if (!collection) {
|
||||
// collection is not present - should not happen
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(restrictionNode->_lhs);
|
||||
assert(restrictionNode->_rhs);
|
||||
|
||||
restriction = QLAstQueryCreateRestriction();
|
||||
if (!restriction) {
|
||||
return false;
|
||||
}
|
||||
restriction->_alias = alias;
|
||||
|
||||
if (restrictionNode->_type == TRI_QueryNodeRestrictWithin) {
|
||||
restriction->_type = RESTRICT_WITHIN;
|
||||
}
|
||||
else {
|
||||
restriction->_type = RESTRICT_NEAR;
|
||||
}
|
||||
|
||||
// compare field 1
|
||||
valueNode = restrictionNode->_rhs->_lhs->_lhs;
|
||||
if (strcmp(valueNode->_lhs->_value._stringValue,
|
||||
collectionAlias) != 0) {
|
||||
// field is from other collection, not valid!
|
||||
QLAstQueryFreeRestriction(restriction);
|
||||
return false;
|
||||
}
|
||||
|
||||
fieldName = QLAstQueryGetMemberNameString(valueNode, false);
|
||||
if (fieldName) {
|
||||
restriction->_compareLat._collection =
|
||||
TRI_DuplicateString(valueNode->_lhs->_value._stringValue);
|
||||
restriction->_compareLat._field = TRI_DuplicateString(fieldName->_buffer);
|
||||
TRI_FreeStringBuffer(fieldName);
|
||||
TRI_Free(fieldName);
|
||||
}
|
||||
else {
|
||||
QLAstQueryFreeRestriction(restriction);
|
||||
return false;
|
||||
}
|
||||
|
||||
// compare field 2
|
||||
valueNode = restrictionNode->_rhs->_lhs->_rhs;
|
||||
if (strcmp(valueNode->_lhs->_value._stringValue,
|
||||
collectionAlias) != 0) {
|
||||
// field is from other collection, not valid!
|
||||
QLAstQueryFreeRestriction(restriction);
|
||||
return false;
|
||||
}
|
||||
|
||||
fieldName = QLAstQueryGetMemberNameString(valueNode, false);
|
||||
if (fieldName) {
|
||||
restriction->_compareLon._collection =
|
||||
TRI_DuplicateString(valueNode->_lhs->_value._stringValue);
|
||||
restriction->_compareLon._field = TRI_DuplicateString(fieldName->_buffer);
|
||||
TRI_FreeStringBuffer(fieldName);
|
||||
TRI_Free(fieldName);
|
||||
}
|
||||
else {
|
||||
QLAstQueryFreeRestriction(restriction);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lat value
|
||||
valueNode = restrictionNode->_rhs->_rhs->_lhs;
|
||||
restriction->_lat = valueNode->_value._doubleValue;
|
||||
|
||||
// lon value
|
||||
valueNode = restrictionNode->_rhs->_rhs->_rhs;
|
||||
restriction->_lon = valueNode->_value._doubleValue;
|
||||
|
||||
if (restrictionNode->_type == TRI_QueryNodeRestrictWithin) {
|
||||
restriction->_arg._radius = restrictionNode->_value._doubleValue;
|
||||
}
|
||||
else {
|
||||
restriction->_arg._numDocuments = restrictionNode->_value._intValue;
|
||||
}
|
||||
|
||||
TRI_InsertKeyAssociativePointer(&query->_geo._restrictions,
|
||||
alias,
|
||||
restriction,
|
||||
true);
|
||||
|
||||
collection->_geoRestriction = restriction;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a string from a member name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_string_buffer_t* QLAstQueryGetMemberNameString (TRI_query_node_t* node,
|
||||
bool includeCollection) {
|
||||
TRI_query_node_t *lhs, *rhs;
|
||||
TRI_string_buffer_t* buffer;
|
||||
|
||||
buffer = (TRI_string_buffer_t*) TRI_Allocate(sizeof(TRI_string_buffer_t));
|
||||
if (!buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TRI_InitStringBuffer(buffer);
|
||||
|
||||
if (includeCollection) {
|
||||
// add collection part
|
||||
lhs = node->_lhs;
|
||||
TRI_AppendStringStringBuffer(buffer, lhs->_value._stringValue);
|
||||
TRI_AppendCharStringBuffer(buffer, '.');
|
||||
}
|
||||
|
||||
rhs = node->_rhs;
|
||||
node = rhs->_next;
|
||||
|
||||
while (node) {
|
||||
// add individual name parts
|
||||
TRI_AppendStringStringBuffer(buffer, node->_value._stringValue);
|
||||
node = node->_next;
|
||||
if (node) {
|
||||
TRI_AppendCharStringBuffer(buffer, '.');
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hash a member name for comparisons
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t QLAstQueryGetMemberNameHash (TRI_query_node_t* node) {
|
||||
TRI_query_node_t *lhs, *rhs;
|
||||
uint64_t hashValue;
|
||||
|
||||
lhs = node->_lhs;
|
||||
hashValue = TRI_FnvHashString(lhs->_value._stringValue);
|
||||
|
||||
rhs = node->_rhs;
|
||||
node = rhs->_next;
|
||||
|
||||
while (node) {
|
||||
hashValue ^= TRI_FnvHashString(node->_value._stringValue);
|
||||
node = node->_next;
|
||||
}
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
159
QL/ast-query.h
159
QL/ast-query.h
|
@ -31,21 +31,19 @@
|
|||
#include <inttypes.h>
|
||||
|
||||
#include <BasicsC/common.h>
|
||||
#include <BasicsC/conversions.h>
|
||||
#include <BasicsC/vector.h>
|
||||
#include <BasicsC/associative.h>
|
||||
#include <BasicsC/hashes.h>
|
||||
#include <BasicsC/strings.h>
|
||||
#include <BasicsC/string-buffer.h>
|
||||
|
||||
#include "QL/ast-node.h"
|
||||
|
||||
|
||||
#define QL_QUERY_NAME_LEN 64
|
||||
#include "VocBase/query-node.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
|
@ -88,12 +86,25 @@ typedef enum {
|
|||
}
|
||||
QL_ast_query_where_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ORDER BY types of a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
QLQueryOrderTypeUndefined = 0,
|
||||
|
||||
QLQueryOrderTypeMustEvaluate,
|
||||
QLQueryOrderTypeNone
|
||||
}
|
||||
QL_ast_query_order_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief SELECT part of a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_select_s {
|
||||
QL_ast_node_t *_base;
|
||||
TRI_query_node_t* _base;
|
||||
QL_ast_query_select_type_e _type;
|
||||
}
|
||||
QL_ast_query_select_t;
|
||||
|
||||
|
@ -102,7 +113,7 @@ QL_ast_query_select_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_from_s {
|
||||
QL_ast_node_t *_base;
|
||||
TRI_query_node_t* _base;
|
||||
TRI_associative_pointer_t _collections;
|
||||
}
|
||||
QL_ast_query_from_t;
|
||||
|
@ -112,8 +123,8 @@ QL_ast_query_from_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_where_s {
|
||||
QL_ast_node_t *_base;
|
||||
QL_ast_query_where_type_e _type;
|
||||
TRI_query_node_t* _base;
|
||||
QL_ast_query_where_type_e _type;
|
||||
}
|
||||
QL_ast_query_where_t;
|
||||
|
||||
|
@ -122,7 +133,8 @@ QL_ast_query_where_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_order_s {
|
||||
QL_ast_node_t *_base;
|
||||
TRI_query_node_t* _base;
|
||||
QL_ast_query_order_type_e _type;
|
||||
}
|
||||
QL_ast_query_order_t;
|
||||
|
||||
|
@ -138,6 +150,49 @@ typedef struct QL_ast_query_limit_s {
|
|||
}
|
||||
QL_ast_query_limit_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Geo restriction types
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
RESTRICT_WITHIN = 1,
|
||||
RESTRICT_NEAR = 2
|
||||
}
|
||||
QL_ast_query_geo_restriction_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief single geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_geo_restriction_s {
|
||||
char* _alias;
|
||||
QL_ast_query_geo_restriction_e _type;
|
||||
struct {
|
||||
char* _collection;
|
||||
char* _field;
|
||||
} _compareLat;
|
||||
struct {
|
||||
char* _collection;
|
||||
char* _field;
|
||||
} _compareLon;
|
||||
double _lat;
|
||||
double _lon;
|
||||
union {
|
||||
double _radius;
|
||||
size_t _numDocuments;
|
||||
} _arg;
|
||||
}
|
||||
QL_ast_query_geo_restriction_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Geo restrictions of a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_geo_s {
|
||||
TRI_associative_pointer_t _restrictions;
|
||||
}
|
||||
QL_ast_query_geo_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Query declaration
|
||||
///
|
||||
|
@ -156,6 +211,7 @@ typedef struct QL_ast_query_s {
|
|||
QL_ast_query_where_t _where;
|
||||
QL_ast_query_order_t _order;
|
||||
QL_ast_query_limit_t _limit;
|
||||
QL_ast_query_geo_t _geo;
|
||||
}
|
||||
QL_ast_query_t;
|
||||
|
||||
|
@ -164,9 +220,12 @@ QL_ast_query_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct QL_ast_query_collection_s {
|
||||
char *_name;
|
||||
char *_alias;
|
||||
bool _isPrimary;
|
||||
char* _name;
|
||||
char* _alias;
|
||||
bool _isPrimary;
|
||||
size_t _refCount;
|
||||
size_t _declarationOrder;
|
||||
QL_ast_query_geo_restriction_t* _geoRestriction;
|
||||
}
|
||||
QL_ast_query_collection_t;
|
||||
|
||||
|
@ -182,23 +241,42 @@ void QLAstQueryInit (QL_ast_query_t*);
|
|||
|
||||
void QLAstQueryFree (QL_ast_query_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the ref count for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t QLAstQueryGetRefCount (QL_ast_query_t*, const char*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Increment ref count for a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryAddRefCount (QL_ast_query_t*, const char*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Check if a collection was defined in a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryIsValidAlias (QL_ast_query_t*, const char*);
|
||||
bool QLAstQueryIsValidAlias (QL_ast_query_t*, const char*, const size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Check if a collection was defined in a query, taking order of
|
||||
/// declaration into account
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryIsValidAliasOrdered (QL_ast_query_t*, const char*, const size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Return the collection name for its alias
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstQueryGetCollectionNameForAlias (QL_ast_query_t*, const char*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Add a collection to the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryAddCollection (QL_ast_query_t*, const char*, const char*, const bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the name of the primary collection used in the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* QLAstQueryGetPrimaryName (const QL_ast_query_t*);
|
||||
bool QLAstQueryAddCollection (QL_ast_query_t*, const char*, const char*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the alias of the primary collection used in the query
|
||||
|
@ -206,6 +284,45 @@ char* QLAstQueryGetPrimaryName (const QL_ast_query_t*);
|
|||
|
||||
char* QLAstQueryGetPrimaryAlias (const QL_ast_query_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get a geo restriction prototype
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_geo_restriction_t* QLAstQueryCreateRestriction (void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clone a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QL_ast_query_geo_restriction_t* QLAstQueryCloneRestriction
|
||||
(const QL_ast_query_geo_restriction_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief free a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLAstQueryFreeRestriction (QL_ast_query_geo_restriction_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief add a geo restriction
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool QLAstQueryAddGeoRestriction (QL_ast_query_t*,
|
||||
const TRI_query_node_t*,
|
||||
const TRI_query_node_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Create a string from a member name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_string_buffer_t* QLAstQueryGetMemberNameString (TRI_query_node_t*, bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Hash a member name for comparisons
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint64_t QLAstQueryGetMemberNameHash (TRI_query_node_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
87
QL/error.c
87
QL/error.c
|
@ -1,87 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief error codes and translations
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "QL/error.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get label/translation for an error code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char *QLErrorGetLabel (const QL_error_type_e errorCode) {
|
||||
switch (errorCode) {
|
||||
case ERR_PARSE:
|
||||
return "parse error: %s";
|
||||
case ERR_NUMBER_OUT_OF_RANGE:
|
||||
return "number '%s' is out of range";
|
||||
case ERR_LIMIT_VALUE_OUT_OF_RANGE:
|
||||
return "limit value '%s' is out of range";
|
||||
case ERR_PARAMETER_NUMBER_OUT_OF_RANGE:
|
||||
return "parameter number '%s' is out of range";
|
||||
case ERR_COLLECTION_NAME_INVALID:
|
||||
return "collection name '%s' or alias is invalid";
|
||||
case ERR_COLLECTION_NAME_REDECLARED:
|
||||
return "collection alias '%s' is declared multiple times";
|
||||
case ERR_COLLECTION_NAME_UNDECLARED:
|
||||
return "collection alias '%s' was not declared in the from clause";
|
||||
default:
|
||||
return "unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a formatted error message with wildcards replaced
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char *QLErrorFormat(const QL_error_type_e errorCode, va_list args) {
|
||||
char buffer[1024];
|
||||
char *format;
|
||||
|
||||
format = QLErrorGetLabel(errorCode);
|
||||
|
||||
vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
return (char *) TRI_DuplicateString((const char*) &buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
93
QL/error.h
93
QL/error.h
|
@ -1,93 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief error codes and translations
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_QL_ERROR
|
||||
#define TRIAGENS_DURHAM_QL_ERROR
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <BasicsC/strings.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup QL
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enumeration of possible parse errors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef enum {
|
||||
ERR_OK = 0,
|
||||
ERR_PARSE = 1,
|
||||
ERR_NUMBER_OUT_OF_RANGE = 100,
|
||||
ERR_PARAMETER_NUMBER_OUT_OF_RANGE = 101,
|
||||
ERR_LIMIT_VALUE_OUT_OF_RANGE = 102,
|
||||
ERR_COLLECTION_NAME_INVALID = 110,
|
||||
ERR_COLLECTION_NAME_REDECLARED = 111,
|
||||
ERR_COLLECTION_NAME_UNDECLARED = 112,
|
||||
|
||||
ERR_LAST
|
||||
}
|
||||
QL_error_type_e;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get label/translation for an error code
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char *QLErrorGetLabel (const QL_error_type_e);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a formatted error message with wildcards replaced
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char *QLErrorFormat(const QL_error_type_e, va_list args);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|// --SECTION--\\|/// @\\}\\)"
|
||||
// End:
|
||||
|
|
@ -25,7 +25,6 @@
|
|||
/// @author Copyright 2012, triagens GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "QL/formatter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,7 +37,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLFormatterIndentationInc (QL_formatter_t* formatter) {
|
||||
formatter->indentLevel++;
|
||||
formatter->_indentLevel++;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -46,7 +45,7 @@ void QLFormatterIndentationInc (QL_formatter_t* formatter) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLFormatterIndentationDec (QL_formatter_t* formatter) {
|
||||
formatter->indentLevel--;
|
||||
formatter->_indentLevel--;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,7 +55,7 @@ void QLFormatterIndentationDec (QL_formatter_t* formatter) {
|
|||
void QLFormatterPrintIndentation (QL_formatter_t* formatter) {
|
||||
unsigned int i=0;
|
||||
|
||||
for (; i < formatter->indentLevel; i++) {
|
||||
for (; i < formatter->_indentLevel; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
@ -110,26 +109,26 @@ void QLFormatterPrintStr (QL_formatter_t* formatter, const char* name, const cha
|
|||
/// @brief Recursively dump an AST
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void QLFormatterDump (QL_ast_node_t* node, QL_formatter_t* formatter, const int blockBehaviour) {
|
||||
void QLFormatterDump (TRI_query_node_t* node, QL_formatter_t* formatter) {
|
||||
const char* name;
|
||||
QL_ast_node_type_e type;
|
||||
QL_ast_node_t *lhs;
|
||||
QL_ast_node_t *rhs;
|
||||
QL_ast_node_t *next;
|
||||
TRI_query_node_type_e type;
|
||||
TRI_query_node_t* lhs;
|
||||
TRI_query_node_t* rhs;
|
||||
TRI_query_node_t* next;
|
||||
|
||||
if (node == 0) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
type = node->_type;
|
||||
name = QLAstNodeGetName(type);
|
||||
name = TRI_QueryNodeGetName(type);
|
||||
|
||||
if (type == QLNodeContainerList) {
|
||||
if (type == TRI_QueryNodeContainerList) {
|
||||
next = node->_next;
|
||||
QLFormatterPrintBlockStart(formatter,name);
|
||||
QLFormatterIndentationInc(formatter);
|
||||
while (next) {
|
||||
QLFormatterDump(next,formatter,1);
|
||||
QLFormatterDump(next,formatter);
|
||||
next = next->_next;
|
||||
}
|
||||
QLFormatterIndentationDec(formatter);
|
||||
|
@ -140,30 +139,32 @@ void QLFormatterDump (QL_ast_node_t* node, QL_formatter_t* formatter, const int
|
|||
QLFormatterPrintBlockStart(formatter,name);
|
||||
QLFormatterIndentationInc(formatter);
|
||||
|
||||
if (type == QLNodeValueString || type ==QLNodeValueNumberDoubleString ||
|
||||
type == QLNodeValueIdentifier || type == QLNodeValueParameterNamed ||
|
||||
type == QLNodeReferenceCollectionAlias) {
|
||||
QLFormatterPrintStr(formatter,"value",node->_value._stringValue);
|
||||
} else if (type == QLNodeValueNumberInt) {
|
||||
QLFormatterPrintInt(formatter,"value",node->_value._intValue);
|
||||
} else if (type == QLNodeValueNumberDouble) {
|
||||
QLFormatterPrintDouble(formatter,"value",node->_value._doubleValue);
|
||||
} else if (type == QLNodeValueBool) {
|
||||
QLFormatterPrintStr(formatter,"value",node->_value._boolValue ? "true" : "false");
|
||||
} else if (type == QLNodeValueOrderDirection) {
|
||||
QLFormatterPrintStr(formatter,"value",node->_value._boolValue ? "asc" : "desc");
|
||||
} else if (type == QLNodeValueParameterNumeric) {
|
||||
QLFormatterPrintInt(formatter,"value",node->_value._intValue);
|
||||
if (type == TRI_QueryNodeValueString ||
|
||||
type == TRI_QueryNodeValueNumberDoubleString ||
|
||||
type == TRI_QueryNodeValueIdentifier ||
|
||||
type == TRI_QueryNodeValueParameterNamed ||
|
||||
type == TRI_QueryNodeReferenceCollectionAlias) {
|
||||
QLFormatterPrintStr(formatter,"value", node->_value._stringValue);
|
||||
} else if (type == TRI_QueryNodeValueNumberInt) {
|
||||
QLFormatterPrintInt(formatter,"value", node->_value._intValue);
|
||||
} else if (type == TRI_QueryNodeValueNumberDouble) {
|
||||
QLFormatterPrintDouble(formatter,"value", node->_value._doubleValue);
|
||||
} else if (type == TRI_QueryNodeValueBool) {
|
||||
QLFormatterPrintStr(formatter,"value", node->_value._boolValue ? "true" : "false");
|
||||
} else if (type == TRI_QueryNodeValueOrderDirection) {
|
||||
QLFormatterPrintStr(formatter,"value", node->_value._boolValue ? "asc" : "desc");
|
||||
} else if (type == TRI_QueryNodeValueParameterNumeric) {
|
||||
QLFormatterPrintInt(formatter,"value", node->_value._intValue);
|
||||
}
|
||||
|
||||
lhs = node->_lhs;
|
||||
if (lhs != 0) {
|
||||
QLFormatterDump(lhs,formatter,0);
|
||||
if (lhs) {
|
||||
QLFormatterDump(lhs, formatter);
|
||||
}
|
||||
|
||||
rhs = node->_rhs;
|
||||
if (rhs != 0) {
|
||||
QLFormatterDump(rhs,formatter,0);
|
||||
if (rhs) {
|
||||
QLFormatterDump(rhs, formatter);
|
||||
}
|
||||
|
||||
QLFormatterIndentationDec(formatter);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue