mirror of https://gitee.com/bigwinds/arangodb
improved interface to GEO SPATIAL index
This commit is contained in:
parent
d5d2534fbc
commit
36fa9bc0b4
|
@ -28,6 +28,7 @@
|
|||
#include "conversions.h"
|
||||
|
||||
#include <Basics/strings.h>
|
||||
#include <Basics/string-buffer.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions for string to number
|
||||
|
@ -398,6 +399,19 @@ char* TRI_StringUInt64 (uint64_t attr) {
|
|||
return TRI_DuplicateString(buffer);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to string from double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_StringDouble (double value) {
|
||||
TRI_string_buffer_t buffer;
|
||||
|
||||
TRI_InitStringBuffer(&buffer);
|
||||
TRI_AppendDoubleStringBuffer(&buffer, value);
|
||||
|
||||
return buffer._buffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -128,6 +128,12 @@ char* TRI_StringInt64 (int64_t);
|
|||
|
||||
char* TRI_StringUInt64 (uint64_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief convert to string from double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char* TRI_StringDouble (double);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,837 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief High-Performance Database Framework made by triagens
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 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 Martin Schoenert
|
||||
/// @author Copyright 2009-2010, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page FruitSort Fruit Sort
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_TYPE
|
||||
///
|
||||
/// The directive @ec FSRT_TYPE refers to the type of each element which is to
|
||||
/// be sorted. If this directive is undefined, then the type @c char* is used
|
||||
/// instead, which may result in a reduction in the speed of the sort
|
||||
/// algorithm. For example,
|
||||
///
|
||||
/// If you define @c FSRT_TYPE the corresponding macros functions will have the
|
||||
/// following signatures:
|
||||
///
|
||||
/// <tt>void FSRT_NAME( FSRT_TYPE * fs_b, FSRT_TYPE * fs_e )</tt> @n
|
||||
/// <tt>int FSRT_LT( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>int FSRT_EQ( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>int FSRT_COMP( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>void FSRT_COPY( FSRT_TYPE * fs_x, FSRT_TYPE * fs_y, size_t fs_s )</tt> @n
|
||||
///
|
||||
/// If @c FSRT_TYPE is undefined the corresponding macros functions will macros
|
||||
/// have the following signatures:
|
||||
///
|
||||
/// <tt>void FSRT_NAME( char * fs_b, char * fs_e, size_t fs_s, char * fs_t )</tt> @n
|
||||
/// <tt>int FSRT_LT( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>int FSRT_EQ( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>int FSRT_COMP( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
|
||||
/// <tt>void FSRT_COPY( char * fs_x, char * fs_y, size_t fs_s )</tt> @n
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_NAME
|
||||
///
|
||||
/// The pre-processor directive @c FSRT_NAME must be defined.
|
||||
///
|
||||
/// The function @c FSRT_NAME(fs_b,fs_e) sorts an array of statically sized
|
||||
/// elements. The parameters @c fs_b and @c fs_e are pointers or iterators
|
||||
/// which access the first and last - 1 element.
|
||||
///
|
||||
/// The function @c FSRT_NAME(fs_b,fs_e,fs_s,fs_t) can be used to sort elements
|
||||
/// whose complete type and size is unkown at compile time. The additional
|
||||
/// parameter @c fs_s refers to the size of the elements, while the parameter
|
||||
/// @c fs_t refers to a location in memory used to store a temporary element.
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_UNIQ
|
||||
///
|
||||
/// The directive @c FSRT_UNIQ provides a hint that the elements to be sorted
|
||||
/// are unique (or little repetitions). In this case, the sorting algorithm will
|
||||
/// use a 2-way partitioning of the elements into <= and >=. The default
|
||||
/// alogorithm is a 3-way partitioning of the elements into <, = and >.
|
||||
///
|
||||
/// Define this directive when know that the number of repetitions is small.
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_INSR
|
||||
///
|
||||
/// The directive @c FSRT_INSR represents the cutoff where the algorithm
|
||||
/// switches from quick sort to insertion sort, i.e. subranges shorter than
|
||||
/// @c FSRT_INSR will be sorted with Insertion sort algorithm rather than the
|
||||
/// Quicksort algorithm.
|
||||
///
|
||||
/// Thus optimal value for @c FSRT_INSR is dependent on the costs associated
|
||||
/// with the comparisons copies of elements. The default value of 8 (when
|
||||
/// @c FSRT_INSR is undefined) is reasonable most of the time. If the cost of
|
||||
/// comparisons and copies is small, you can use larger values (up to about 40)
|
||||
/// to increase performance. Consider reducing the value of @c FSRT_INSR where
|
||||
/// the cost of comparisons and copies is high (down to 4).
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_THREE
|
||||
///
|
||||
/// The directive @c FSRT_THREE represents the cutoff for median of 3 pivot
|
||||
/// selection. Defaults to 10 unless otherwise defined. The directive
|
||||
/// @c FSRT_NINE represents the cutoff for median of 9 pivot selection.
|
||||
/// Defaults to 10 unless otherwise defined.
|
||||
///
|
||||
/// @section Pre-processor directive FSRT_EXTRA_ARGS
|
||||
///
|
||||
/// The directive @c FSRT_EXTRA_ARGS provides a list of additional arguments
|
||||
/// which may be required by the copy and comparison functions.
|
||||
/// @c FSRT_EXTRA_ARGS is a comma separated list of names of the additional
|
||||
/// function arguments required. By default no additional arguments are defined.
|
||||
/// The directive @c FSRT_EXTRA_DECL provides additional declarations for any
|
||||
/// extra arguments which may be required. @c FSRT_EXTRA_DECL is a comman
|
||||
/// separated list of declarations.
|
||||
///
|
||||
/// By default no additional declarations are defined. For example:
|
||||
///
|
||||
/// <tt>#define FSRT_EXTRA_ARGS dsd, loc</tt> @n
|
||||
/// <tt>#define FSRT_EXTRA_DECL DataSetDescription* dsd, Locale* loc</tt> @n
|
||||
/// <tt>#define FSRT_LT(x,y,s,d,l) my_str_cmp(x,y,d,l)</tt> @n
|
||||
///
|
||||
/// @section Required Directives
|
||||
///
|
||||
/// @c FSRT_NAME and @c FSRT_NAM2.
|
||||
///
|
||||
/// @section Required Macros
|
||||
///
|
||||
/// @c FSRT_LT and @c FSRT_EQ or @c FSRT_COMP.
|
||||
///
|
||||
/// @section Optional Macros
|
||||
///
|
||||
/// @c FSRT_COPY, @c FSRT_TYPE, @c FSRT_UNIQ, @c FSRT_INSR, @c FSRT_THREE,
|
||||
/// @c FSRT_NINE @c FSRT_EXTRA_ARGS, @c FSRT_EXTRA_DECL, @c FSRT_COUNT, @c
|
||||
/// FSRT_DEBUG, @c FSRT_COUNT.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup FruitSort Fruit Sort
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT_COUNT
|
||||
/// @brief statistics buffer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_COUNT
|
||||
static uint32_t FSRT_Count [20];
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__TYPE
|
||||
/// @brief the type of the elements which are begin sorted
|
||||
///
|
||||
/// Optional. Unless specified the type defaults to a @c char.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__UNIT
|
||||
/// @brief the size of an element specified in terms of the @c FSRT_TYPE
|
||||
///
|
||||
/// When the default value of @c FSRT_TYPE is @c char, this defaults
|
||||
/// to the size of the elements in bytes. That is, @c fs_s.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__SIZE
|
||||
/// @brief the size of an element given in bytes
|
||||
///
|
||||
/// That is, @a fs_s.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__TEMP
|
||||
/// @brief the address of some memory storage set aside for an element
|
||||
///
|
||||
/// The address of some memory storage set aside at least as large as the size
|
||||
/// of an element. This temporary storage is used by the function @c FSRT_NAME.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__DIST
|
||||
/// @brief The number of elements between a given two elements.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_TYPE
|
||||
|
||||
#define FSRT__TYPE FSRT_TYPE
|
||||
#define FSRT__UNIT 1
|
||||
#define FSRT__SIZE sizeof(FSRT_TYPE)
|
||||
#define FSRT__TEMP &fs_t
|
||||
#define FSRT__DIST(fs_x,fs_y,fs_s) ((fs_x) - (fs_y))
|
||||
|
||||
#else
|
||||
|
||||
#define FSRT__TYPE char
|
||||
#define FSRT__UNIT (fs_s)
|
||||
#define FSRT__SIZE (fs_s)
|
||||
#define FSRT__TEMP fs_t
|
||||
#define FSRT__DIST(fs_x,fs_y,fs_s) (((fs_x) - (fs_y)) / (fs_s))
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__LT(x,y,s,d)
|
||||
/// @brief less-than comparison
|
||||
///
|
||||
/// Returns true if @c x is less than @c y. Otherwise, returns false.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__EQ(x,y,s,d)
|
||||
/// @brief equal-than comparison
|
||||
///
|
||||
/// Returns the integer 0 if the elements @c x and @c y both of size @c s are
|
||||
/// equal. A non-zero value is returned otherwise.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__LEC(x,y,s,d)
|
||||
/// @brief comparison
|
||||
///
|
||||
/// Sets the var @c fs_c to the result of a comparision of @c x and @c y. A
|
||||
/// value of 0 indicates equality between @c x and @c y. This variable is used
|
||||
/// as part of the sorting algorithm.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__EQC(x,y,s,d)
|
||||
/// @brief equalitity test
|
||||
///
|
||||
/// Performs a test of equality between @c x and @c y. The value of the variable
|
||||
/// @a fs_c contains an integer which is the result of a @em previous
|
||||
/// comparision between @a x and @a y.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_LT
|
||||
|
||||
#ifndef FSRT__COUNT
|
||||
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) FSRT_LT((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
|
||||
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
|
||||
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (! FSRT_LT((fs_y),(fs_x),(fs_s) FSRT__EXTRA_ARGS))
|
||||
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
|
||||
#else
|
||||
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_LT((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
|
||||
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
|
||||
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (! FSRT_LT((fs_y),(fs_x),(fs_s) FSRT__EXTRA_ARGS)))
|
||||
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_EQ((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef FSRT__COUNT
|
||||
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) < 0)
|
||||
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) == 0)
|
||||
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) ((fs_c = FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)) <= 0)
|
||||
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (fs_c == 0)
|
||||
#else
|
||||
#define FSRT__LT(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) < 0))
|
||||
#define FSRT__EQ(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS) == 0))
|
||||
#define FSRT__LEC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, ((fs_c = FSRT_COMP((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)) <= 0))
|
||||
#define FSRT__EQC(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (fs_c == 0))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__COPY
|
||||
/// @brief copies one element onto another
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__SWAP
|
||||
/// @brief swaps two elements
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_COPY
|
||||
|
||||
#ifndef FSRT__COUNT
|
||||
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) FSRT_COPY((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS)
|
||||
#else
|
||||
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, FSRT_COPY((fs_x),(fs_y),(fs_s) FSRT__EXTRA_ARGS))
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef FSRT__COUNT
|
||||
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (memmove( (char*)(fs_x), (char*)(fs_y), (fs_s) ))
|
||||
#else
|
||||
#define FSRT__COPY(fs_x,fs_y,fs_s,fs_d) (FSRT_Count[(fs_d)]++, (memcpy( (char*)(fs_x), (char*)(fs_y), (fs_s) )))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define FSRT__SWAP(fs_x,fs_y,fs_s,fs_d) (FSRT__COPY( FSRT__TEMP, (fs_x), (fs_s), (fs_d) ), \
|
||||
FSRT__COPY( (fs_x), (fs_y), (fs_s), (0) ), \
|
||||
FSRT__COPY( (fs_y), FSRT__TEMP, (fs_s), (0) ))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__INSR
|
||||
/// @brief Cutoff point when to use the insertion short algorithm.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_INSR
|
||||
#define FSRT__INSR FSRT_INSR
|
||||
#else
|
||||
#define FSRT__INSR 8
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__THREE
|
||||
/// @brief Used for sorting short arrays.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__NINE
|
||||
/// @brief Used for sorting short arrays.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_THREE
|
||||
#define FSRT__THREE FSRT_THREE
|
||||
#else
|
||||
#define FSRT__THREE 10
|
||||
#endif
|
||||
#ifdef FSRT_NINE
|
||||
#define FSRT__NINE FSRT_NINE
|
||||
#else
|
||||
#define FSRT__NINE 40
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__EXTRA_ARGS
|
||||
/// @brief additional arguments which may be required for the algorithm
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__EXTRA_DECL
|
||||
/// @brief additional declarations which may be required for the algorithm
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_EXTRA_ARGS
|
||||
#define FSRT__EXTRA_ARGS , FSRT_EXTRA_ARGS
|
||||
#define FSRT__EXTRA_DECL , FSRT_EXTRA_DECL
|
||||
#else
|
||||
#define FSRT__EXTRA_ARGS // none
|
||||
#define FSRT__EXTRA_DECL // none
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn FSRT__TYPE * FSRT_NAM2 (
|
||||
/// FSRT__TYPE * fs_x,
|
||||
/// FSRT__TYPE * fs_y,
|
||||
/// FSRT__TYPE * fs_z
|
||||
/// FSRT__EXTRA_DECL )
|
||||
///
|
||||
/// @brief returns the middle element given three elements
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__MED3
|
||||
/// @brief an alias for the FSRT_NAM2 function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_TYPE
|
||||
|
||||
#define FSRT__MED3(fs_x,fs_y,fs_z,fs_s) FSRT_NAM2((fs_x),(fs_y),(fs_z) FSRT__EXTRA_ARGS)
|
||||
|
||||
FSRT__TYPE * FSRT_NAM2 (
|
||||
FSRT__TYPE * fs_x,
|
||||
FSRT__TYPE * fs_y,
|
||||
FSRT__TYPE * fs_z
|
||||
FSRT__EXTRA_DECL ) {
|
||||
|
||||
#else
|
||||
|
||||
#define FSRT__MED3(fs_x,fs_y,fs_z,fs_s) FSRT_NAM2((fs_x),(fs_y),(fs_z),(fs_s) FSRT__EXTRA_ARGS)
|
||||
|
||||
FSRT__TYPE * FSRT_NAM2 (
|
||||
FSRT__TYPE * fs_x,
|
||||
FSRT__TYPE * fs_y,
|
||||
FSRT__TYPE * fs_z,
|
||||
size_t fs_s
|
||||
FSRT__EXTRA_DECL ) {
|
||||
|
||||
#endif
|
||||
|
||||
if ( FSRT__LT( fs_x, fs_y, FSRT__SIZE, 1 ) ) {
|
||||
if ( FSRT__LT( fs_y, fs_z, FSRT__SIZE, 1 ) ) { return fs_y; }
|
||||
else if ( FSRT__LT( fs_x, fs_z, FSRT__SIZE, 1 ) ) { return fs_z; }
|
||||
else { return fs_x; }
|
||||
}
|
||||
else {
|
||||
if ( FSRT__LT( fs_x, fs_z, FSRT__SIZE, 1 ) ) { return fs_x; }
|
||||
else if ( FSRT__LT( fs_y, fs_z, FSRT__SIZE, 1 ) ) { return fs_z; }
|
||||
else { return fs_y; }
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @var FSRT_Rand
|
||||
/// @brief stores the position of the current random element within the array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FSRT__RAND
|
||||
uint32_t FSRT_Rand;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__RAND
|
||||
/// @brief computes a quasi-random element
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef FSRT__RAND
|
||||
#define FSRT__RAND \
|
||||
((fs_b) + FSRT__UNIT * ((FSRT_Rand = FSRT_Rand * 31415 + 27818) % FSRT__DIST(fs_e,fs_b,FSRT__SIZE)))
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn void FSRT_NAME (
|
||||
/// FSRT__TYPE * fs_b,
|
||||
/// FSRT__TYPE * fs_e
|
||||
/// FSRT__EXTRA_DECL )
|
||||
///
|
||||
/// @brief The actual sorting algorithm.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @def FSRT__SORT
|
||||
///
|
||||
/// @brief An alias for the sorting algorithm FSRT_NAME.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef FSRT_TYPE
|
||||
|
||||
#define FSRT__SORT(fs_x,fs_y,fs_s,fs_t) FSRT_NAME((fs_x),(fs_y) FSRT__EXTRA_ARGS)
|
||||
|
||||
void FSRT_NAME (
|
||||
FSRT__TYPE * fs_b,
|
||||
FSRT__TYPE * fs_e
|
||||
FSRT__EXTRA_DECL ) {
|
||||
FSRT__TYPE * fs_l;
|
||||
FSRT__TYPE * fs_r;
|
||||
FSRT__TYPE * fs_p;
|
||||
#ifndef FSRT_UNIQ
|
||||
FSRT__TYPE * fs_m;
|
||||
FSRT__TYPE * fs_q;
|
||||
#endif
|
||||
FSRT__TYPE fs_t;
|
||||
|
||||
#else
|
||||
|
||||
#define FSRT__SORT(fs_x,fs_y,fs_s,fs_t) FSRT_NAME((fs_x),(fs_y),(fs_s),(fs_t) FSRT__EXTRA_ARGS)
|
||||
|
||||
void FSRT_NAME (
|
||||
FSRT__TYPE * fs_b,
|
||||
FSRT__TYPE * fs_e,
|
||||
size_t fs_s,
|
||||
FSRT__TYPE * fs_t
|
||||
FSRT__EXTRA_DECL ) {
|
||||
|
||||
FSRT__TYPE * fs_l;
|
||||
FSRT__TYPE * fs_r;
|
||||
FSRT__TYPE * fs_p;
|
||||
#ifndef FSRT_UNIQ
|
||||
FSRT__TYPE * fs_m;
|
||||
FSRT__TYPE * fs_q;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef FSRT_LT
|
||||
int fs_c;
|
||||
#endif
|
||||
|
||||
// iterate while the number of elements in the range is large enough
|
||||
while ( FSRT__INSR <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
|
||||
|
||||
// for larger ranges take the median-of-median of nine random elms
|
||||
if ( FSRT__NINE <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
|
||||
fs_l = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
|
||||
fs_r = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
|
||||
fs_p = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
|
||||
fs_p = FSRT__MED3( fs_l, fs_r, fs_p, FSRT__SIZE );
|
||||
}
|
||||
|
||||
// for smaller ranges take the median of three random elms
|
||||
else if ( FSRT__THREE <= FSRT__DIST(fs_e,fs_b,FSRT__SIZE) ) {
|
||||
fs_p = FSRT__MED3( FSRT__RAND, FSRT__RAND, FSRT__RAND, FSRT__SIZE );
|
||||
}
|
||||
|
||||
// and for very small ranges take one random element
|
||||
else {
|
||||
fs_p = FSRT__RAND;
|
||||
}
|
||||
|
||||
// swap the pivot to the beg pos (out of the way for partitioning)
|
||||
FSRT__SWAP( fs_b, fs_p, FSRT__SIZE, 4 );
|
||||
|
||||
#ifdef FSRT_UNIQ
|
||||
|
||||
// 2-way partitioning into elements le and ge.
|
||||
// Swap elements smaller (or equal) to the pivot to the left,
|
||||
// and elements larger (or equal) to the pivot to the right.
|
||||
// Note that scanning pointers stop on and exchange equal elements
|
||||
// This is important if we sort arrays with few different keys
|
||||
// because after a few iterations the subranges contain only
|
||||
// elements with equal keys, and if we would scan over elements
|
||||
// equal to the pivot, the right pointer would scan all the way
|
||||
// down and the quick sort would degenerate to a quadratic algo.
|
||||
|
||||
#define FSRT__UNIQ__ALG1
|
||||
#ifdef FSRT__UNIQ__ALG1
|
||||
|
||||
// Note that this code is a lot trickier than it appears ;-)
|
||||
// It is faster than other more obvious formulations, because
|
||||
// it compares every element exactly once to the pivot and
|
||||
// it keeps the number of statements (especially jumps) minimal
|
||||
// so the optimizer can generate compact and fast code.
|
||||
|
||||
fs_p = fs_b;
|
||||
fs_l = fs_b;
|
||||
fs_r = fs_e;
|
||||
|
||||
// *(b==l) <= *p and *p <= *r .. *(e-1) since the set is empty
|
||||
while ( fs_l < fs_r ) {
|
||||
|
||||
// *b .. *(l-1) *l <= *p *p <= *r *(r+1) .. *(e-1)
|
||||
do { fs_r -= FSRT__UNIT; }
|
||||
while ( fs_l < fs_r && FSRT__LT( fs_p, fs_r, FSRT__SIZE, 2 ) );
|
||||
|
||||
// *p >= *r *p <= *(r+1) .. *(e-1)
|
||||
do { fs_l += FSRT__UNIT; }
|
||||
while ( fs_l < fs_r && FSRT__LT( fs_l, fs_p, FSRT__SIZE, 2 ) );
|
||||
|
||||
// *b .. *(l-1) <= *p and ((l < r & *l >= *p) or (l >= r))
|
||||
if ( fs_l < fs_r ) {
|
||||
|
||||
// .. *(l-1) <= *p *l >= *p *p >= *r *p <= *(r+1) ..
|
||||
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
|
||||
// *b .. *(l-1) *l <= *p *p >= *r *(r+1) .. *(e-1)
|
||||
}
|
||||
}
|
||||
|
||||
// l == r and *b .. *(l-1) *(l==r) <= *p <= *(r+1) .. *(e-1)
|
||||
// l == r+1 and *b .. *(l-1==r) <= *p <= *(l==r+1) .. *(e-1)
|
||||
|
||||
// swap the pivot to the middle
|
||||
FSRT__SWAP( fs_b, fs_r, FSRT__SIZE, 4 );
|
||||
fs_l = fs_r;
|
||||
fs_r = fs_l + FSRT__UNIT;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FSRT__UNIQ__ALG2
|
||||
|
||||
// This is a 2-way partitioning algorithm.
|
||||
// It performs exactely the same comparisons and swaps as alg1.
|
||||
// However it is formulated slightly different.
|
||||
// This is bad for the performance (the code is bit slower).
|
||||
// But I leave it in here, because this algorithm serves as a good
|
||||
// starting point for the 3-way partitioning algorithm below.
|
||||
|
||||
fs_p = fs_b;
|
||||
fs_l = fs_b+FSRT__UNIT;
|
||||
fs_r = fs_e-FSRT__UNIT;
|
||||
|
||||
while ( 1 ) {
|
||||
while ( fs_l <= fs_r && FSRT__LT( fs_p, fs_r, FSRT__SIZE, 2 ) ) {
|
||||
fs_r -= FSRT__UNIT;
|
||||
}
|
||||
|
||||
while ( fs_l < fs_r && FSRT__LT( fs_l, fs_p, FSRT__SIZE, 2 ) ) {
|
||||
fs_l += FSRT__UNIT;
|
||||
}
|
||||
|
||||
if ( fs_r <= fs_l ) { break; }
|
||||
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
|
||||
fs_r -= FSRT__UNIT;
|
||||
fs_l += FSRT__UNIT;
|
||||
}
|
||||
|
||||
fs_l = fs_r + FSRT__UNIT;
|
||||
|
||||
if ( fs_b < fs_r ) { FSRT__SWAP( fs_b, fs_r, FSRT__SIZE, 4 ); }
|
||||
fs_l -= FSRT__UNIT;
|
||||
fs_r += FSRT__UNIT;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FSRT_DEBUG
|
||||
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
|
||||
if ( fs_p < fs_l ) {
|
||||
if ( FSRT__LT( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x not less equal after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( fs_p < fs_r ) {
|
||||
if ( ! FSRT__EQ( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x not equal after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( FSRT__LT( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x not greater equal after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
// 3-way partitioning into elements lt, eq, and gt
|
||||
// This is a bit slower than 2-way partitioning but a lot faster
|
||||
// if the range contains only elements with few different keys.
|
||||
// In the first step this does a split-end partitioning,
|
||||
// i.e. the elements equal to the pivot end up at the very left
|
||||
// (left of m) or at the very right (right of q) end of the range.
|
||||
// In the second step (down below) they are swapped to the middle.
|
||||
// This has the advantage, that it executes fewer swaps
|
||||
// (which is quite counter to the intuition).
|
||||
// It executes about 1/4 N swaps for the not-equal elements and
|
||||
// 2 E swaps for the equal elements (and even fewer if E > N).
|
||||
// The alternative (that keeps the equal elements during the
|
||||
// partitioning in the middle) executes about 3/4 N swaps for the
|
||||
// not-equal elements and 1 E swaps for the equal elements.
|
||||
|
||||
fs_p = fs_b;
|
||||
fs_l = fs_b+FSRT__UNIT;
|
||||
fs_m = fs_b+FSRT__UNIT;
|
||||
fs_r = fs_e-FSRT__UNIT;
|
||||
fs_q = fs_e-FSRT__UNIT;
|
||||
|
||||
while ( 1 ) {
|
||||
while ( fs_l <= fs_r && FSRT__LEC( fs_p, fs_r, FSRT__SIZE, 2 ) ) {
|
||||
if ( FSRT__EQC( fs_p, fs_r, FSRT__SIZE, 0 ) ) {
|
||||
if ( fs_r < fs_q ) { FSRT__SWAP( fs_r, fs_q, FSRT__SIZE, 4 ); }
|
||||
fs_q -= FSRT__UNIT;
|
||||
}
|
||||
fs_r -= FSRT__UNIT;
|
||||
}
|
||||
|
||||
while ( fs_l < fs_r && FSRT__LEC( fs_l, fs_p, FSRT__SIZE, 2 ) ) {
|
||||
if ( FSRT__EQC( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
|
||||
if ( fs_m < fs_l ) { FSRT__SWAP( fs_m, fs_l, FSRT__SIZE, 4 ); }
|
||||
fs_m += FSRT__UNIT;
|
||||
}
|
||||
fs_l += FSRT__UNIT;
|
||||
}
|
||||
|
||||
if ( fs_r <= fs_l ) { break; }
|
||||
|
||||
FSRT__SWAP( fs_l, fs_r, FSRT__SIZE, 4 );
|
||||
fs_r -= FSRT__UNIT;
|
||||
fs_l += FSRT__UNIT;
|
||||
}
|
||||
|
||||
fs_l = fs_r + FSRT__UNIT;
|
||||
|
||||
#ifdef FSRT_DEBUG
|
||||
// printf("%08x %08x %08x %08x %08x %08x\n",fs_b,fs_m,fs_l,fs_r,fs_q,fs_e);
|
||||
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
|
||||
if ( fs_p < fs_m ) {
|
||||
if ( ! FSRT__EQ( fs_p, fs_b, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x < fs_m not equal after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( fs_p < fs_l ) {
|
||||
if ( ! FSRT__LT( fs_p, fs_b, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x < fs_l not less after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( fs_q < fs_p ) {
|
||||
if ( ! FSRT__EQ( fs_b, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_q < fs_p %08x not equal after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( fs_r < fs_p ) {
|
||||
if ( ! FSRT__LT( fs_b, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_r < fs_p %08x not greater after partitioning\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Swap the equal elements (including the pivot) to the middle.
|
||||
// I found it not so easy to get this code correct, so beware ;-)
|
||||
fs_p = fs_b;
|
||||
|
||||
while ( fs_p < fs_m && fs_m < fs_l ) {
|
||||
fs_l -= FSRT__UNIT;
|
||||
FSRT__SWAP( fs_p, fs_l, FSRT__SIZE, 4 );
|
||||
fs_p += FSRT__UNIT;
|
||||
}
|
||||
|
||||
if ( fs_l == fs_m ) {
|
||||
fs_l = fs_p;
|
||||
}
|
||||
|
||||
fs_p = fs_e-FSRT__UNIT;
|
||||
|
||||
while ( fs_q < fs_p && fs_r < fs_q ) {
|
||||
fs_r += FSRT__UNIT;
|
||||
FSRT__SWAP( fs_r, fs_p, FSRT__SIZE, 4 );
|
||||
fs_p -= FSRT__UNIT;
|
||||
}
|
||||
|
||||
if ( fs_r == fs_q ) {
|
||||
fs_r = fs_p;
|
||||
}
|
||||
|
||||
fs_r = fs_r + FSRT__UNIT;
|
||||
|
||||
#ifdef FSRT_DEBUG
|
||||
|
||||
for ( fs_p = fs_b; fs_p < fs_e; fs_p++ ) {
|
||||
if ( fs_p < fs_l ) {
|
||||
if ( ! FSRT__LT( fs_p, fs_l, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x < fs_l not less after swapping\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ( fs_p < fs_r ) {
|
||||
if ( ! FSRT__EQ( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_p %08x < fs_r not equal after swapping\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( ! FSRT__LT( fs_l, fs_p, FSRT__SIZE, 0 ) ) {
|
||||
printf("fs_r <= fs_p %08x not greater after swapping\n",fs_p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Now sort the range before and the range after the pivot.
|
||||
// Sort the smaller range recursively and the larger iteratively.
|
||||
// This limits the maximal redursion depth to log2(N).
|
||||
// To avoid extra variables we modify the arguments of the func.
|
||||
|
||||
if ( fs_l-fs_b < fs_e-fs_r ) {
|
||||
FSRT__SORT( fs_b, fs_l, FSRT__SIZE, FSRT__TEMP );
|
||||
fs_b = fs_r;
|
||||
}
|
||||
else {
|
||||
FSRT__SORT( fs_r, fs_e, FSRT__SIZE, FSRT__TEMP );
|
||||
fs_e = fs_l;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally the remaining short subrange is sorted with insertion sort.
|
||||
// Sorting each individual short subrange instead of executing one
|
||||
// insertion sort over the entire range at the end is more efficient,
|
||||
// because we know that all the pivots (and all the elements equal to
|
||||
// them) are at the right location, so we need not compare them with
|
||||
// their predecessor and successor.
|
||||
// It may also be a bit more cache friendly.
|
||||
// I tried other algorithms (shell sort, special cases, etc.)
|
||||
// but in the end this algorithm always was the fastest
|
||||
// (probably because the subranges are so small).
|
||||
|
||||
for ( fs_l = fs_b+FSRT__UNIT; fs_l < fs_e; fs_l += FSRT__UNIT ) {
|
||||
if ( FSRT__LT( fs_l, fs_l-FSRT__UNIT, FSRT__SIZE, 3 ) ) {
|
||||
FSRT__COPY( FSRT__TEMP, fs_l, FSRT__SIZE, 5 );
|
||||
FSRT__COPY( fs_l, fs_l-FSRT__UNIT, FSRT__SIZE, 5 );
|
||||
for ( fs_r = fs_l-2*FSRT__UNIT;
|
||||
fs_b <= fs_r && FSRT__LT( FSRT__TEMP, fs_r, FSRT__SIZE, 3 );
|
||||
fs_r -= FSRT__UNIT ) {
|
||||
FSRT__COPY( fs_r+FSRT__UNIT, fs_r, FSRT__SIZE, 5 );
|
||||
}
|
||||
FSRT__COPY( fs_r+FSRT__UNIT, FSRT__TEMP, FSRT__SIZE, 5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef FSRT__TYPE
|
||||
#undef FSRT__UNIT
|
||||
#undef FSRT__SIZE
|
||||
#undef FSRT__DIST
|
||||
#undef FSRT__TEMP
|
||||
#undef FSRT__LT
|
||||
#undef FSRT__EQ
|
||||
#undef FSRT__LEC
|
||||
#undef FSRT__EQC
|
||||
#undef FSRT__COPY
|
||||
#undef FSRT__SWAP
|
||||
#undef FSRT__INSR
|
||||
#undef FSRT__THREE
|
||||
#undef FSRT__NINE
|
||||
#undef FSRT__EXTRA_ARGS
|
||||
#undef FSRT__EXTRA_DECL
|
||||
#undef FSRT__MED3
|
||||
// #undef FSRT__RAND
|
||||
#undef FSRT__SORT
|
||||
|
||||
#undef FSRT_NAME
|
||||
#undef FSRT_NAM2
|
||||
#undef FSRT_LT
|
||||
#undef FSRT_EQ
|
||||
#undef FSRT_COMP
|
||||
#undef FSRT_TYPE
|
||||
#undef FSRT_COPY
|
||||
#undef FSRT_UNIQ
|
||||
#undef FSRT_INSR
|
||||
#undef FSRT_THREE
|
||||
#undef FSRT_NINE
|
||||
#undef FSRT_EXTRA_ARGS
|
||||
#undef FSRT_EXTRA_DECL
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// fsrt.h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
|
||||
//
|
||||
// 0.90 2008-11-20 mschoene initial version
|
||||
//
|
||||
// 0.95 2009-03-24 mschoene file is now called fsrt.h
|
||||
// changed prefix to FSRT_
|
||||
// parameters and local variables begin with fs_
|
||||
// changed INSR default to 8
|
||||
// added description for split-end partitioning
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
|
||||
// End:
|
|
@ -57,5 +57,4 @@ avocdb_SOURCES = \
|
|||
VocBase/simple-collection.c \
|
||||
VocBase/vocbase.c \
|
||||
VocBase/voc-shaper.c \
|
||||
VocBase/write-slots.c \
|
||||
# end of file list
|
||||
|
|
1468
V8/v8-json.cpp
1468
V8/v8-json.cpp
File diff suppressed because it is too large
Load Diff
|
@ -195,7 +195,7 @@ static v8::Handle<v8::Value> ParseArray (yyscan_t scanner) {
|
|||
|
||||
v8::Handle<v8::Object> array = v8::Object::New();
|
||||
bool comma = false;
|
||||
char const* name;
|
||||
char* name;
|
||||
char const* ptr;
|
||||
size_t len;
|
||||
size_t outLength;
|
||||
|
@ -270,7 +270,7 @@ static v8::Handle<v8::Value> ParseObject (yyscan_t scanner, int c) {
|
|||
char buffer[1024];
|
||||
|
||||
char* ep;
|
||||
char const* ptr;
|
||||
char* ptr;
|
||||
double d;
|
||||
size_t outLength;
|
||||
|
||||
|
|
1744
V8/v8-shell.cpp
1744
V8/v8-shell.cpp
File diff suppressed because it is too large
Load Diff
|
@ -29,13 +29,19 @@
|
|||
#define TRIAGENS_DURHAM_V8_V8_SHELL_H 1
|
||||
|
||||
#define TRI_WITHIN_C
|
||||
#include <Basics/Common.h>
|
||||
#include <Basics/json.h>
|
||||
|
||||
#include <VocBase/simple-collection.h>
|
||||
#undef TRI_WITHIN_C
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- CONVERSION FUNCTIONS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -46,29 +52,79 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an object to a string
|
||||
/// @brief converts a TRI_json_t into a V8 object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> ObjectJson (TRI_json_t const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts a TRI_shaped_json_t into a V8 object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Value> ObjectShapedJson (TRI_doc_collection_t* collection,
|
||||
TRI_voc_did_t did,
|
||||
TRI_shaper_t* shaper,
|
||||
TRI_shaped_json_t const* shaped);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts a TRI_result_set_t into a V8 array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Handle<v8::Array> ArrayResultSet (TRI_result_set_t* rs);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a TRI_shaped_json_t
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_shaped_json_t* ShapedJsonV8Object (v8::Handle<v8::Value> object, TRI_shaper_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an V8 object to a string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string ObjectToString (v8::Handle<v8::Value> value);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an object to a character
|
||||
/// @brief converts an V8 object to a character
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
char ObjectToCharacter (v8::Handle<v8::Value> value, bool& error);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an object to a double
|
||||
/// @brief converts an V8 object to a double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double ObjectToDouble (v8::Handle<v8::Value> value);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief converts an object to a double
|
||||
/// @brief converts an V8 object to a double
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
double ObjectToDouble (v8::Handle<v8::Value> value, bool& error);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds attributes to array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void AugmentObject (v8::Handle<v8::Value> value, TRI_json_t const* json);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- GENERAL
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup V8Shell V8 Shell
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stores the V8 shell function inside the global variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
2920
V8/v8-vocbase.cpp
2920
V8/v8-vocbase.cpp
File diff suppressed because it is too large
Load Diff
123
V8/v8-vocbase.h
123
V8/v8-vocbase.h
|
@ -35,6 +35,129 @@
|
|||
|
||||
#include <v8.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page DurhamFluentInterface Fluent Interface
|
||||
///
|
||||
/// A fluent interface is implemented by using method chaining to relay the
|
||||
/// instruction context of a subsequent call. The AvocadoDB provides the
|
||||
/// following methods:
|
||||
///
|
||||
/// - selection by example
|
||||
/// - field selection (aka projection)
|
||||
/// - @ref GeoFI "geo coordinates"
|
||||
/// - sorting
|
||||
/// - cursors
|
||||
/// - pagination of the result-set
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section FirstStepsFI First Steps
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// For instance, in order to select all elements of a collection "examples",
|
||||
/// one can use the "all()" operator.
|
||||
///
|
||||
/// @verbinclude fluent1
|
||||
///
|
||||
/// This will select all documents and prints the first 20 documents. If there
|
||||
/// are more than 20 documents, then "...more results..." is printed and you
|
||||
/// can use the variable "it" to access the next 20 document.
|
||||
///
|
||||
/// @verbinclude fluent2
|
||||
///
|
||||
/// In the above examples "db.examples.all()" defines a query. Printing
|
||||
/// that query, executes the query and returns a cursor to the result set.
|
||||
/// The first 20 documents are printed and the query (resp. cursor) is
|
||||
/// assigned to the variable "it".
|
||||
///
|
||||
/// A cursor can also be queried using "hasNext()" and "next()". Calling
|
||||
/// either of these functions also executes the query, turning it into
|
||||
/// a cursor.
|
||||
///
|
||||
/// @verbinclude fluent3
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section GeoFI Geo Coordinates
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// The AvocadoDB allows to selects documents based on geographic
|
||||
/// coordinates. In order for this to work a geo-spatial index must be defined.
|
||||
/// This index will use a very elaborate algorithm to lookup neighbours that is
|
||||
/// a magnitude faster than a simple R* index.
|
||||
///
|
||||
/// In general a geo coordinate is a pair of latitude and longitude. This can
|
||||
/// either be an list with two elements like "[ -10, +30 ]" (latitude first,
|
||||
/// followed by longitude) or an object like "{ lon: -10, lat: +30 }". In order
|
||||
/// to find all documents within a given radius around a coordinate use the @ref
|
||||
/// WithinFI "within()" operator. In order to find all documents near a given
|
||||
/// document use the @ref NearFI "near()" operator.
|
||||
///
|
||||
/// It is possible to define more than one geo-spatial index per collection. In
|
||||
/// this case you must give a hint which of indexes should be used in a query.
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @subsection EnsureGeoIndexFI Create a Geo-Spatial Index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// @copydetails JS_EnsureGeoIndexVocbaseCol
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @subsection NearFI The Near Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// @copydetails JS_NearVocbaseCol
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @subsection WithinFI The Within Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section LimitFI The Limit Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// If, for example, you display the result of a user search, then you are in
|
||||
/// general not interested in the completed result set, but only the first 10
|
||||
/// documents. In this case, you can the "limit()" operator. This operators
|
||||
/// works like LIMIT in MySQL, it specifies a maximal number of documents to
|
||||
/// return.
|
||||
///
|
||||
/// @verbinclude fluent4
|
||||
///
|
||||
/// Specifying a limit of "0" returns no documents at all. If you do not need
|
||||
/// a limit, just do not add the limit operator. If you specifiy a negtive
|
||||
/// limit of -n, this will return the last n documents instead.
|
||||
///
|
||||
/// @verbinclude fluent8
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section SkipFI The Skip Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// "skip" used together with "limit" can be used to implement pagination.
|
||||
/// The "skip" operator skips over the first n documents. So, in order to
|
||||
/// create result pages with 10 result documents per page, you can use
|
||||
/// "skip(n * 10).limit(10)" to access the n.th page.
|
||||
///
|
||||
/// @verbinclude fluent5
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section CountFI The Count Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// If you are implementation pagination, then you need the total amount of
|
||||
/// documents a query returned. "count()" just does this. It returns the
|
||||
/// total amount of documents regardless of any "limit()" and "skip()"
|
||||
/// operator used before the "count()". If you really want these to be taken
|
||||
/// into account, use "count(true)".
|
||||
///
|
||||
/// @verbinclude fluent6
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @section ExplainFI The Explain Operator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// @copydetails JS_ExplainQuery
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
182
VocBase/index.c
182
VocBase/index.c
|
@ -249,7 +249,84 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
|||
shaper = geo->base._collection->_shaper;
|
||||
|
||||
// lookup latitude and longitude
|
||||
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
|
||||
if (geo->_location != 0) {
|
||||
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
|
||||
}
|
||||
else {
|
||||
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
|
||||
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// and insert into index
|
||||
gc.latitude = latitude;
|
||||
gc.longitude = longitude;
|
||||
gc.data = doc;
|
||||
|
||||
res = GeoIndex_insert(geo->_geoIndex, &gc);
|
||||
|
||||
if (res == -1) {
|
||||
LOG_WARNING("found duplicate entry in geo-index, should not happend");
|
||||
}
|
||||
else if (res == -2) {
|
||||
LOG_WARNING("out-of-memory in geo-index");
|
||||
}
|
||||
else if (res == -3) {
|
||||
LOG_DEBUG("illegal geo-coordinates, ignoring entry");
|
||||
}
|
||||
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates a document, location is a list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
|
||||
GeoCoordinate gc;
|
||||
TRI_shaper_t* shaper;
|
||||
bool ok;
|
||||
double latitude;
|
||||
double longitude;
|
||||
TRI_geo_index_t* geo;
|
||||
int res;
|
||||
|
||||
geo = (TRI_geo_index_t*) idx;
|
||||
shaper = geo->base._collection->_shaper;
|
||||
|
||||
// lookup OLD latitude and longitude
|
||||
if (geo->_location != 0) {
|
||||
ok = ExtractDoubleList(shaper, old, geo->_location, &latitude, &longitude);
|
||||
}
|
||||
else {
|
||||
ok = ExtractDoubleArray(shaper, old, geo->_latitude, &latitude);
|
||||
ok = ok && ExtractDoubleArray(shaper, old, geo->_longitude, &longitude);
|
||||
}
|
||||
|
||||
// and remove old entry
|
||||
if (ok) {
|
||||
gc.latitude = latitude;
|
||||
gc.longitude = longitude;
|
||||
gc.data = doc;
|
||||
|
||||
res = GeoIndex_remove(geo->_geoIndex, &gc);
|
||||
|
||||
if (res != 0) {
|
||||
LOG_WARNING("cannot remove old index entry: %d", res);
|
||||
}
|
||||
}
|
||||
|
||||
// create new entry with new coordinates
|
||||
if (geo->_location != 0) {
|
||||
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
|
||||
}
|
||||
else {
|
||||
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
|
||||
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
|
@ -274,19 +351,46 @@ static bool InsertGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
|||
return res == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates a document, location is a list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool UpdateGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief erases a document, location is a list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EraseGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
static bool RemoveGeoIndex (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
GeoCoordinate gc;
|
||||
TRI_shaper_t* shaper;
|
||||
bool ok;
|
||||
double latitude;
|
||||
double longitude;
|
||||
TRI_geo_index_t* geo;
|
||||
int res;
|
||||
|
||||
geo = (TRI_geo_index_t*) idx;
|
||||
shaper = geo->base._collection->_shaper;
|
||||
|
||||
// lookup OLD latitude and longitude
|
||||
if (geo->_location != 0) {
|
||||
ok = ExtractDoubleList(shaper, &doc->_document, geo->_location, &latitude, &longitude);
|
||||
}
|
||||
else {
|
||||
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
|
||||
ok = ok && ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
|
||||
}
|
||||
|
||||
// and remove old entry
|
||||
if (ok) {
|
||||
gc.latitude = latitude;
|
||||
gc.longitude = longitude;
|
||||
gc.data = doc;
|
||||
|
||||
res = GeoIndex_remove(geo->_geoIndex, &gc);
|
||||
|
||||
if (res != 0) {
|
||||
LOG_WARNING("cannot remove old index entry: %d", res);
|
||||
}
|
||||
|
||||
return res == 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -318,55 +422,6 @@ static TRI_json_t* JsonGeoIndex (TRI_index_t* idx, TRI_doc_collection_t* collect
|
|||
return json;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief inserts a new document, location is an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool InsertGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
TRI_shaper_t* shaper;
|
||||
bool ok;
|
||||
double latitude;
|
||||
double longitude;
|
||||
TRI_geo_index_t* geo;
|
||||
|
||||
geo = (TRI_geo_index_t*) idx;
|
||||
shaper = geo->base._collection->_shaper;
|
||||
|
||||
// lookup latitude
|
||||
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_latitude, &latitude);
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// lookup longitude
|
||||
ok = ExtractDoubleArray(shaper, &doc->_document, geo->_longitude, &longitude);
|
||||
|
||||
if (! ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("%f %f\n", latitude, longitude);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief updates a document, location is an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool UpdateGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc, TRI_shaped_json_t const* old) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief erases a document, location is an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool EraseGeoIndex2 (TRI_index_t* idx, TRI_doc_mptr_t const* doc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief saves the index to file, location is an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -489,7 +544,7 @@ TRI_index_t* TRI_CreateGeoIndex (struct TRI_doc_collection_s* collection,
|
|||
geo->base._collection = collection;
|
||||
|
||||
geo->base.insert = InsertGeoIndex;
|
||||
geo->base.erase = EraseGeoIndex;
|
||||
geo->base.remove = RemoveGeoIndex;
|
||||
geo->base.update = UpdateGeoIndex;
|
||||
geo->base.json = JsonGeoIndex;
|
||||
|
||||
|
@ -513,12 +568,13 @@ TRI_index_t* TRI_CreateGeoIndex2 (struct TRI_doc_collection_s* collection,
|
|||
|
||||
geo = TRI_Allocate(sizeof(TRI_geo_index_t));
|
||||
|
||||
geo->base._iid = TRI_NewTickVocBase();
|
||||
geo->base._type = TRI_IDX_TYPE_GEO_INDEX;
|
||||
geo->base._collection = collection;
|
||||
|
||||
geo->base.insert = InsertGeoIndex2;
|
||||
geo->base.erase = EraseGeoIndex2;
|
||||
geo->base.update = UpdateGeoIndex2;
|
||||
geo->base.insert = InsertGeoIndex;
|
||||
geo->base.remove = RemoveGeoIndex;
|
||||
geo->base.update = UpdateGeoIndex;
|
||||
geo->base.json = JsonGeoIndex2;
|
||||
|
||||
geo->_geoIndex = GeoIndex_new();
|
||||
|
|
|
@ -81,7 +81,7 @@ typedef struct TRI_index_s {
|
|||
struct TRI_doc_collection_s* _collection;
|
||||
|
||||
bool (*insert) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
bool (*erase) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
bool (*remove) (struct TRI_index_s*, struct TRI_doc_mptr_s const*);
|
||||
bool (*update) (struct TRI_index_s*, struct TRI_doc_mptr_s const*, struct TRI_shaped_json_s const*);
|
||||
TRI_json_t* (*json) (struct TRI_index_s*, struct TRI_doc_collection_s*);
|
||||
}
|
||||
|
|
1399
VocBase/query.c
1399
VocBase/query.c
File diff suppressed because it is too large
Load Diff
184
VocBase/query.h
184
VocBase/query.h
|
@ -36,117 +36,6 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @page DurhamFluentInterface Fluent Interface
|
||||
///
|
||||
/// A fluent interface is implemented by using method chaining to relay the
|
||||
/// instruction context of a subsequent call.
|
||||
///
|
||||
/// The Durham Storage Engine provides the following methods:
|
||||
///
|
||||
/// - selection by example
|
||||
/// - field selection aka projection
|
||||
/// - @ref GeoFI "geo coordinates"
|
||||
/// - sorting
|
||||
/// - pagination of the result using @ref LimitFI "limit", @ref SkipFI "skip",
|
||||
/// and @ref CountFI "count".
|
||||
///
|
||||
/// @section FirstStepsFI First Steps
|
||||
///
|
||||
/// For instance, in order to select all elements of a collection "examples",
|
||||
/// one can use
|
||||
///
|
||||
/// @verbinclude fluent1
|
||||
///
|
||||
/// This will select all documents and prints the first 20 documents. If there
|
||||
/// are more than 20 documents, then "...more results..." is printed and you
|
||||
/// can use the variable "it" to access the next 20 document.
|
||||
///
|
||||
/// @verbinclude fluent2
|
||||
///
|
||||
/// In the above examples "db.examples.select()" defines a query. Printing
|
||||
/// that query, executes the query and returns a cursor to the result set.
|
||||
/// The first 20 documents are printed and the query (resp. cursor) is
|
||||
/// assigned to the variable "it".
|
||||
///
|
||||
/// A cursor can also be query using "hasNext()" and "next()".
|
||||
///
|
||||
/// @verbinclude fluent3
|
||||
///
|
||||
/// @section GeoFI Geo Coordinates
|
||||
///
|
||||
/// The Storage Engine allows to selects documents based on geographic
|
||||
/// coordinates. In order for this to work a geo index must be defined. This
|
||||
/// index will a very elaborate index to lookup neighbours that is magnitudes
|
||||
/// faster than a simple R* index.
|
||||
///
|
||||
/// In generale a geo coordinate is a pair of longitude and latitude. This can
|
||||
/// either be an list with two elements like "[ -10, +30 ]" or an object like "{
|
||||
/// lon: -10, lat: +30 }". In order to find all documents within a given radius
|
||||
/// around a coordinate use the @ref WithinFI "within()" operator. In order to
|
||||
/// find all documents near a given document use the @ref NearFI "near()"
|
||||
/// operator.
|
||||
///
|
||||
/// @section WithinFI The Within Operator
|
||||
///
|
||||
/// @section NearFI The Near Operator
|
||||
///
|
||||
/// Assume that the geo coordinate is stored as list of size 2. The first
|
||||
/// value being the latitude and the second value being the longitude.
|
||||
///
|
||||
/// @section LimitFI The Limit Operator
|
||||
///
|
||||
/// If, for example, you display the result of a user search, then you are in
|
||||
/// general not interested in the completed result set, but only the first 10
|
||||
/// documents. In this case, you can the "limit()" operator. This operators
|
||||
/// works like LIMIT in MySQL, it specifies a maximal number of documents to
|
||||
/// return.
|
||||
///
|
||||
/// @verbinclude fluent4
|
||||
///
|
||||
/// Specifying a limit of "0" returns no documents at all. If you do not need
|
||||
/// a limit, just do not add the limit operator. If you specifiy a negtive
|
||||
/// limit of -n, this will return the last n documents instead.
|
||||
///
|
||||
/// @verbinclude fluent8
|
||||
///
|
||||
/// @section SkipFI The Skip Operator
|
||||
///
|
||||
/// "skip" used together with "limit" can be used to implement pagination.
|
||||
/// The "skip" operator skips over the first n documents. So, in order to
|
||||
/// create result pages with 10 result documents per page, you can use
|
||||
/// "skip(n * 10).limit(10)" to access the n.th page.
|
||||
///
|
||||
/// @verbinclude fluent5
|
||||
///
|
||||
/// @section CountFI The Count Operator
|
||||
///
|
||||
/// If you are implementation pagination, then you need the total amount of
|
||||
/// documents a query returned. "count()" just does this. It returns the
|
||||
/// total amount of documents regardless of any "limit()" and "skip()"
|
||||
/// operator used before the "count()". If you really want these to be taken
|
||||
/// into account, use "count(true)".
|
||||
///
|
||||
/// @verbinclude fluent6
|
||||
///
|
||||
/// @section ExplainFI The Explain Operator
|
||||
///
|
||||
/// In order to optimise queries you need to know how the storage engine
|
||||
/// executed that type of query. You can use the "explain()" operator to
|
||||
/// see how a query was executed.
|
||||
///
|
||||
/// @verbinclude fluent9
|
||||
///
|
||||
/// The "explain()" operator returns an object with the following attributes.
|
||||
///
|
||||
/// - cursor: describes how the result set was computed.
|
||||
/// - scannedIndexEntries: how many index entries were scanned
|
||||
/// - scannedDocuments: how many documents were scanned
|
||||
/// - matchedDocuments: the sum of all matched documents in each step
|
||||
/// - runtime: the runtime in seconds
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- forward declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -176,13 +65,39 @@ typedef enum {
|
|||
}
|
||||
TRI_que_type_e;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_query_result_s {
|
||||
char* _cursor;
|
||||
char* _error;
|
||||
|
||||
TRI_voc_size_t _length;
|
||||
TRI_voc_size_t _total;
|
||||
|
||||
TRI_voc_size_t _scannedIndexEntries;
|
||||
TRI_voc_size_t _scannedDocuments;
|
||||
TRI_voc_size_t _matchedDocuments;
|
||||
|
||||
struct TRI_doc_mptr_s const** _documents;
|
||||
struct TRI_json_s* _augmented;
|
||||
}
|
||||
TRI_query_result_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_query_s {
|
||||
TRI_que_type_e _type;
|
||||
struct TRI_doc_collection_s* _collection;
|
||||
TRI_vocbase_col_t const* _collection;
|
||||
|
||||
char* _string;
|
||||
|
||||
void (*execute) (struct TRI_query_s*, TRI_query_result_t*);
|
||||
struct TRI_query_s* (*clone) (struct TRI_query_s*);
|
||||
void (*free) (struct TRI_query_s*);
|
||||
}
|
||||
TRI_query_t;
|
||||
|
||||
|
@ -226,9 +141,14 @@ TRI_limit_query_t;
|
|||
typedef struct TRI_near_query_s {
|
||||
TRI_query_t base;
|
||||
|
||||
struct TRI_index_s* _index;
|
||||
TRI_query_t* _operand;
|
||||
|
||||
char* _location;
|
||||
char* _distance;
|
||||
|
||||
double _latitude;
|
||||
double _longitude;
|
||||
|
||||
TRI_voc_size_t _count;
|
||||
}
|
||||
TRI_near_query_t;
|
||||
|
@ -250,7 +170,7 @@ TRI_skip_query_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -262,7 +182,13 @@ TRI_skip_query_t;
|
|||
/// @brief creates a full scan of a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_t* TRI_CreateCollectionQuery (struct TRI_doc_collection_s*);
|
||||
TRI_query_t* TRI_CreateCollectionQuery (TRI_vocbase_col_t const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds the distance to a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_t* TRI_CreateDistanceQuery (TRI_query_t*, char const* name);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up a document
|
||||
|
@ -281,23 +207,10 @@ TRI_query_t* TRI_CreateLimitQuery (TRI_query_t*, TRI_voc_ssize_t);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_t* TRI_CreateNearQuery (TRI_query_t*,
|
||||
char const* location,
|
||||
double latitude,
|
||||
double longitude,
|
||||
TRI_voc_size_t count,
|
||||
char const** error);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief looks up documents near a given point
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_t* TRI_CreateNear2Query (TRI_query_t*,
|
||||
char const* locLatitude,
|
||||
double latitude,
|
||||
char const* locLongitude,
|
||||
double longitude,
|
||||
TRI_voc_size_t count,
|
||||
char const** error);
|
||||
char const* distance);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief skips elements of an existing query
|
||||
|
@ -305,6 +218,19 @@ TRI_query_t* TRI_CreateNear2Query (TRI_query_t*,
|
|||
|
||||
TRI_query_t* TRI_CreateSkipQuery (TRI_query_t*, TRI_voc_size_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -66,6 +66,7 @@ typedef struct doc_rs_vector_s {
|
|||
|
||||
TRI_shaped_json_t* _elements;
|
||||
TRI_voc_did_t* _dids;
|
||||
TRI_json_t* _augmented;
|
||||
|
||||
TRI_voc_size_t _length;
|
||||
TRI_voc_size_t _current;
|
||||
|
@ -100,9 +101,15 @@ static bool HasNextRSSingle (TRI_result_set_t* rs) {
|
|||
/// @brief returns the current element of a single result set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_shaped_json_t* NextRSSingle (TRI_result_set_t* rs, TRI_voc_did_t* did) {
|
||||
static TRI_shaped_json_t* NextRSSingle (TRI_result_set_t* rs,
|
||||
TRI_voc_did_t* did,
|
||||
TRI_json_t const** augmented) {
|
||||
doc_rs_single_t* rss = (doc_rs_single_t*) rs;
|
||||
|
||||
if (augmented != NULL) {
|
||||
*augmented = NULL;
|
||||
}
|
||||
|
||||
if (rss->_empty) {
|
||||
*did = 0;
|
||||
|
||||
|
@ -167,12 +174,23 @@ static bool HasNextRSVector (TRI_result_set_t* rs) {
|
|||
/// @brief returns the current element of a vector result set
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_shaped_json_t* NextRSVector (TRI_result_set_t* rs, TRI_voc_did_t* did) {
|
||||
static TRI_shaped_json_t* NextRSVector (TRI_result_set_t* rs,
|
||||
TRI_voc_did_t* did,
|
||||
TRI_json_t const** augmented) {
|
||||
doc_rs_vector_t* rss = (doc_rs_vector_t*) rs;
|
||||
|
||||
if (rss->_current < rss->_length) {
|
||||
*did = rss->_dids[rss->_current];
|
||||
|
||||
if (augmented != NULL) {
|
||||
if (rss->_augmented == NULL) {
|
||||
*augmented = NULL;
|
||||
}
|
||||
else {
|
||||
*augmented = &rss->_augmented[rss->_current];
|
||||
}
|
||||
}
|
||||
|
||||
return &rss->_elements[rss->_current++];
|
||||
}
|
||||
else {
|
||||
|
@ -206,13 +224,17 @@ static void FreeRSVector (TRI_result_set_t* rs) {
|
|||
|
||||
void* f;
|
||||
|
||||
f = TRI_RemoveKeyAssociativeSynced(&rs->_container->_resultSets, &rs->_id);
|
||||
assert(f != NULL);
|
||||
|
||||
if (rss->_elements != NULL) {
|
||||
TRI_Free(rss->_dids);
|
||||
TRI_Free(rss->_elements);
|
||||
}
|
||||
|
||||
f = TRI_RemoveKeyAssociativeSynced(&rs->_container->_resultSets, &rs->_id);
|
||||
assert(f != NULL);
|
||||
if (rss->_augmented != NULL) {
|
||||
TRI_Free(rss->_augmented);
|
||||
}
|
||||
|
||||
TRI_Free(rs->_info._cursor);
|
||||
TRI_Free(rs);
|
||||
|
@ -308,6 +330,8 @@ TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection,
|
|||
|
||||
rs = TRI_Allocate(sizeof(doc_rs_single_t));
|
||||
|
||||
rs->base._error = NULL;
|
||||
|
||||
rs->base.hasNext = HasNextRSSingle;
|
||||
rs->base.next = NextRSSingle;
|
||||
rs->base.count = CountRSSingle;
|
||||
|
@ -338,6 +362,7 @@ TRI_result_set_t* TRI_CreateRSSingle (TRI_doc_collection_t* collection,
|
|||
|
||||
TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
|
||||
TRI_doc_mptr_t const** header,
|
||||
TRI_json_t const* augmented,
|
||||
TRI_voc_size_t length,
|
||||
TRI_voc_size_t total) {
|
||||
doc_rs_vector_t* rs;
|
||||
|
@ -348,6 +373,8 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
|
|||
|
||||
rs = TRI_Allocate(sizeof(doc_rs_vector_t));
|
||||
|
||||
rs->base._error = NULL;
|
||||
|
||||
rs->base.hasNext = HasNextRSVector;
|
||||
rs->base.next = NextRSVector;
|
||||
rs->base.count = CountRSVector;
|
||||
|
@ -361,6 +388,7 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
|
|||
rs->_current = 0;
|
||||
rs->_dids = NULL;
|
||||
rs->_elements = NULL;
|
||||
rs->_augmented = NULL;
|
||||
}
|
||||
else {
|
||||
rs->_length = length;
|
||||
|
@ -377,6 +405,14 @@ TRI_result_set_t* TRI_CreateRSVector (TRI_doc_collection_t* collection,
|
|||
*wtr = (*qtr)->_did;
|
||||
*ptr = (*qtr)->_document;
|
||||
}
|
||||
|
||||
if (augmented == NULL) {
|
||||
rs->_augmented = NULL;
|
||||
}
|
||||
else {
|
||||
rs->_augmented = TRI_Allocate(length * sizeof(TRI_json_t));
|
||||
memcpy(rs->_augmented, augmented, length * sizeof(TRI_json_t));
|
||||
}
|
||||
}
|
||||
|
||||
rs->_total = total;
|
||||
|
|
|
@ -39,8 +39,9 @@ extern "C" {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct TRI_doc_collection_s;
|
||||
struct TRI_shaped_json_s;
|
||||
struct TRI_doc_mptr_s;
|
||||
struct TRI_json_s;
|
||||
struct TRI_shaped_json_s;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
|
@ -92,8 +93,10 @@ typedef struct TRI_result_set_s {
|
|||
TRI_rs_container_t* _container;
|
||||
TRI_rs_info_t _info;
|
||||
|
||||
char* _error;
|
||||
|
||||
bool (*hasNext) (struct TRI_result_set_s*);
|
||||
struct TRI_shaped_json_s* (*next) (struct TRI_result_set_s*, TRI_voc_did_t*);
|
||||
struct TRI_shaped_json_s* (*next) (struct TRI_result_set_s*, TRI_voc_did_t*, struct TRI_json_s const**);
|
||||
TRI_voc_size_t (*count) (struct TRI_result_set_s*, bool current);
|
||||
|
||||
void (*free) (struct TRI_result_set_s*);
|
||||
|
@ -139,6 +142,7 @@ TRI_result_set_t* TRI_CreateRSSingle (struct TRI_doc_collection_s* collection,
|
|||
|
||||
TRI_result_set_t* TRI_CreateRSVector (struct TRI_doc_collection_s* collection,
|
||||
struct TRI_doc_mptr_s const** header,
|
||||
struct TRI_json_s const* augmented,
|
||||
TRI_voc_size_t length,
|
||||
TRI_voc_size_t total);
|
||||
|
||||
|
|
|
@ -55,7 +55,8 @@ static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
|
|||
static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
char const* location,
|
||||
char const* latitude,
|
||||
char const* longitude);
|
||||
char const* longitude,
|
||||
TRI_idx_iid iid);
|
||||
|
||||
static uint64_t HashKeyHeader (TRI_associative_pointer_t* array, void const* key);
|
||||
|
||||
|
@ -351,8 +352,8 @@ static bool UpdateDocument (TRI_sim_collection_t* collection,
|
|||
update._rid = marker->_rid;
|
||||
update._data = *result;
|
||||
update._document._sid = ((TRI_doc_document_marker_t*) marker)->_shape;
|
||||
update._document._data.length = ((TRI_df_marker_t const*) (header->_data))->_size - sizeof(TRI_doc_document_marker_t);
|
||||
update._document._data.data = ((char*) header->_data) + sizeof(TRI_doc_document_marker_t);
|
||||
update._document._data.length = ((TRI_df_marker_t const*) (update._data))->_size - sizeof(TRI_doc_document_marker_t);
|
||||
update._document._data.data = ((char*) update._data) + sizeof(TRI_doc_document_marker_t);
|
||||
|
||||
UpdateImmediateIndexes(collection, header, &update);
|
||||
}
|
||||
|
@ -650,7 +651,9 @@ static void OpenIterator (TRI_df_marker_t const* marker, void* data, bool journa
|
|||
}
|
||||
}
|
||||
else if (marker->_type == TRI_DOC_MARKER_DELETION) {
|
||||
TRI_doc_deletion_marker_t const* d = (TRI_doc_deletion_marker_t const*) marker;
|
||||
TRI_doc_deletion_marker_t const* d;
|
||||
|
||||
d = (TRI_doc_deletion_marker_t const*) marker;
|
||||
|
||||
LOG_TRACE("deletion did %lu, rid %lu, deletion %lu",
|
||||
(unsigned long) d->_did,
|
||||
|
@ -692,11 +695,13 @@ static void OpenIterator (TRI_df_marker_t const* marker, void* data, bool journa
|
|||
|
||||
static void OpenIndex (char const* filename, void* data) {
|
||||
TRI_sim_collection_t* doc;
|
||||
TRI_idx_iid iid;
|
||||
TRI_json_t* json;
|
||||
TRI_json_t* loc;
|
||||
TRI_json_t* lat;
|
||||
TRI_json_t* lon;
|
||||
TRI_json_t* type;
|
||||
TRI_json_t* iis;
|
||||
char const* typeStr;
|
||||
char* error;
|
||||
|
||||
|
@ -729,12 +734,18 @@ static void OpenIndex (char const* filename, void* data) {
|
|||
loc = TRI_LookupArrayJson(json, "location");
|
||||
lat = TRI_LookupArrayJson(json, "latitude");
|
||||
lon = TRI_LookupArrayJson(json, "longitude");
|
||||
iis = TRI_LookupArrayJson(json, "iid");
|
||||
iid = 0;
|
||||
|
||||
if (iis != NULL && loc->_type == TRI_JSON_NUMBER) {
|
||||
iid = loc->_value._number;
|
||||
}
|
||||
|
||||
if (loc != NULL && loc->_type == TRI_JSON_STRING) {
|
||||
CreateGeoIndexSimCollection(doc, loc->_value._string.data, NULL, NULL);
|
||||
CreateGeoIndexSimCollection(doc, loc->_value._string.data, NULL, NULL, iid);
|
||||
}
|
||||
else if (lat != NULL && lat->_type == TRI_JSON_STRING && lon != NULL && lon ->_type == TRI_JSON_STRING) {
|
||||
CreateGeoIndexSimCollection(doc, NULL, lat->_value._string.data, lon->_value._string.data);
|
||||
CreateGeoIndexSimCollection(doc, NULL, lat->_value._string.data, lon->_value._string.data, iid);
|
||||
}
|
||||
else {
|
||||
LOG_WARNING("ignore geo-index, need either 'location' or 'latitude' and 'longitude'");
|
||||
|
@ -770,6 +781,7 @@ static void InitSimCollection (TRI_sim_collection_t* collection,
|
|||
TRI_InitCondition(&collection->_journalsCondition);
|
||||
|
||||
TRI_InitVectorPointer(&collection->_indexes);
|
||||
collection->_geoIndex = NULL;
|
||||
|
||||
collection->base.beginRead = BeginRead;
|
||||
collection->base.endRead = EndRead;
|
||||
|
@ -1058,7 +1070,43 @@ static bool CreateImmediateIndexes (TRI_sim_collection_t* collection,
|
|||
static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
|
||||
TRI_doc_mptr_t const* header,
|
||||
TRI_doc_mptr_t const* update) {
|
||||
#warning TODO
|
||||
|
||||
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
|
||||
TRI_shaped_json_t old;
|
||||
bool ok;
|
||||
bool result;
|
||||
size_t i;
|
||||
size_t n;
|
||||
|
||||
// get the old document
|
||||
old = header->_document;
|
||||
|
||||
// update all fields, the document identifier stays the same
|
||||
change.c = header;
|
||||
|
||||
change.v->_rid = update->_rid;
|
||||
change.v->_eid = update->_eid;
|
||||
change.v->_deletion = update->_deletion;
|
||||
|
||||
change.v->_data = update->_data;
|
||||
change.v->_document = update->_document;
|
||||
|
||||
// update all other indexes
|
||||
n = TRI_SizeVectorPointer(&collection->_indexes);
|
||||
result = true;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx;
|
||||
|
||||
idx = TRI_AtVectorPointer(&collection->_indexes, i);
|
||||
|
||||
ok = idx->update(idx, header, &old);
|
||||
|
||||
if (! ok) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1069,7 +1117,45 @@ static bool UpdateImmediateIndexes (TRI_sim_collection_t* collection,
|
|||
static bool DeleteImmediateIndexes (TRI_sim_collection_t* collection,
|
||||
TRI_doc_mptr_t const* header,
|
||||
TRI_voc_tick_t deletion) {
|
||||
#warning TODO
|
||||
union { TRI_doc_mptr_t const* c; TRI_doc_mptr_t* v; } change;
|
||||
TRI_doc_mptr_t* found;
|
||||
size_t n;
|
||||
size_t i;
|
||||
bool result;
|
||||
bool ok;
|
||||
|
||||
// set the deletion flag
|
||||
change.c = header;
|
||||
change.v->_deletion = deletion;
|
||||
|
||||
// remove from main index
|
||||
found = TRI_RemoveKeyAssociativePointer(&collection->_primaryIndex, &header->_did);
|
||||
|
||||
if (found == NULL) {
|
||||
TRI_set_errno(TRI_VOC_ERROR_DOCUMENT_NOT_FOUND);
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove all other indexes
|
||||
n = TRI_SizeVectorPointer(&collection->_indexes);
|
||||
result = true;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx;
|
||||
|
||||
idx = TRI_AtVectorPointer(&collection->_indexes, i);
|
||||
|
||||
ok = idx->remove(idx, header);
|
||||
|
||||
if (! ok) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
// and release the header pointer
|
||||
collection->_headers->release(collection->_headers, change.v);
|
||||
|
||||
// that's it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1176,7 +1262,8 @@ static bool EqualKeyDocument (TRI_associative_pointer_t* array, void const* key,
|
|||
static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
char const* location,
|
||||
char const* latitude,
|
||||
char const* longitude) {
|
||||
char const* longitude,
|
||||
TRI_idx_iid iid) {
|
||||
TRI_index_t* idx;
|
||||
TRI_shape_pid_t lat;
|
||||
TRI_shape_pid_t loc;
|
||||
|
@ -1204,10 +1291,10 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
|
|||
|
||||
// check, if we know the index
|
||||
if (location != NULL) {
|
||||
idx = TRI_LookupGeoIndexSimCollection(collection, location);
|
||||
idx = TRI_LookupGeoIndexSimCollection(collection, loc);
|
||||
}
|
||||
else if (longitude != NULL && latitude != NULL) {
|
||||
idx = TRI_LookupGeoIndex2SimCollection(collection, latitude, longitude);
|
||||
idx = TRI_LookupGeoIndex2SimCollection(collection, lat, lon);
|
||||
}
|
||||
else {
|
||||
TRI_set_errno(TRI_VOC_ERROR_ILLEGAL_PARAMETER);
|
||||
|
@ -1242,12 +1329,23 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
|
|||
(unsigned long) lon);
|
||||
}
|
||||
|
||||
if (iid) {
|
||||
idx->_iid = iid;
|
||||
}
|
||||
|
||||
// initialises the index with all existing documents
|
||||
FillIndex(collection, idx);
|
||||
|
||||
// and store index
|
||||
TRI_PushBackVectorPointer(&collection->_indexes, idx);
|
||||
|
||||
if (collection->_geoIndex == NULL) {
|
||||
collection->_geoIndex = (TRI_geo_index_t*) idx;
|
||||
}
|
||||
else if (collection->_geoIndex->base._iid > idx->_iid) {
|
||||
collection->_geoIndex = (TRI_geo_index_t*) idx;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -1269,15 +1367,11 @@ static TRI_index_t* CreateGeoIndexSimCollection (TRI_sim_collection_t* collectio
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
||||
char const* location) {
|
||||
TRI_shape_pid_t loc;
|
||||
TRI_shaper_t* shaper;
|
||||
TRI_shape_pid_t location) {
|
||||
size_t n;
|
||||
size_t i;
|
||||
|
||||
n = TRI_SizeVectorPointer(&collection->_indexes);
|
||||
shaper = collection->base._shaper;
|
||||
loc = shaper->findAttributePathByName(shaper, location);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx;
|
||||
|
@ -1287,7 +1381,7 @@ TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
|||
if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
|
||||
TRI_geo_index_t* geo = (TRI_geo_index_t*) idx;
|
||||
|
||||
if (geo->_location == loc) {
|
||||
if (geo->_location != 0 && geo->_location == location) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
@ -1301,18 +1395,12 @@ TRI_index_t* TRI_LookupGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection,
|
||||
char const* latitude,
|
||||
char const* longitude) {
|
||||
TRI_shape_pid_t lat;
|
||||
TRI_shape_pid_t lon;
|
||||
TRI_shaper_t* shaper;
|
||||
TRI_shape_pid_t latitude,
|
||||
TRI_shape_pid_t longitude) {
|
||||
size_t n;
|
||||
size_t i;
|
||||
|
||||
n = TRI_SizeVectorPointer(&collection->_indexes);
|
||||
shaper = collection->base._shaper;
|
||||
lat = shaper->findAttributePathByName(shaper, latitude);
|
||||
lon = shaper->findAttributePathByName(shaper, longitude);
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
TRI_index_t* idx;
|
||||
|
@ -1322,7 +1410,7 @@ TRI_index_t* TRI_LookupGeoIndex2SimCollection (TRI_sim_collection_t* collection,
|
|||
if (idx->_type == TRI_IDX_TYPE_GEO_INDEX) {
|
||||
TRI_geo_index_t* geo = (TRI_geo_index_t*) idx;
|
||||
|
||||
if (geo->_latitude == lat && geo->_longitude == lon) {
|
||||
if (geo->_latitude != 0 && geo->_longitude != 0 && geo->_latitude == latitude && geo->_longitude == longitude) {
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
|
@ -1346,7 +1434,7 @@ bool TRI_EnsureGeoIndexSimCollection (TRI_sim_collection_t* collection,
|
|||
|
||||
TRI_WriteLockReadWriteLock(&collection->_lock);
|
||||
|
||||
idx = CreateGeoIndexSimCollection(collection, location, NULL, NULL);
|
||||
idx = CreateGeoIndexSimCollection(collection, location, NULL, NULL, 0);
|
||||
|
||||
if (idx == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&collection->_lock);
|
||||
|
@ -1385,7 +1473,7 @@ bool TRI_EnsureGeoIndex2SimCollection (TRI_sim_collection_t* collection,
|
|||
|
||||
TRI_WriteLockReadWriteLock(&collection->_lock);
|
||||
|
||||
idx = CreateGeoIndexSimCollection(collection, NULL, latitude, longitude);
|
||||
idx = CreateGeoIndexSimCollection(collection, NULL, latitude, longitude, 0);
|
||||
|
||||
if (idx == NULL) {
|
||||
TRI_WriteUnlockReadWriteLock(&collection->_lock);
|
||||
|
|
|
@ -41,6 +41,7 @@ extern "C" {
|
|||
// -----------------------------------------------------------------------------
|
||||
|
||||
struct TRI_index_s;
|
||||
struct TRI_geo_index_s;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
|
@ -71,6 +72,7 @@ typedef struct TRI_sim_collection_s {
|
|||
TRI_headers_t* _headers;
|
||||
TRI_associative_pointer_t _primaryIndex;
|
||||
TRI_vector_pointer_t _indexes;
|
||||
struct TRI_geo_index_s* _geoIndex;
|
||||
|
||||
// .............................................................................
|
||||
// this condition variable protects the _journals
|
||||
|
@ -176,7 +178,7 @@ bool TRI_CloseSimCollection (TRI_sim_collection_t* collection);
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_index_s* TRI_LookupGeoIndexSimCollection (struct TRI_sim_collection_s* collection,
|
||||
char const* location);
|
||||
TRI_shape_pid_t location);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief finds a geo index
|
||||
|
@ -185,8 +187,8 @@ struct TRI_index_s* TRI_LookupGeoIndexSimCollection (struct TRI_sim_collection_s
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct TRI_index_s* TRI_LookupGeoIndex2SimCollection (struct TRI_sim_collection_s* collection,
|
||||
char const* latitude,
|
||||
char const* longitude);
|
||||
TRI_shape_pid_t latitude,
|
||||
TRI_shape_pid_t longitude);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ensures that a geo index exists
|
||||
|
|
|
@ -1,192 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write slots
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 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 Dr. Frank Celler
|
||||
/// @author Copyright 2011-2010, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "write-slots.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialses a write slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitWriteSlots (TRI_col_write_slots_t* slots) {
|
||||
size_t i;
|
||||
TRI_col_write_slot_t* next;
|
||||
TRI_col_write_slot_t* last = NULL;
|
||||
|
||||
for (i = 0; i < TRI_COL_WRITE_SLOTS; ++i) {
|
||||
next = TRI_Allocate(sizeof(TRI_col_write_slot_t));
|
||||
|
||||
next->_begin = NULL;
|
||||
next->_end = NULL;
|
||||
next->_backward = NULL;
|
||||
next->_forward = last;
|
||||
|
||||
last = next;
|
||||
}
|
||||
|
||||
slots->_free = last;
|
||||
slots->_used = NULL;
|
||||
|
||||
slots->_position = NULL;
|
||||
slots->_synced = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys the writes slots, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyWriteSlots (TRI_col_write_slots_t* slots) {
|
||||
TRI_col_write_slot_t* next;
|
||||
TRI_col_write_slot_t* current;
|
||||
|
||||
// clear free list
|
||||
current = slots->_free;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->_forward;
|
||||
TRI_Free(current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
// clear used list
|
||||
current = slots->_used;
|
||||
|
||||
while (current != 0) {
|
||||
next = current->_forward;
|
||||
TRI_Free(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys the writes slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeWriteSlots (TRI_col_write_slots_t* slots) {
|
||||
TRI_DestroyWriteSlots(slots);
|
||||
TRI_Free(slots);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief acquires a free write slot, returns 0 if none is free
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_col_write_slot_t* TRI_AcquireWriteSlots (TRI_col_write_slots_t* slots, void* begin, void* end) {
|
||||
TRI_col_write_slot_t* slot;
|
||||
TRI_col_write_slot_t* used;
|
||||
|
||||
if (slots->_free == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
slot = slots->_free;
|
||||
slots->_free = slot->_forward;
|
||||
|
||||
slot->_forward = NULL;
|
||||
slot->_begin = begin;
|
||||
slot->_end = end;
|
||||
|
||||
if (slots->_used == NULL) {
|
||||
slot->_backward = NULL;
|
||||
|
||||
slots->_used = slot;
|
||||
}
|
||||
else {
|
||||
used = slots->_used;
|
||||
|
||||
while (used->_forward != NULL) {
|
||||
used = used->_forward;
|
||||
}
|
||||
|
||||
used->_forward = slot;
|
||||
slot->_backward = used;
|
||||
}
|
||||
|
||||
if (slots->_synced == NULL) {
|
||||
slots->_synced = begin;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief releases a write slot
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_ReleaseWriteSlots (TRI_col_write_slots_t* slots, TRI_col_write_slot_t* slot) {
|
||||
void* position;
|
||||
|
||||
// correct the predecessor
|
||||
if (slot->_backward == NULL) {
|
||||
slots->_used = slot->_forward;
|
||||
|
||||
// correct the position
|
||||
if (slots->_used == NULL) {
|
||||
slots->_position = slot->_end;
|
||||
}
|
||||
else {
|
||||
slots->_position = slots->_used->_begin;
|
||||
}
|
||||
}
|
||||
else {
|
||||
slot->_backward->_forward = slot->_forward;
|
||||
}
|
||||
|
||||
// correct the successor
|
||||
if (slot->_forward != NULL) {
|
||||
slot->_forward->_backward = slot->_backward;
|
||||
}
|
||||
|
||||
// put back onto free list
|
||||
slot->_backward = NULL;
|
||||
slot->_begin = NULL;
|
||||
slot->_end = NULL;
|
||||
|
||||
slot->_forward = slots->_free;
|
||||
slots->_free = slot;
|
||||
|
||||
position = slots->_position;
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
|
||||
// End:
|
|
@ -1,148 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write slots
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2011 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 Dr. Frank Celler
|
||||
/// @author Copyright 2011-2010, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRIAGENS_DURHAM_VOCBASE_WRITE_SLOTS_H
|
||||
#define TRIAGENS_DURHAM_VOCBASE_WRITE_SLOTS_H 1
|
||||
|
||||
#include <Basics/Common.h>
|
||||
|
||||
#include <Basics/vector.h>
|
||||
#include <Basics/locks.h>
|
||||
|
||||
#include <VocBase/vocbase.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public constants
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief default write slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_COL_WRITE_SLOTS (10)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public types
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief single write slot
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_col_write_slot_s {
|
||||
struct TRI_col_write_slot_s* _forward;
|
||||
struct TRI_col_write_slot_s* _backward;
|
||||
|
||||
void* _begin;
|
||||
void* _end; // excluding
|
||||
}
|
||||
TRI_col_write_slot_t;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_col_write_slots_s {
|
||||
TRI_col_write_slot_t* _free;
|
||||
TRI_col_write_slot_t* _used;
|
||||
|
||||
void* _position; // position of finished writes (excluding)
|
||||
void* _synced; // position of synced writes (excluding)
|
||||
}
|
||||
TRI_col_write_slots_t;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase VocBase
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief initialses a write slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitWriteSlots (TRI_col_write_slots_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys the writes slots, but does not free the pointer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_DestroyWriteSlots (TRI_col_write_slots_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief destroys the writes slots
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_FreeWriteSlots (TRI_col_write_slots_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief acquires a free write slot, returns 0 if none is free
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_col_write_slot_t* TRI_AcquireWriteSlots (TRI_col_write_slots_t*, void* begin, void* end);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief releases a write slot
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void* TRI_ReleaseWriteSlots (TRI_col_write_slots_t*, TRI_col_write_slot_t*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
|
||||
// End:
|
Loading…
Reference in New Issue