mongory 0.8.0-x86_64-linux → 0.8.2-x86_64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +12 -0
- data/docs/advanced_usage.md +10 -0
- data/ext/mongory_ext/mongory-core/src/foundations/array.c +22 -15
- data/ext/mongory_ext/mongory-core/src/foundations/array_private.h +1 -0
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.c +0 -2
- data/ext/mongory_ext/mongory-core/src/foundations/string_buffer.h +0 -6
- data/ext/mongory_ext/mongory-core/src/foundations/table.c +9 -10
- data/ext/mongory_ext/mongory-core/src/foundations/utils.c +21 -11
- data/ext/mongory_ext/mongory-core/src/foundations/utils.h +2 -2
- data/ext/mongory_ext/mongory-core/src/foundations/value.c +10 -2
- data/ext/mongory_ext/mongory-core/src/matchers/base_matcher.h +2 -0
- data/ext/mongory_ext/mongory-core/src/matchers/existance_matcher.c +16 -3
- data/ext/mongory_ext/mongory-core/src/matchers/literal_matcher.c +4 -0
- data/ext/mongory_ext/mongory-core/src/matchers/matcher.c +43 -7
- data/ext/mongory_ext/mongory_ext.c +57 -19
- data/lib/core/2.6/mongory_ext.so +0 -0
- data/lib/core/2.7/mongory_ext.so +0 -0
- data/lib/core/3.0/mongory_ext.so +0 -0
- data/lib/core/3.1/mongory_ext.so +0 -0
- data/lib/core/3.2/mongory_ext.so +0 -0
- data/lib/core/3.3/mongory_ext.so +0 -0
- data/lib/core/3.4/mongory_ext.so +0 -0
- data/lib/core/4.0/mongory_ext.so +0 -0
- data/lib/mongory/c_matcher.rb +7 -7
- data/lib/mongory/converters/key_converter.rb +1 -1
- data/lib/mongory/matchers/array_record_matcher.rb +1 -1
- data/lib/mongory/matchers/field_matcher.rb +16 -3
- data/lib/mongory/query_builder.rb +6 -0
- data/lib/mongory/version.rb +1 -1
- data/lib/mongory.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 62fa18e529cd104d255956668e3acb8421d5d8a943d9c8505a6fec1213bed592
|
|
4
|
+
data.tar.gz: 75aefb02081fcd48af41b6d8f6cdb9c22cc066821a92b02e227ef3818c50b547
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d1d092f65c6afcd16ec537795d08f03b60d66bce217281e9d854d42657de024b3230c93f5115e3552f60c51389dfec3b14f61657ebc03eb08effacffe108b66f
|
|
7
|
+
data.tar.gz: c9426e11587601a802b57a054665d9d43a7e393d00b397aa17c2d6e77598a21f8d9a2ee52941e11b00f6aeb2f656b6620da7b6eb14cf94acd0c5813e54f3b614
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.8.2] - 2026-11-14
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
- **Key & Array Index Matching (`QueryMatcher` & `CMatcher`)**:
|
|
7
|
+
- Normalize `Integer` condition keys to `String` in `KeyConverter` (consistent with `Symbol` keys), preventing `TypeError` in `CMatcher` and `NoMethodError` in `FieldMatcher`.
|
|
8
|
+
- Enforce strict integer index format (`\A(?:0|-?[1-9]\d*)\z`) when matching against arrays so keys with leading zeros (e.g., `"01"`, `"-0"`) or multiline strings are treated as document field keys rather than array indices.
|
|
9
|
+
- Treat valid numeric keys on `Array` records strictly as array indices in both `FieldMatcher` and `mongory-core`.
|
|
10
|
+
- **C Extension (`mongory_ext`)**:
|
|
11
|
+
- Fix GC use-after-free crash when `$regex` condition is given as a `String` pattern by registering the compiled `Regexp` in the matcher's GC `mark_list`.
|
|
12
|
+
- Fix NULL pointer dereference crash when calling `CMatcher#disable_trace` or `CMatcher#print_trace` before `enable_trace`.
|
|
13
|
+
- Fix memory pool type mismatch and out-of-bounds `owner` read in `CMatcher#trace` and uninitialized `owner` pointer in `CMatcher#enable_trace`.
|
|
14
|
+
- Prevent memory leaks when `CMatcher.new`, `trace`, `enable_trace`, or `disable_trace` raises `Mongory::TypeError`.
|
|
15
|
+
- Coerce non-string/non-symbol hash keys in `DataConverter`-converted condition values and register them in `mark_list`.
|
|
16
|
+
- **Core (`mongory-core` submodule)**:
|
|
17
|
+
- Fix off-by-one capacity growth condition in `mongory_array` and `mongory_table`.
|
|
18
|
+
- Propagate `extern_ctx` in `mongory_matcher_field_new` so nested custom matchers receive the Ruby matcher context.
|
|
19
|
+
- Sync trace state across `literal_matcher`'s `delegate_matcher` and `array_record_matcher`.
|
|
20
|
+
- Return `mongory_value_compare_fail` when comparing `NaN` float/double values instead of treating `NaN` as equal.
|
|
21
|
+
|
|
22
|
+
## [0.8.1] - 2025-08-30
|
|
23
|
+
|
|
24
|
+
### Fixes
|
|
25
|
+
- Use `require_relative` instead of `require` for internal file loading.
|
|
26
|
+
|
|
27
|
+
### Docs & Chores
|
|
28
|
+
- Deprecate `QueryBuilder#fast` and update YARD documentation and README.
|
|
29
|
+
|
|
30
|
+
## [0.8.0] - 2025-08-30
|
|
31
|
+
|
|
32
|
+
### Features
|
|
33
|
+
- Add trace mode support to `QueryBuilder` and `CQueryBuilder`, printing trace output and resetting trace pool on each match.
|
|
34
|
+
- Expose `CMatcher.trace_result_colorful=` configuration option.
|
|
35
|
+
- Support cross-platform precompiled native gems for Linux (`x86_64`, `aarch64`, musl/glibc), macOS (`x86_64-darwin`, `arm64-darwin`), and Windows (`x64-mingw32`, `x64-mingw-ucrt`).
|
|
36
|
+
|
|
2
37
|
## [0.7.1] - 2025-08-17
|
|
3
38
|
### Fixes
|
|
4
39
|
- Linter error
|
data/README.md
CHANGED
|
@@ -110,6 +110,18 @@ records = [
|
|
|
110
110
|
result = records.mongory
|
|
111
111
|
.where(:age.gte => 18)
|
|
112
112
|
.or({ :name => /J/ }, { :name.eq => 'Bob' })
|
|
113
|
+
.to_a
|
|
114
|
+
|
|
115
|
+
# Or input condition via json string from front-end
|
|
116
|
+
result = records.mongory
|
|
117
|
+
.where(JSON.parse('{
|
|
118
|
+
"age": {"$gt": 18},
|
|
119
|
+
"$or": [
|
|
120
|
+
{"name": {"$regex": "J"}},
|
|
121
|
+
{"name": "Bob"}
|
|
122
|
+
]
|
|
123
|
+
}'))
|
|
124
|
+
.to_a
|
|
113
125
|
|
|
114
126
|
# Using limit to restrict results
|
|
115
127
|
# Note: limit executes immediately and affects subsequent conditions
|
data/docs/advanced_usage.md
CHANGED
|
@@ -25,6 +25,16 @@ users.mongory
|
|
|
25
25
|
posts.mongory
|
|
26
26
|
.where(:tags.elem_match => { :name => 'ruby', :priority.gt => 5 })
|
|
27
27
|
.where(:comments.every => { :approved => true })
|
|
28
|
+
|
|
29
|
+
# Since Matcher provide `to_proc` method, you could treat Matcher as a block
|
|
30
|
+
matcher = Mongory::QueryMatcher.new({
|
|
31
|
+
:tags.elem_match => { :name => 'ruby', :priority.gt => 5 },
|
|
32
|
+
:comments.every => { :approved => true }
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
# Will filter
|
|
36
|
+
posts_1.select!(&matcher)
|
|
37
|
+
posts_2.select!(&matcher)
|
|
28
38
|
```
|
|
29
39
|
|
|
30
40
|
## Integration with ActiveRecord
|
|
@@ -146,8 +146,8 @@ static inline mongory_value *mongory_array_get(mongory_array *self, size_t index
|
|
|
146
146
|
*/
|
|
147
147
|
static inline bool mongory_array_set(mongory_array *self, size_t index, mongory_value *value) {
|
|
148
148
|
mongory_array_private *internal = (mongory_array_private *)self;
|
|
149
|
-
// Ensure capacity for the given
|
|
150
|
-
if (!mongory_array_grow_if_needed(self, index
|
|
149
|
+
// Ensure capacity for the given 0-based index.
|
|
150
|
+
if (!mongory_array_grow_if_needed(self, index)) {
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -163,17 +163,10 @@ static inline bool mongory_array_set(mongory_array *self, size_t index, mongory_
|
|
|
163
163
|
return true;
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
* using the provided memory pool. Assigns function pointers for array
|
|
171
|
-
* operations.
|
|
172
|
-
*
|
|
173
|
-
* @param pool The memory pool to use for allocations.
|
|
174
|
-
* @return Pointer to the new mongory_array, or NULL on allocation failure.
|
|
175
|
-
*/
|
|
176
|
-
mongory_array *mongory_array_new(mongory_memory_pool *pool) {
|
|
166
|
+
mongory_array *mongory_array_new_with_capacity(mongory_memory_pool *pool, size_t capacity) {
|
|
167
|
+
if (capacity == 0) {
|
|
168
|
+
capacity = MONGORY_ARRAY_INIT_SIZE;
|
|
169
|
+
}
|
|
177
170
|
// First, allocate the private structure that holds all array metadata.
|
|
178
171
|
mongory_array_private *internal = MG_ALLOC_PTR(pool, mongory_array_private);
|
|
179
172
|
if (!internal) {
|
|
@@ -182,7 +175,7 @@ mongory_array *mongory_array_new(mongory_memory_pool *pool) {
|
|
|
182
175
|
}
|
|
183
176
|
|
|
184
177
|
// Then, allocate the initial block of memory for the array items.
|
|
185
|
-
mongory_value **items = MG_ALLOC_ARY(pool, mongory_value*,
|
|
178
|
+
mongory_value **items = MG_ALLOC_ARY(pool, mongory_value*, capacity);
|
|
186
179
|
if (!items) {
|
|
187
180
|
// If this fails, the 'internal' struct allocated above will be cleaned up
|
|
188
181
|
// by the pool, assuming it's a tracing pool.
|
|
@@ -200,11 +193,25 @@ mongory_array *mongory_array_new(mongory_memory_pool *pool) {
|
|
|
200
193
|
|
|
201
194
|
// Initialize the private part of the array structure.
|
|
202
195
|
internal->items = items;
|
|
203
|
-
internal->capacity =
|
|
196
|
+
internal->capacity = capacity;
|
|
204
197
|
|
|
205
198
|
return &internal->base; // Return pointer to the public structure.
|
|
206
199
|
}
|
|
207
200
|
|
|
201
|
+
/**
|
|
202
|
+
* @brief Creates and initializes a new mongory_array.
|
|
203
|
+
*
|
|
204
|
+
* Allocates memory for the array structure itself and its initial item storage
|
|
205
|
+
* using the provided memory pool. Assigns function pointers for array
|
|
206
|
+
* operations.
|
|
207
|
+
*
|
|
208
|
+
* @param pool The memory pool to use for allocations.
|
|
209
|
+
* @return Pointer to the new mongory_array, or NULL on allocation failure.
|
|
210
|
+
*/
|
|
211
|
+
mongory_array *mongory_array_new(mongory_memory_pool *pool) {
|
|
212
|
+
return mongory_array_new_with_capacity(pool, MONGORY_ARRAY_INIT_SIZE);
|
|
213
|
+
}
|
|
214
|
+
|
|
208
215
|
/**
|
|
209
216
|
* @brief Creates a new mongory_array instance with a nested array.
|
|
210
217
|
*
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include <stdbool.h>
|
|
7
7
|
|
|
8
8
|
bool mongory_array_resize(mongory_array *self, size_t size); // resize array
|
|
9
|
+
mongory_array *mongory_array_new_with_capacity(mongory_memory_pool *pool, size_t capacity);
|
|
9
10
|
|
|
10
11
|
typedef struct mongory_array_private {
|
|
11
12
|
mongory_array base; // public array
|
|
@@ -16,8 +16,6 @@ mongory_string_buffer *mongory_string_buffer_new(mongory_memory_pool *pool) {
|
|
|
16
16
|
return buffer;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
void mongory_string_buffer_free(mongory_string_buffer *buffer) { buffer->pool->free(buffer->pool->ctx); }
|
|
20
|
-
|
|
21
19
|
static inline void mongory_string_buffer_grow(mongory_string_buffer *buffer, size_t additional_size) {
|
|
22
20
|
bool trigger_grow = false;
|
|
23
21
|
while (buffer->size + additional_size + 1 > buffer->capacity) {
|
|
@@ -40,10 +40,4 @@ char *mongory_string_buffer_cstr(mongory_string_buffer *buffer);
|
|
|
40
40
|
*/
|
|
41
41
|
void mongory_string_buffer_clear(mongory_string_buffer *buffer);
|
|
42
42
|
|
|
43
|
-
/**
|
|
44
|
-
* @brief Frees the buffer.
|
|
45
|
-
* @param buffer The buffer to free.
|
|
46
|
-
*/
|
|
47
|
-
void mongory_string_buffer_free(mongory_string_buffer *buffer);
|
|
48
|
-
|
|
49
43
|
#endif
|
|
@@ -178,11 +178,12 @@ static inline bool mongory_table_rehash(mongory_table *self) {
|
|
|
178
178
|
// might copy elements if count is not zero. We are managing elements manually.
|
|
179
179
|
internal->array->count = 0;
|
|
180
180
|
|
|
181
|
-
if (!mongory_array_resize(internal->array, new_capacity)
|
|
181
|
+
if (!mongory_array_resize(internal->array, new_capacity) ||
|
|
182
|
+
!internal->array->set(internal->array, new_capacity - 1, NULL)) {
|
|
182
183
|
// Error: Rehashing failed because the underlying array could not be resized.
|
|
183
184
|
// The table remains functional but may have a suboptimal load factor.
|
|
184
185
|
self->pool->error = &MONGORY_ALLOC_ERROR;
|
|
185
|
-
internal->array->count =
|
|
186
|
+
internal->array->count = original_capacity; // Restore previous bucket count
|
|
186
187
|
return false;
|
|
187
188
|
}
|
|
188
189
|
// After resize, internal->array (and old_array_private_view) points to the
|
|
@@ -416,14 +417,12 @@ mongory_table *mongory_table_new(mongory_memory_pool *pool) {
|
|
|
416
417
|
return NULL; // Must have a valid pool.
|
|
417
418
|
|
|
418
419
|
size_t init_capacity = MONGORY_TABLE_INIT_SIZE;
|
|
419
|
-
mongory_array *bucket_array =
|
|
420
|
-
|
|
421
|
-
// Initialize the bucket array
|
|
422
|
-
//
|
|
423
|
-
//
|
|
424
|
-
|
|
425
|
-
bool array_init_success = bucket_array && mongory_array_resize(bucket_array, init_capacity) &&
|
|
426
|
-
bucket_array->set(bucket_array, init_capacity - 1, NULL);
|
|
420
|
+
mongory_array *bucket_array = mongory_array_new_with_capacity(pool, init_capacity);
|
|
421
|
+
|
|
422
|
+
// Initialize the bucket array by setting the last element to NULL.
|
|
423
|
+
// The `mongory_array_set` function will automatically fill all intermediate
|
|
424
|
+
// slots with NULL without triggering a resize.
|
|
425
|
+
bool array_init_success = bucket_array && bucket_array->set(bucket_array, init_capacity - 1, NULL);
|
|
427
426
|
|
|
428
427
|
if (!array_init_success) {
|
|
429
428
|
// If array initialization fails, we cannot proceed.
|
|
@@ -25,30 +25,40 @@
|
|
|
25
25
|
* `false` otherwise. `errno` may be set by `strtol`.
|
|
26
26
|
*/
|
|
27
27
|
bool mongory_try_parse_int(const char *key, int *out) {
|
|
28
|
-
if (key == NULL
|
|
28
|
+
if (key == NULL) {
|
|
29
29
|
return false; // Invalid input string.
|
|
30
30
|
}
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
|
|
32
|
+
// Strictly match "0" or "-?[1-9][0-9]*" (no leading whitespace, '+', "-0", or leading zeros like "01").
|
|
33
|
+
if (key[0] == '0') {
|
|
34
|
+
if (key[1] != '\0') {
|
|
35
|
+
return false; // Disallow leading zeros like "00" or "01".
|
|
36
|
+
}
|
|
37
|
+
if (out != NULL) {
|
|
38
|
+
*out = 0;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const char *p = (key[0] == '-') ? key + 1 : key;
|
|
44
|
+
if (*p < '1') {
|
|
45
|
+
return false; // Disallow "", "-", "-0", "-01", leading whitespace, or '+'.
|
|
33
46
|
}
|
|
34
47
|
|
|
35
48
|
char *endptr = NULL;
|
|
36
49
|
errno = 0; // Clear errno before calling strtol.
|
|
37
50
|
long val = strtol(key, &endptr, 10); // Base 10 conversion.
|
|
38
51
|
|
|
39
|
-
// Check for parsing errors reported by strtol.
|
|
40
|
-
if (endptr == key) {
|
|
41
|
-
return false; // No digits were found.
|
|
42
|
-
}
|
|
43
52
|
if (*endptr != '\0') {
|
|
44
53
|
return false; // Additional characters after the number.
|
|
45
54
|
}
|
|
46
|
-
if (
|
|
47
|
-
// Value out of range for int.
|
|
48
|
-
return false;
|
|
55
|
+
if (val < INT_MIN || val > INT_MAX) {
|
|
56
|
+
return false; // Value out of range for int.
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
if (out != NULL) {
|
|
60
|
+
*out = (int)val; // Successfully parsed and within int range.
|
|
61
|
+
}
|
|
52
62
|
return true;
|
|
53
63
|
}
|
|
54
64
|
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* range (`INT_MIN`, `INT_MAX`).
|
|
14
14
|
*
|
|
15
15
|
* @param key The null-terminated string to parse. Must not be NULL or empty.
|
|
16
|
-
* @param out
|
|
17
|
-
* successful.
|
|
16
|
+
* @param out Optional pointer to an integer where the parsed value will be
|
|
17
|
+
* stored if successful. May be NULL if only validation is needed.
|
|
18
18
|
* @return bool True if the string was successfully parsed as an integer and is
|
|
19
19
|
* within `int` range, false otherwise. `errno` might be set by `strtol` on
|
|
20
20
|
* failure (e.g. `ERANGE`).
|
|
@@ -154,6 +154,9 @@ static inline int mongory_value_int_compare(mongory_value *a, mongory_value *b)
|
|
|
154
154
|
// Compare int (a) as double with double (b).
|
|
155
155
|
double a_as_double = (double)a->data.i;
|
|
156
156
|
double b_value = b->data.d;
|
|
157
|
+
if (b_value != b_value) {
|
|
158
|
+
return mongory_value_compare_fail; // NaN is not comparable.
|
|
159
|
+
}
|
|
157
160
|
return (a_as_double > b_value) - (a_as_double < b_value);
|
|
158
161
|
}
|
|
159
162
|
if (b->type == MONGORY_TYPE_INT) {
|
|
@@ -179,14 +182,19 @@ mongory_value *mongory_value_wrap_i(mongory_memory_pool *pool, int64_t i_val) {
|
|
|
179
182
|
|
|
180
183
|
/** Compares MONGORY_TYPE_DOUBLE with DOUBLE or INT. */
|
|
181
184
|
static inline int mongory_value_double_compare(mongory_value *a, mongory_value *b) {
|
|
185
|
+
double a_value = a->data.d;
|
|
186
|
+
if (a_value != a_value) {
|
|
187
|
+
return mongory_value_compare_fail; // NaN is not comparable.
|
|
188
|
+
}
|
|
182
189
|
if (b->type == MONGORY_TYPE_DOUBLE) {
|
|
183
|
-
double a_value = a->data.d;
|
|
184
190
|
double b_value = b->data.d;
|
|
191
|
+
if (b_value != b_value) {
|
|
192
|
+
return mongory_value_compare_fail; // NaN is not comparable.
|
|
193
|
+
}
|
|
185
194
|
return (a_value > b_value) - (a_value < b_value);
|
|
186
195
|
}
|
|
187
196
|
if (b->type == MONGORY_TYPE_INT) {
|
|
188
197
|
// Compare double (a) with int (b) as double.
|
|
189
|
-
double a_value = a->data.d;
|
|
190
198
|
double b_as_double = (double)b->data.i;
|
|
191
199
|
return (a_value > b_as_double) - (a_value < b_as_double);
|
|
192
200
|
}
|
|
@@ -97,4 +97,6 @@ mongory_matcher *mongory_matcher_always_true_new(mongory_memory_pool *pool, mong
|
|
|
97
97
|
*/
|
|
98
98
|
mongory_matcher *mongory_matcher_always_false_new(mongory_memory_pool *pool, mongory_value *condition, void *extern_ctx);
|
|
99
99
|
|
|
100
|
+
void mongory_matcher_enable_trace_at(mongory_matcher *matcher, mongory_array *trace_stack, int level);
|
|
101
|
+
|
|
100
102
|
#endif /* MONGORY_MATCHER_BASE_H */
|
|
@@ -95,7 +95,7 @@ static inline bool mongory_matcher_present_match(mongory_matcher *matcher, mongo
|
|
|
95
95
|
return !condition_expects_presence;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
bool actual_value_is_present;
|
|
98
|
+
bool actual_value_is_present = false;
|
|
99
99
|
switch (value->type) {
|
|
100
100
|
case MONGORY_TYPE_ARRAY:
|
|
101
101
|
actual_value_is_present = (value->data.a != NULL && value->data.a->count > 0);
|
|
@@ -103,9 +103,22 @@ static inline bool mongory_matcher_present_match(mongory_matcher *matcher, mongo
|
|
|
103
103
|
case MONGORY_TYPE_TABLE:
|
|
104
104
|
actual_value_is_present = (value->data.t != NULL && value->data.t->count > 0);
|
|
105
105
|
break;
|
|
106
|
-
case MONGORY_TYPE_STRING:
|
|
107
|
-
|
|
106
|
+
case MONGORY_TYPE_STRING: {
|
|
107
|
+
// If the string is NULL, it is not "present".
|
|
108
|
+
// If the strint is " " or more than one space, it is not "present".
|
|
109
|
+
char *s = value->data.s;
|
|
110
|
+
if (s != NULL && *s != '\0') {
|
|
111
|
+
char *p = s;
|
|
112
|
+
while (*p != '\0') {
|
|
113
|
+
if (*p != ' ') {
|
|
114
|
+
actual_value_is_present = true;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
p++;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
108
120
|
break;
|
|
121
|
+
}
|
|
109
122
|
case MONGORY_TYPE_NULL:
|
|
110
123
|
actual_value_is_present = false; // An explicit BSON-style Null is not "present".
|
|
111
124
|
break;
|
|
@@ -62,6 +62,9 @@ static inline bool mongory_matcher_literal_match(mongory_matcher *matcher, mongo
|
|
|
62
62
|
// Lazily create the array_record_matcher if needed.
|
|
63
63
|
// The condition for array_record_new is the original condition of the literal matcher.
|
|
64
64
|
literal->array_record_matcher = mongory_matcher_array_record_new(literal->base.pool, literal->base.condition, literal->base.extern_ctx);
|
|
65
|
+
if (literal->array_record_matcher && literal->base.trace_stack) {
|
|
66
|
+
mongory_matcher_enable_trace_at(literal->array_record_matcher, literal->base.trace_stack, literal->base.trace_level + 1);
|
|
67
|
+
}
|
|
65
68
|
}
|
|
66
69
|
// If right child exists (or was successfully created), use it.
|
|
67
70
|
return literal->array_record_matcher ? literal->array_record_matcher->match(literal->array_record_matcher, value) : false;
|
|
@@ -207,6 +210,7 @@ mongory_matcher *mongory_matcher_field_new(mongory_memory_pool *pool, char *fiel
|
|
|
207
210
|
field_m->literal.base.name = mongory_string_cpy(pool, "Field");
|
|
208
211
|
field_m->literal.base.explain = mongory_matcher_field_explain;
|
|
209
212
|
field_m->literal.base.traverse = mongory_matcher_literal_traverse;
|
|
213
|
+
field_m->literal.base.extern_ctx = extern_ctx;
|
|
210
214
|
// The 'left' child of the composite is the actual matcher for the field's value,
|
|
211
215
|
// determined by the type of 'condition_for_field'.
|
|
212
216
|
field_m->literal.delegate_matcher = mongory_matcher_literal_delegate(pool, condition_for_field, extern_ctx);
|
|
@@ -147,13 +147,38 @@ static bool mongory_matcher_enable_trace_cb(mongory_matcher *matcher, mongory_ma
|
|
|
147
147
|
matcher->trace_stack = (mongory_array *)ctx->acc;
|
|
148
148
|
matcher->trace_level = ctx->level;
|
|
149
149
|
matcher->match = mongory_matcher_traced_match;
|
|
150
|
+
if (matcher->traverse == mongory_matcher_literal_traverse) {
|
|
151
|
+
mongory_literal_matcher *literal = (mongory_literal_matcher *)matcher;
|
|
152
|
+
if (literal->array_record_matcher && literal->delegate_matcher) {
|
|
153
|
+
mongory_matcher_traverse_context delegate_ctx = {
|
|
154
|
+
.pool = ctx->pool,
|
|
155
|
+
.level = ctx->level + 1,
|
|
156
|
+
.count = 0,
|
|
157
|
+
.total = 1,
|
|
158
|
+
.acc = ctx->acc,
|
|
159
|
+
.callback = ctx->callback,
|
|
160
|
+
};
|
|
161
|
+
literal->delegate_matcher->traverse(literal->delegate_matcher, &delegate_ctx);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
150
164
|
return true;
|
|
151
165
|
}
|
|
152
166
|
|
|
153
167
|
static bool mongory_matcher_disable_trace_cb(mongory_matcher *matcher, mongory_matcher_traverse_context *ctx) {
|
|
154
|
-
(void)ctx;
|
|
155
168
|
matcher->match = matcher->original_match;
|
|
156
169
|
matcher->trace_stack = NULL;
|
|
170
|
+
if (matcher->traverse == mongory_matcher_literal_traverse) {
|
|
171
|
+
mongory_literal_matcher *literal = (mongory_literal_matcher *)matcher;
|
|
172
|
+
if (literal->array_record_matcher && literal->delegate_matcher) {
|
|
173
|
+
mongory_matcher_traverse_context delegate_ctx = {
|
|
174
|
+
.level = ctx->level + 1,
|
|
175
|
+
.count = 0,
|
|
176
|
+
.total = 1,
|
|
177
|
+
.callback = ctx->callback,
|
|
178
|
+
};
|
|
179
|
+
literal->delegate_matcher->traverse(literal->delegate_matcher, &delegate_ctx);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
157
182
|
return true;
|
|
158
183
|
}
|
|
159
184
|
|
|
@@ -192,15 +217,17 @@ static mongory_array *mongory_matcher_traces_sort(mongory_array *self, int level
|
|
|
192
217
|
return sorted_array;
|
|
193
218
|
}
|
|
194
219
|
|
|
195
|
-
void
|
|
196
|
-
|
|
197
|
-
|
|
220
|
+
void mongory_matcher_enable_trace_at(mongory_matcher *matcher, mongory_array *trace_stack, int level) {
|
|
221
|
+
if (!matcher || !trace_stack) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
MONGORY_VALIDATE_PTR(trace_stack->pool, matcher->traverse);
|
|
225
|
+
if (trace_stack->pool->error != NULL) {
|
|
198
226
|
return;
|
|
199
227
|
}
|
|
200
|
-
mongory_array *trace_stack = mongory_array_new(temp_pool);
|
|
201
228
|
mongory_matcher_traverse_context ctx = {
|
|
202
|
-
.pool =
|
|
203
|
-
.level =
|
|
229
|
+
.pool = trace_stack->pool,
|
|
230
|
+
.level = level,
|
|
204
231
|
.count = 0,
|
|
205
232
|
.total = 0,
|
|
206
233
|
.acc = (void *)trace_stack,
|
|
@@ -209,6 +236,15 @@ void mongory_matcher_enable_trace(mongory_matcher *matcher, mongory_memory_pool
|
|
|
209
236
|
matcher->traverse(matcher, &ctx);
|
|
210
237
|
}
|
|
211
238
|
|
|
239
|
+
void mongory_matcher_enable_trace(mongory_matcher *matcher, mongory_memory_pool *temp_pool) {
|
|
240
|
+
MONGORY_VALIDATE_PTR(temp_pool, matcher) && MONGORY_VALIDATE_PTR(temp_pool, matcher->traverse);
|
|
241
|
+
if (temp_pool->error != NULL) {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
mongory_array *trace_stack = mongory_array_new(temp_pool);
|
|
245
|
+
mongory_matcher_enable_trace_at(matcher, trace_stack, 0);
|
|
246
|
+
}
|
|
247
|
+
|
|
212
248
|
void mongory_matcher_disable_trace(mongory_matcher *matcher) {
|
|
213
249
|
MONGORY_VALIDATE_PTR(matcher->pool, matcher) && MONGORY_VALIDATE_PTR(matcher->pool, matcher->traverse);
|
|
214
250
|
if (matcher->pool->error != NULL) {
|
|
@@ -108,11 +108,14 @@ static VALUE rb_mongory_matcher_new(int argc, VALUE *argv, VALUE class) {
|
|
|
108
108
|
rb_mongory_matcher_parse_argv(wrapper, argc, argv);
|
|
109
109
|
|
|
110
110
|
mongory_matcher *matcher = mongory_matcher_new(matcher_pool_base, wrapper->condition, wrapper->ctx);
|
|
111
|
-
if (
|
|
111
|
+
if (matcher_pool_base->error) {
|
|
112
|
+
char err_msg[256];
|
|
113
|
+
snprintf(err_msg, sizeof(err_msg), "%s",
|
|
114
|
+
matcher_pool_base->error->message ? matcher_pool_base->error->message : "Unknown error");
|
|
112
115
|
matcher_pool_base->free(matcher_pool_base);
|
|
113
116
|
scratch_pool_base->free(scratch_pool_base);
|
|
114
117
|
xfree(wrapper);
|
|
115
|
-
|
|
118
|
+
rb_raise(eMongoryTypeError, "Failed to create matcher: %s", err_msg);
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
wrapper->matcher = matcher;
|
|
@@ -182,16 +185,21 @@ static VALUE rb_mongory_matcher_explain(VALUE self) {
|
|
|
182
185
|
static VALUE rb_mongory_matcher_trace(VALUE self, VALUE data) {
|
|
183
186
|
rb_mongory_matcher_t *wrapper;
|
|
184
187
|
TypedData_Get_Struct(self, rb_mongory_matcher_t, &rb_mongory_matcher_type, wrapper);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
188
|
+
rb_mongory_memory_pool_t *trace_pool = rb_mongory_memory_pool_new();
|
|
189
|
+
trace_pool->owner = wrapper;
|
|
190
|
+
mongory_memory_pool *trace_pool_base = &trace_pool->base;
|
|
191
|
+
mongory_value *data_value = rb_to_mongory_value_shallow(trace_pool_base, data);
|
|
192
|
+
|
|
193
|
+
if (trace_pool_base->error) {
|
|
194
|
+
char err_msg[256];
|
|
195
|
+
snprintf(err_msg, sizeof(err_msg), "%s",
|
|
196
|
+
trace_pool_base->error->message ? trace_pool_base->error->message : "Unknown error");
|
|
197
|
+
trace_pool_base->free(trace_pool_base);
|
|
198
|
+
rb_raise(eMongoryTypeError, "Trace failed: %s", err_msg);
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
bool matched = mongory_matcher_trace(wrapper->matcher, data_value);
|
|
194
|
-
|
|
202
|
+
trace_pool_base->free(trace_pool_base);
|
|
195
203
|
|
|
196
204
|
return matched ? Qtrue : Qfalse;
|
|
197
205
|
}
|
|
@@ -200,14 +208,23 @@ static VALUE rb_mongory_matcher_trace(VALUE self, VALUE data) {
|
|
|
200
208
|
static VALUE rb_mongory_matcher_enable_trace(VALUE self) {
|
|
201
209
|
rb_mongory_matcher_t *wrapper;
|
|
202
210
|
TypedData_Get_Struct(self, rb_mongory_matcher_t, &rb_mongory_matcher_type, wrapper);
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (rb_mongory_error_handling(trace_pool, "Enable trace failed")) {
|
|
207
|
-
trace_pool->free(trace_pool);
|
|
208
|
-
return Qnil;
|
|
211
|
+
if (wrapper->trace_pool) {
|
|
212
|
+
wrapper->trace_pool->free(wrapper->trace_pool);
|
|
213
|
+
wrapper->trace_pool = NULL;
|
|
209
214
|
}
|
|
210
|
-
|
|
215
|
+
rb_mongory_memory_pool_t *trace_pool = rb_mongory_memory_pool_new();
|
|
216
|
+
trace_pool->owner = wrapper;
|
|
217
|
+
mongory_memory_pool *trace_pool_base = &trace_pool->base;
|
|
218
|
+
mongory_matcher_enable_trace(wrapper->matcher, trace_pool_base);
|
|
219
|
+
|
|
220
|
+
if (trace_pool_base->error) {
|
|
221
|
+
char err_msg[256];
|
|
222
|
+
snprintf(err_msg, sizeof(err_msg), "%s",
|
|
223
|
+
trace_pool_base->error->message ? trace_pool_base->error->message : "Unknown error");
|
|
224
|
+
trace_pool_base->free(trace_pool_base);
|
|
225
|
+
rb_raise(eMongoryTypeError, "Enable trace failed: %s", err_msg);
|
|
226
|
+
}
|
|
227
|
+
wrapper->trace_pool = trace_pool_base;
|
|
211
228
|
|
|
212
229
|
return Qnil;
|
|
213
230
|
}
|
|
@@ -218,9 +235,17 @@ static VALUE rb_mongory_matcher_disable_trace(VALUE self) {
|
|
|
218
235
|
TypedData_Get_Struct(self, rb_mongory_matcher_t, &rb_mongory_matcher_type, wrapper);
|
|
219
236
|
mongory_memory_pool *trace_pool = wrapper->trace_pool;
|
|
220
237
|
mongory_matcher_disable_trace(wrapper->matcher);
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
238
|
+
if (trace_pool) {
|
|
239
|
+
wrapper->trace_pool = NULL;
|
|
240
|
+
if (trace_pool->error) {
|
|
241
|
+
char err_msg[256];
|
|
242
|
+
snprintf(err_msg, sizeof(err_msg), "%s",
|
|
243
|
+
trace_pool->error->message ? trace_pool->error->message : "Unknown error");
|
|
244
|
+
trace_pool->free(trace_pool);
|
|
245
|
+
rb_raise(eMongoryTypeError, "Disable trace failed: %s", err_msg);
|
|
246
|
+
}
|
|
247
|
+
trace_pool->free(trace_pool);
|
|
248
|
+
}
|
|
224
249
|
|
|
225
250
|
return Qnil;
|
|
226
251
|
}
|
|
@@ -229,6 +254,9 @@ static VALUE rb_mongory_matcher_disable_trace(VALUE self) {
|
|
|
229
254
|
static VALUE rb_mongory_matcher_print_trace(VALUE self) {
|
|
230
255
|
rb_mongory_matcher_t *wrapper;
|
|
231
256
|
TypedData_Get_Struct(self, rb_mongory_matcher_t, &rb_mongory_matcher_type, wrapper);
|
|
257
|
+
if (!wrapper->trace_pool) {
|
|
258
|
+
return Qnil;
|
|
259
|
+
}
|
|
232
260
|
mongory_matcher_print_trace(wrapper->matcher);
|
|
233
261
|
rb_mongory_error_handling(wrapper->trace_pool, "Print trace failed");
|
|
234
262
|
|
|
@@ -266,6 +294,7 @@ static rb_mongory_memory_pool_t *rb_mongory_memory_pool_new() {
|
|
|
266
294
|
rb_mongory_memory_pool_t *pool = malloc(sizeof(rb_mongory_memory_pool_t));
|
|
267
295
|
mongory_memory_pool *base = mongory_memory_pool_new();
|
|
268
296
|
memcpy(&pool->base, base, sizeof(mongory_memory_pool));
|
|
297
|
+
pool->owner = NULL;
|
|
269
298
|
free(base);
|
|
270
299
|
|
|
271
300
|
return pool;
|
|
@@ -407,12 +436,16 @@ static int hash_foreach_deep_convert_cb(VALUE key, VALUE val, VALUE ptr) {
|
|
|
407
436
|
key_str = (char *)rb_id2name(SYM2ID(key));
|
|
408
437
|
store_map = owner->symbol_map;
|
|
409
438
|
} else {
|
|
439
|
+
if (!RB_TYPE_P(key, T_STRING)) {
|
|
440
|
+
key = rb_obj_as_string(key);
|
|
441
|
+
}
|
|
410
442
|
key_str = StringValueCStr(key);
|
|
411
443
|
store_map = owner->string_map;
|
|
412
444
|
}
|
|
413
445
|
mongory_value *store = mongory_value_wrap_u(ctx->pool, NULL);
|
|
414
446
|
store->origin = (void *)key;
|
|
415
447
|
store_map->set(store_map, key_str, store);
|
|
448
|
+
owner->mark_list->push(owner->mark_list, store);
|
|
416
449
|
mongory_value *cval = rb_to_mongory_value_deep(ctx->pool, val);
|
|
417
450
|
ctx->table->set(ctx->table, key_str, cval);
|
|
418
451
|
return ST_CONTINUE;
|
|
@@ -591,6 +624,10 @@ static bool rb_mongory_regex_match_adapter(mongory_memory_pool *pool, mongory_va
|
|
|
591
624
|
mongory_value *temp_value = mongory_value_wrap_regex(pool, (void *)rb_re);
|
|
592
625
|
memcpy(pattern, temp_value, sizeof(mongory_value));
|
|
593
626
|
pattern->origin = (void *)rb_re;
|
|
627
|
+
rb_mongory_memory_pool_t *rb_pool = (rb_mongory_memory_pool_t *)pool;
|
|
628
|
+
if (rb_pool->owner) {
|
|
629
|
+
rb_pool->owner->mark_list->push(rb_pool->owner->mark_list, pattern);
|
|
630
|
+
}
|
|
594
631
|
} else {
|
|
595
632
|
return false;
|
|
596
633
|
}
|
|
@@ -678,6 +715,7 @@ void Init_mongory_ext(void) {
|
|
|
678
715
|
// Define modules and classes
|
|
679
716
|
mMongory = rb_define_module("Mongory");
|
|
680
717
|
cMongoryMatcher = rb_define_class_under(mMongory, "CMatcher", rb_cObject);
|
|
718
|
+
rb_undef_alloc_func(cMongoryMatcher);
|
|
681
719
|
mMongoryMatchers = rb_define_module_under(mMongory, "Matchers");
|
|
682
720
|
VALUE mMongoryUtils = rb_define_module_under(mMongory, "Utils");
|
|
683
721
|
cMongoryMatcherContext = rb_define_class_under(mMongoryUtils, "Context", rb_cObject);
|
data/lib/core/2.6/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/2.7/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/3.0/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/3.1/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/3.2/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/3.3/mongory_ext.so
CHANGED
|
Binary file
|
data/lib/core/3.4/mongory_ext.so
CHANGED
|
Binary file
|
|
Binary file
|
data/lib/mongory/c_matcher.rb
CHANGED
|
@@ -10,9 +10,13 @@ module Mongory
|
|
|
10
10
|
# collection.mongory.c.where(condition).to_a
|
|
11
11
|
class CMatcher
|
|
12
12
|
# @!method self.new(condition)
|
|
13
|
-
# @param condition [
|
|
13
|
+
# @param condition [Hash] the condition
|
|
14
14
|
# @return [Mongory::CMatcher] a new matcher
|
|
15
15
|
# @note This method is implemented in the C extension
|
|
16
|
+
# @!method self.trace_result_colorful=(colorful)
|
|
17
|
+
# @param colorful [Boolean] whether to enable colorful trace result
|
|
18
|
+
# @return [void]
|
|
19
|
+
# @note This method is implemented in the C extension
|
|
16
20
|
#
|
|
17
21
|
# @!method match?(record)
|
|
18
22
|
# @param record [Object] the record to match against
|
|
@@ -20,7 +24,7 @@ module Mongory
|
|
|
20
24
|
# @note This method is implemented in the C extension
|
|
21
25
|
# @!method explain
|
|
22
26
|
# @return [void]
|
|
23
|
-
# @note This method will print
|
|
27
|
+
# @note This method will print matcher tree structure
|
|
24
28
|
# @note This method is implemented in the C extension
|
|
25
29
|
# @!method trace
|
|
26
30
|
# @return [Boolean] true if the record matches the condition, false otherwise
|
|
@@ -39,15 +43,11 @@ module Mongory
|
|
|
39
43
|
# @note This method will print trace result
|
|
40
44
|
# @note This method is implemented in the C extension
|
|
41
45
|
# @!method condition
|
|
42
|
-
# @return [
|
|
46
|
+
# @return [Hash] the condition
|
|
43
47
|
# @note This method is implemented in the C extension
|
|
44
48
|
# @!method context
|
|
45
49
|
# @return [Utils::Context] the context
|
|
46
50
|
# @note This method is implemented in the C extension
|
|
47
|
-
# @!method trace_result_colorful=
|
|
48
|
-
# @param colorful [Boolean] whether to enable colorful trace result
|
|
49
|
-
# @return [Boolean]
|
|
50
|
-
# @note This method is implemented in the C extension
|
|
51
51
|
|
|
52
52
|
# @return [Proc] a Proc that performs the matching operation
|
|
53
53
|
def to_proc
|
|
@@ -33,6 +33,8 @@ module Mongory
|
|
|
33
33
|
::Symbol
|
|
34
34
|
].freeze
|
|
35
35
|
|
|
36
|
+
INTEGER_INDEX_REGEX = /\A(?:0|-?[1-9]\d*)\z/.freeze
|
|
37
|
+
|
|
36
38
|
# Initializes a new field matcher.
|
|
37
39
|
#
|
|
38
40
|
# @param field [String, Symbol] the field to match against
|
|
@@ -84,6 +86,7 @@ module Mongory
|
|
|
84
86
|
def raw_proc
|
|
85
87
|
super_proc = super
|
|
86
88
|
field = @field
|
|
89
|
+
str_field, sym_field, int_field = parse_field_keys(field)
|
|
87
90
|
need_convert = @context.need_convert
|
|
88
91
|
data_converter = Mongory.data_converter
|
|
89
92
|
|
|
@@ -91,11 +94,11 @@ module Mongory
|
|
|
91
94
|
sub_record =
|
|
92
95
|
case record
|
|
93
96
|
when Hash
|
|
94
|
-
record.fetch(
|
|
95
|
-
record.fetch(
|
|
97
|
+
record.fetch(str_field) do
|
|
98
|
+
record.fetch(sym_field, KEY_NOT_FOUND)
|
|
96
99
|
end
|
|
97
100
|
when Array
|
|
98
|
-
record.fetch(
|
|
101
|
+
int_field ? record.fetch(int_field, KEY_NOT_FOUND) : KEY_NOT_FOUND
|
|
99
102
|
when KEY_NOT_FOUND, *CLASSES_NOT_ALLOW_TO_DIG
|
|
100
103
|
next false
|
|
101
104
|
else
|
|
@@ -124,6 +127,16 @@ module Mongory
|
|
|
124
127
|
|
|
125
128
|
private
|
|
126
129
|
|
|
130
|
+
def parse_field_keys(field)
|
|
131
|
+
str_field = field.to_s
|
|
132
|
+
int_field = if field.is_a?(Integer)
|
|
133
|
+
field
|
|
134
|
+
elsif field.is_a?(String) && INTEGER_INDEX_REGEX.match?(field)
|
|
135
|
+
field.to_i
|
|
136
|
+
end
|
|
137
|
+
[str_field, str_field.to_sym, int_field]
|
|
138
|
+
end
|
|
139
|
+
|
|
127
140
|
# Returns a single-line summary of the field matcher including the field and condition.
|
|
128
141
|
#
|
|
129
142
|
# @return [String] a formatted title for tree display
|
|
@@ -55,10 +55,16 @@ module Mongory
|
|
|
55
55
|
# Iterates through all records that match the current matcher.
|
|
56
56
|
# Uses a compiled Proc for faster matching.
|
|
57
57
|
#
|
|
58
|
+
# @deprecated
|
|
59
|
+
# Since C extension has implemented, the fast mode is no longer needed. Use C extension instead.
|
|
60
|
+
#
|
|
61
|
+
# This method is deprecated and will be removed in future versions.
|
|
62
|
+
#
|
|
58
63
|
# @yieldparam record [Object] each matching record
|
|
59
64
|
# @return [Enumerator] if no block given
|
|
60
65
|
# @return [void] if block given
|
|
61
66
|
def fast
|
|
67
|
+
warn('Deprecated: Since C extension has implemented, the fast mode is no longer needed. Use C extension instead.')
|
|
62
68
|
return to_enum(:fast) unless block_given?
|
|
63
69
|
|
|
64
70
|
@context.need_convert = false
|
data/lib/mongory/version.rb
CHANGED
data/lib/mongory.rb
CHANGED
|
@@ -118,7 +118,7 @@ end
|
|
|
118
118
|
|
|
119
119
|
begin
|
|
120
120
|
abi = RUBY_VERSION.split('.').first(2).join('.')
|
|
121
|
-
|
|
121
|
+
require_relative "core/#{abi}/mongory_ext"
|
|
122
122
|
require_relative 'mongory/c_query_builder'
|
|
123
123
|
require_relative 'mongory/c_matcher'
|
|
124
124
|
rescue LoadError => e
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mongory
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: x86_64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- koten0224
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-11-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A Mongo-like in-memory query DSL for Ruby
|
|
14
14
|
email:
|
|
@@ -84,6 +84,7 @@ files:
|
|
|
84
84
|
- lib/core/3.2/mongory_ext.so
|
|
85
85
|
- lib/core/3.3/mongory_ext.so
|
|
86
86
|
- lib/core/3.4/mongory_ext.so
|
|
87
|
+
- lib/core/4.0/mongory_ext.so
|
|
87
88
|
- lib/generators/mongory/install/install_generator.rb
|
|
88
89
|
- lib/generators/mongory/install/templates/initializer.rb.erb
|
|
89
90
|
- lib/generators/mongory/matcher/matcher_generator.rb
|