1
0
Fork 0

Merge branch 'devel' of https://github.com/triAGENS/AvocadoDB into devel

Conflicts:
	Makefile.in
This commit is contained in:
Frank Celler 2012-02-29 20:59:10 +01:00
commit 9420b58437
218 changed files with 24915 additions and 15561 deletions

4
.gitignore vendored
View File

@ -51,3 +51,7 @@ stamp-h*
config.h
3rdParty/libev/libtool
out
3rdParty/libev/ARCH.x64
.v8-build
.libev-build
Doxygen/js

View File

@ -30,7 +30,7 @@ boost
protected:
~error_info_base() throw()
virtual ~error_info_base() throw()
{
}
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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
// -----------------------------------------------------------------------------

View File

@ -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);

View File

@ -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

View File

@ -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);
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,5 +1,5 @@
////////////////////////////////////////////////////////////////////////////////
/// @brief hash functions
/// @brief hash functions
///
/// @file
///
@ -35,7 +35,7 @@ extern "C" {
#endif
// -----------------------------------------------------------------------------
// --SECTION-- FNV
// --SECTION-- (FNV-1a FowlerNollVo 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);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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, &copy);
TRI_CopyToJson(&copy, 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, &copy);
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;

View File

@ -71,6 +71,12 @@
#undef TRI_ENABLE_TIMING
////////////////////////////////////////////////////////////////////////////////
/// @brief memory allocation failures
////////////////////////////////////////////////////////////////////////////////
#undef TRI_ENABLE_MEMFAIL
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -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 }

View File

@ -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

View File

@ -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 }

View File

@ -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 }

View File

@ -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

View File

@ -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 }

View File

@ -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 }

View File

@ -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 }

View File

@ -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

View File

@ -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 }

View File

@ -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"
]
}

View File

@ -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

View File

@ -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}

View File

@ -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}

View File

@ -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

View File

@ -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 }

View File

@ -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 }

View File

@ -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 }

View File

@ -1 +1 @@
{collection-name} {collection-alias}
collection-name collection-alias

View File

@ -1,3 +1,5 @@
users u
locations locs
visitors v
`select` s
`select` `select`

View File

@ -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 }

View File

@ -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 )

View File

@ -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 )

View File

@ -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)

View File

@ -0,0 +1 @@
SELECT { name: u.name } FROM users u WHERE u.name == 'Fox'

View File

@ -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 }

View File

@ -0,0 +1,2 @@
avocado> db.five.all().limit(2).count(true);
2

View File

@ -0,0 +1,2 @@
avocado> edges.edges-collection.edges("195189:1702517");
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]

View File

@ -0,0 +1,2 @@
avocado> edges.edges-collection.inEdges("195189:1833589");
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]

View File

@ -0,0 +1,2 @@
avocado> edges.edges-collection.inEdges("195189:1702517");
[ { _id : 2030197:3537525, _rev : 3537525, _from : 195189:1702517, _to : 195189:1833589, label : knows } ]

View File

@ -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 ] } ]

View File

@ -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 ] } ]

View File

@ -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 ] } ]

View File

@ -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 ] } ]

View File

@ -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 } ]

View File

@ -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 } ]

View File

@ -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 }

View File

@ -0,0 +1,2 @@
avocado> db.five.all().next();
{ _id : 159896:1798296, _rev : 1798296, doc : 3 }

View File

@ -0,0 +1,2 @@
avocado> db.five.all().nextRef();
159896:1798296

View File

@ -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 }

View File

@ -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 } ]

View File

@ -0,0 +1,2 @@
avocado> db.five.all().limit(2).count();
5

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 ();
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -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 ();
////////////////////////////////////////////////////////////////////////////////
/// @}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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 */

651
HashIndex/hashindex.c Executable file
View File

@ -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;
}

107
HashIndex/hashindex.h Executable file
View File

@ -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*);

View File

@ -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 {

View File

@ -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;

View File

@ -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 MySqls \
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
"

View File

@ -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

View File

@ -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>

View File

@ -46,7 +46,7 @@ namespace triagens {
class HttpRequest;
namespace InputParser {
class ObjectDescriptionImpl;
struct ObjectDescriptionImpl;
////////////////////////////////////////////////////////////////////////////////
/// @ingroup Utilities

View File

@ -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 */

View File

@ -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;
}

View File

@ -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"

View File

@ -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

View File

@ -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))

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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;
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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*);
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////

View File

@ -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:

View File

@ -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:

View File

@ -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