mongolitedb 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1c4ba47f1829ac304ccd6b11f7ef4ea97e06b4c1
4
- data.tar.gz: 020c5c5191f247972874ac9f4c474e4ca7272ed8
3
+ metadata.gz: 61d2c498c08966845f3e8d5ac13c8858599f831b
4
+ data.tar.gz: 514b684b4a2c21f75437f68bdf1b39b7cb8baea0
5
5
  SHA512:
6
- metadata.gz: c7012586e2c0a364f5952de9c9e932fe01fd9c183f951eeb6807295cf718c92af3143527a5a2d30c0a504788727ac370b0463213bd73393342ca094d82fcba74
7
- data.tar.gz: cd39d1355be855655dde02048e8523017c658067e90d4719cc29f5866850b2118eb754d34e3bb78255e9747dd52d98c5ddfdb6a1d877209284ef7b9130487722
6
+ metadata.gz: f89e5e7be09e0992104210f61c7eb3340f23b1628422075f4973a510e29a4c5b5e524eff969363ab50c44c3a5bcf63d71135dd612e4e18c3cd9f4932f82f3b9c
7
+ data.tar.gz: c5a076ba07eb8f8a2d77da70ef8f7b8f55ae05d898ad89371084981bb90638fdf3d23c437cfb75f416638893703b467bd86715c70b1d68f43047bd9673b7abc0
data/lib/matcher.rb ADDED
@@ -0,0 +1,87 @@
1
+ require 'predicate_matcher'
2
+
3
+ class Matcher
4
+ def initialize(query)
5
+ @query = query
6
+ end
7
+
8
+ def match(obj)
9
+ if @query.length > 1
10
+ # We always have an implied $and for multiple entries
11
+ matcher = AndMatcher.new({"$and" => @query.map{|k,v| {k => v}}})
12
+ elsif @query.length == 0
13
+ matcher = EmptyMatcher.new(@query)
14
+ else
15
+ # we only have one entry
16
+ case @query.keys.first
17
+ when "$or"
18
+ matcher = OrMatcher.new(@query)
19
+ when "$nor"
20
+ matcher = NorMatcher.new(@query)
21
+ when "$and"
22
+ matcher = AndMatcher.new(@query)
23
+ else
24
+ matcher = AttrMatcher.new(@query)
25
+ end
26
+ end
27
+ return matcher.match(obj)
28
+ end
29
+ end
30
+
31
+ class AttrMatcher < Matcher
32
+ def match(obj)
33
+ attribute = @query.keys.first
34
+ if attribute.include?(".")
35
+ value = obj
36
+ attribute.split(".").each do |attr|
37
+ value = value[attr]
38
+ if value.nil?
39
+ return false
40
+ end
41
+ end
42
+ else
43
+ value = obj[@query.keys.first]
44
+ end
45
+ predicate = @query.values.first
46
+ if predicate.kind_of? Hash
47
+ matcher = PredicateMatcher.new(predicate)
48
+ return matcher.match(value)
49
+ else
50
+ return value == predicate
51
+ end
52
+ end
53
+ end
54
+
55
+ class AndMatcher < Matcher
56
+ def match(obj)
57
+ does_it_match = true
58
+ @query.values.first.each do |subquery|
59
+ matcher = Matcher.new(subquery)
60
+ does_it_match &&= matcher.match(obj)
61
+ end
62
+ return does_it_match
63
+ end
64
+ end
65
+
66
+ class EmptyMatcher < Matcher
67
+ def match(obj)
68
+ true
69
+ end
70
+ end
71
+
72
+ class OrMatcher < Matcher
73
+ def match(obj)
74
+ does_it_match = false
75
+ @query.values.first.each do |subquery|
76
+ matcher = Matcher.new(subquery)
77
+ does_it_match ||= matcher.match(obj)
78
+ end
79
+ return does_it_match
80
+ end
81
+ end
82
+
83
+ class NorMatcher < Matcher
84
+ def match(obj)
85
+ return !OrMatcher.new(@query).match(obj)
86
+ end
87
+ end
data/lib/mongolitedb.rb CHANGED
@@ -1,160 +1,92 @@
1
1
  require 'json'
2
+ require 'matcher'
2
3
 
3
4
  class MongoLiteDB
4
- def initialize(filename="db.nsl")
5
- @filename = filename
6
- if not File.exists?(@filename)
7
- open(@filename, 'w'){|f| f.write(
8
- {
9
- "max_index" => 0,
10
- "objects" => []
11
- }.to_json
12
- )}
13
- end
5
+ def initialize(filename="db.nsl")
6
+ @filename = filename
7
+ if not File.exists?(@filename)
8
+ open(@filename, 'w'){|f| f.write(
9
+ {
10
+ "max_index" => 0,
11
+ "objects" => []
12
+ }.to_json
13
+ )}
14
14
  end
15
- def insert(objects)
16
- if not objects.kind_of?(Array)
17
- objects = [objects]
18
- end
19
- write_to_disk do |db|
20
- objects.each do |object|
21
- object_copy = object.clone
22
- object_copy["id"] = db["max_index"]
23
- db["max_index"] += 1
24
- db["objects"] << object_copy
25
- end
26
- end
15
+ end
16
+ def insert(objects)
17
+ if not objects.kind_of?(Array)
18
+ objects = [objects]
27
19
  end
28
- def find(query)
29
- entries = []
30
- load_from_disk do |db|
31
- each_match(db, query) do |obj|
32
- entries << obj
33
- end
34
- end
35
- return entries
20
+ write_to_disk do |db|
21
+ objects.each do |object|
22
+ object_copy = object.clone
23
+ object_copy["id"] = db["max_index"]
24
+ db["max_index"] += 1
25
+ db["objects"] << object_copy
26
+ end
36
27
  end
37
-
38
- def update(query, attr)
39
- write_to_disk do |db|
40
- each_match(db, query) do |obj|
41
- obj.update(attr)
42
- end
43
- end
28
+ end
29
+ def find(query)
30
+ entries = []
31
+ load_from_disk do |db|
32
+ each_match(db, query) do |obj|
33
+ entries << obj
34
+ end
44
35
  end
45
- def delete(query)
46
- write_to_disk do |db|
47
- each_match(db, query) do |obj|
48
- db["objects"].delete(obj)
49
- end
50
- end
36
+ return entries
37
+ end
38
+ def update(query, attr)
39
+ write_to_disk do |db|
40
+ each_match(db, query) do |obj|
41
+ obj.update(attr)
42
+ end
43
+ end
44
+ end
45
+ def delete(query)
46
+ write_to_disk do |db|
47
+ each_match(db, query) do |obj|
48
+ db["objects"].delete(obj)
49
+ end
51
50
  end
51
+ end
52
52
 
53
- private
54
- def write_to_disk
55
- f = open(@filename, 'r+')
56
- f.flock(File::LOCK_EX)
57
- db = JSON.parse f.read
58
- yield db
59
- ensure
60
- if f
61
- if db
62
- f.rewind
63
- f.write db.to_json
64
- f.flush
65
- f.truncate f.pos
66
- end
67
- f.close
68
- end
53
+ private
54
+ def write_to_disk
55
+ f = open(@filename, 'r+')
56
+ f.flock(File::LOCK_EX)
57
+ db = JSON.parse f.read
58
+ yield db
59
+ ensure
60
+ if f
61
+ if db
62
+ f.rewind
63
+ f.write db.to_json
64
+ f.flush
65
+ f.truncate f.pos
66
+ end
67
+ f.close
69
68
  end
69
+ end
70
70
 
71
- def load_from_disk
72
- f = open(@filename, 'r+')
73
- f.flock(File::LOCK_SH)
74
- db = JSON.parse f.read
75
- yield db
76
- ensure
77
- if f
78
- f.close
79
- end
80
- end
71
+ def load_from_disk
72
+ f = open(@filename, 'r+')
73
+ f.flock(File::LOCK_SH)
74
+ db = JSON.parse f.read
75
+ yield db
76
+ ensure
77
+ if f
78
+ f.close
79
+ end
80
+ end
81
81
 
82
- def each_match(db, query)
83
- db["objects"].clone.each do |obj|
84
- yield(obj) unless not match(obj, query)
85
- end
82
+ def each_match(db, query)
83
+ db["objects"].clone.each do |obj|
84
+ yield(obj) unless not match(obj, query)
86
85
  end
86
+ end
87
87
 
88
- def match(obj, query)
89
- # query is either an array in the form of [key, value] or a hash
90
- # if query is an Array, key is a string, value can be anything
91
- # if value is an array, we should expect a keyword for key
92
- # if value is an hash, we should expect it's only key to be a keyword
93
- # if value is a string or FixNum , we should check for attribute match
94
- # if query is Hash, then we break it into individual queries and recursively call them (as arrays)
95
- if query.kind_of? Array
96
- if query[1].kind_of? Array
97
- case query[0]
98
- when "$or"
99
- match = false
100
- query[1].each do |attr|
101
- is_a_match = match(obj, attr)
102
- match ||= is_a_match
103
- end
104
- return match
105
- else
106
- raise NotImplementedError
107
- end
108
- elsif query[1].kind_of? Hash
109
- match = true
110
- query[1].each do |k,v|
111
- case k
112
- when "$in"
113
- local_match = false
114
- v.each do |value|
115
- is_a_match = match(obj, [query[0], value])
116
- local_match ||= is_a_match
117
- end
118
- match &&= local_match
119
- when "$exists"
120
- match &&= (not obj[query[0]].nil?) == v
121
- when "$nin"
122
- local_match = true
123
- v.each do |value|
124
- is_a_match = match(obj, [query[0], value])
125
- local_match &&= (not is_a_match)
126
- end
127
- match &&= local_match
128
- when "$gt"
129
- return obj[query[0]] > v
130
- when "$gte"
131
- return obj[query[0]] >= v
132
- when "$lt"
133
- return obj[query[0]] < v
134
- when "$lte"
135
- return obj[query[0]] <= v
136
- when "$ne"
137
- return obj[query[0]] != v
138
- when "$mod"
139
- return obj[query[0]] % v[0] == v[1]
140
- else
141
- raise NotImplementedError
142
- end
143
- end
144
- return match
145
- else
146
- match = (obj[query[0]] == query[1])
147
- return match
148
- end
149
- elsif query.kind_of? Hash
150
- match = true
151
- query.to_a.each do |attr|
152
- is_a_match = match(obj, attr)
153
- match &&= is_a_match
154
- end
155
- return match
156
- else
157
- raise NotImplementedError
158
- end
159
- end
88
+ def match(obj, query)
89
+ matcher = Matcher.new(query)
90
+ return matcher.match(obj)
91
+ end
160
92
  end
@@ -0,0 +1,45 @@
1
+ class PredicateMatcher
2
+ def initialize(predicate)
3
+ @predicate = predicate
4
+ end
5
+ def match(value)
6
+ if @predicate.length > 1
7
+ matcher = AndPredicateMatcher.new(@predicate)
8
+ return matcher.match(value)
9
+ end
10
+ case @predicate.keys.first
11
+ when "$exists"
12
+ return @predicate.values.first == !value.nil?
13
+ when "$in"
14
+ return @predicate.values.first.include?(value)
15
+ when "$nin"
16
+ return !@predicate.values.first.include?(value)
17
+ when "$gt"
18
+ return value > @predicate.values.first
19
+ when "$gte"
20
+ return value >= @predicate.values.first
21
+ when "$lt"
22
+ return value < @predicate.values.first
23
+ when "$lte"
24
+ return value <= @predicate.values.first
25
+ when "$ne"
26
+ return value != @predicate.values.first
27
+ when "$mod"
28
+ return value % @predicate.values.first[0] == @predicate.values.first[1]
29
+ else
30
+ raise NotImplementedError
31
+ end
32
+ end
33
+ end
34
+
35
+ class AndPredicateMatcher < PredicateMatcher
36
+ def match(value)
37
+ does_it_match = true
38
+ @predicate.each do |k,v|
39
+ matcher = PredicateMatcher.new({k => v})
40
+ does_it_match &&= matcher.match(value)
41
+ end
42
+ return does_it_match
43
+ end
44
+ end
45
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongolitedb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Hamilton
@@ -17,6 +17,8 @@ extensions: []
17
17
  extra_rdoc_files: []
18
18
  files:
19
19
  - lib/mongolitedb.rb
20
+ - lib/matcher.rb
21
+ - lib/predicate_matcher.rb
20
22
  homepage: https://github.com/hamiltop/MongoLiteDB
21
23
  licenses: []
22
24
  metadata: {}
@@ -36,7 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
36
38
  version: '0'
37
39
  requirements: []
38
40
  rubyforge_project:
39
- rubygems_version: 2.0.2
41
+ rubygems_version: 2.0.3
40
42
  signing_key:
41
43
  specification_version: 4
42
44
  summary: MongoLiteDB embedded database