Browse Source

Add KeyValueRegex query (-r)

Johannes Hofmann 7 years ago
parent
commit
d21337af83
4 changed files with 152 additions and 14 deletions
  1. 8
    0
      src/args.rs
  2. 46
    14
      src/config.rs
  3. 95
    0
      src/query.rs
  4. 3
    0
      src/search.rs

+ 8
- 0
src/args.rs View File

42
             .multiple(true)
42
             .multiple(true)
43
             .help("Search for places that are tagged with the given key and value")
43
             .help("Search for places that are tagged with the given key and value")
44
             .takes_value(true))
44
             .takes_value(true))
45
+        .arg(Arg::with_name("keyvalregex")
46
+            .short("r")
47
+            .long("keyvalregex")
48
+            .value_names(&["KEY", "REGEX"])
49
+            .number_of_values(2)
50
+            .multiple(true)
51
+            .help("Search for places that are tagged with the given key and a value that matches the given regex")
52
+            .takes_value(true))
45
         .arg(Arg::with_name("fps")
53
         .arg(Arg::with_name("fps")
46
             .long("fps")
54
             .long("fps")
47
             .value_name("FPS")
55
             .value_name("FPS")

+ 46
- 14
src/config.rs View File

30
     pbf_path: Option<PathBuf>,
30
     pbf_path: Option<PathBuf>,
31
     search_pattern: Option<String>,
31
     search_pattern: Option<String>,
32
     keyval: Vec<(String, String)>,
32
     keyval: Vec<(String, String)>,
33
+    keyvalregex: Vec<(String, String)>,
33
     fps: f64,
34
     fps: f64,
34
     use_network: bool,
35
     use_network: bool,
35
     async: bool,
36
     async: bool,
84
             },
85
             },
85
         );
86
         );
86
 
87
 
88
+        self.keyvalregex = matches.values_of("keyvalregex").map_or_else(
89
+            || vec![],
90
+            |mut kv| {
91
+                let mut vec = vec![];
92
+                loop {
93
+                    if let (Some(k), Some(v)) = (kv.next(), kv.next()) {
94
+                        vec.push((k.to_string(), v.to_string()));
95
+                    } else {
96
+                        break;
97
+                    }
98
+                }
99
+                vec
100
+            },
101
+        );
102
+
87
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
103
         if let Some(Ok(fps)) = matches.value_of("fps").map(|s| s.parse()) {
88
             self.fps = fps;
104
             self.fps = fps;
89
         }
105
         }
247
                         pbf_path,
263
                         pbf_path,
248
                         search_pattern: None,
264
                         search_pattern: None,
249
                         keyval: vec![],
265
                         keyval: vec![],
266
+                        keyvalregex: vec![],
250
                         fps,
267
                         fps,
251
                         use_network,
268
                         use_network,
252
                         async,
269
                         async,
412
         self.keyval.as_slice()
429
         self.keyval.as_slice()
413
     }
430
     }
414
 
431
 
432
+    pub fn keyvalregex(&self) -> &[(String, String)] {
433
+        self.keyvalregex.as_slice()
434
+    }
435
+
415
     pub fn query_args(&self) -> Option<QueryArgs> {
436
     pub fn query_args(&self) -> Option<QueryArgs> {
416
-        match (&self.search_pattern, self.keyval.len()) {
417
-            (&Some(ref pattern), 0) => Some(QueryArgs::ValuePattern(pattern.to_string())),
418
-            (&None, 1) => Some(
419
-                QueryArgs::KeyValue(self.keyval[0].0.to_string(), self.keyval[0].1.to_string())
437
+        match (&self.search_pattern, self.keyval.first(), self.keyvalregex.first()) {
438
+            (&Some(ref pattern), None, None) => Some(
439
+                QueryArgs::ValuePattern(pattern.to_string())
440
+            ),
441
+            (&None, Some(keyval), None) => Some(
442
+                QueryArgs::KeyValue(keyval.0.to_string(), keyval.1.to_string())
420
             ),
443
             ),
421
-            (&Some(ref pattern), _) => {
422
-                let mut vec = vec![QueryArgs::ValuePattern(pattern.to_string())];
444
+            (&None, None, Some(keyvalregex)) => Some(
445
+                QueryArgs::KeyValueRegex(keyvalregex.0.to_string(), keyvalregex.1.to_string())
446
+            ),
447
+            (pattern_opt, _, _) => {
448
+                let mut vec = vec![];
449
+
450
+                if let Some(ref pattern) = pattern_opt {
451
+                    vec.push(QueryArgs::ValuePattern(pattern.to_string()));
452
+                }
423
 
453
 
424
                 for (k, v) in &self.keyval {
454
                 for (k, v) in &self.keyval {
425
                     vec.push(QueryArgs::KeyValue(k.to_string(), v.to_string()));
455
                     vec.push(QueryArgs::KeyValue(k.to_string(), v.to_string()));
426
                 }
456
                 }
427
-                Some(QueryArgs::Intersection(vec))
428
-            },
429
-            (&None, x) if x > 0 => {
430
-                let mut vec = self.keyval.iter()
431
-                    .map(|&(ref k, ref v)| QueryArgs::KeyValue(k.to_string(), v.to_string()))
432
-                    .collect();
433
-                Some(QueryArgs::Intersection(vec))
457
+
458
+                for (k, v) in &self.keyvalregex {
459
+                    vec.push(QueryArgs::KeyValueRegex(k.to_string(), v.to_string()));
460
+                }
461
+
462
+                if vec.is_empty() {
463
+                    None
464
+                } else {
465
+                    Some(QueryArgs::Intersection(vec))
466
+                }
434
             },
467
             },
435
-            (&None, _) => None,
436
         }
468
         }
437
     }
469
     }
438
 
470
 

+ 95
- 0
src/query.rs View File

18
 pub enum QueryArgs {
18
 pub enum QueryArgs {
19
     ValuePattern(String),
19
     ValuePattern(String),
20
     KeyValue(String, String),
20
     KeyValue(String, String),
21
+    KeyValueRegex(String, String),
21
     Intersection(Vec<QueryArgs>),
22
     Intersection(Vec<QueryArgs>),
22
 }
23
 }
23
 
24
 
25
 pub enum QueryKind {
26
 pub enum QueryKind {
26
     ValuePattern(ValuePatternQuery),
27
     ValuePattern(ValuePatternQuery),
27
     KeyValue(KeyValueQuery),
28
     KeyValue(KeyValueQuery),
29
+    KeyValueRegex(KeyValueRegexQuery),
28
     Intersection(Vec<QueryKind>),
30
     Intersection(Vec<QueryKind>),
29
 }
31
 }
30
 
32
 
37
             QueryArgs::KeyValue(k, v) => {
39
             QueryArgs::KeyValue(k, v) => {
38
                 Ok(QueryKind::KeyValue(KeyValueQuery::new(k, v)))
40
                 Ok(QueryKind::KeyValue(KeyValueQuery::new(k, v)))
39
             },
41
             },
42
+            QueryArgs::KeyValueRegex(k, v) => {
43
+                Ok(QueryKind::KeyValueRegex(KeyValueRegexQuery::new(k, &v)?))
44
+            },
40
             QueryArgs::Intersection(queries) => {
45
             QueryArgs::Intersection(queries) => {
41
                 let mut subqueries = Vec::with_capacity(queries.len());
46
                 let mut subqueries = Vec::with_capacity(queries.len());
42
                 for q in queries {
47
                 for q in queries {
191
     }
196
     }
192
 }
197
 }
193
 
198
 
199
+#[derive(Debug)]
200
+pub struct KeyValueRegexQuery {
201
+    key: String,
202
+    value_re: Regex,
203
+}
204
+
205
+impl KeyValueRegexQuery {
206
+    pub fn new<S: Into<String>>(key: S, value_pattern: &str) -> Result<Self, String> {
207
+        let value_re = Regex::new(value_pattern)
208
+            .map_err(|e| format!("{}", e))?;
209
+        Ok(KeyValueRegexQuery {
210
+            key: key.into(),
211
+            value_re,
212
+        })
213
+    }
214
+}
215
+
216
+impl Query for KeyValueRegexQuery {
217
+    type BI = (Vec<u32>, Vec<u32>);
218
+
219
+    fn create_block_index(&self, block: &PrimitiveBlock) -> Option<(Vec<u32>, Vec<u32>)> {
220
+        let mut key_indices = vec![];
221
+        let mut value_indices = vec![];
222
+
223
+        let key_bytes = self.key.as_bytes();
224
+
225
+        for (i, string) in block.raw_stringtable().iter().enumerate() {
226
+            if string.as_slice() == key_bytes {
227
+                key_indices.push(i as u32);
228
+            }
229
+
230
+            if let Ok(s) = ::std::str::from_utf8(string) {
231
+                if self.value_re.is_match(s) {
232
+                    value_indices.push(i as u32);
233
+                }
234
+            }
235
+        }
236
+
237
+        if key_indices.is_empty() || value_indices.is_empty() {
238
+            // No matches possible for this block
239
+            return None;
240
+        }
241
+
242
+        key_indices.sort();
243
+        value_indices.sort();
244
+
245
+        Some((key_indices, value_indices))
246
+    }
247
+
248
+    fn node_matches(&self, bi: &Self::BI, node: &Node) -> bool {
249
+        for (key, val) in node.raw_tags() {
250
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
251
+                return true;
252
+            }
253
+        }
254
+        return false;
255
+    }
256
+
257
+    fn dense_node_matches(&self, bi: &Self::BI, dnode: &DenseNode) -> bool {
258
+        for (key, val) in dnode.raw_tags() {
259
+            if key >= 0 &&
260
+               val >= 0 &&
261
+               bi.0.binary_search(&(key as u32)).is_ok() &&
262
+               bi.1.binary_search(&(val as u32)).is_ok()
263
+            {
264
+                return true;
265
+            }
266
+        }
267
+        return false;
268
+    }
269
+
270
+    fn way_matches(&self, bi: &Self::BI, way: &Way) -> bool {
271
+        for (key, val) in way.raw_tags() {
272
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
273
+                return true;
274
+            }
275
+        }
276
+        return false;
277
+    }
278
+
279
+    fn relation_matches(&self, bi: &Self::BI, relation: &Relation) -> bool {
280
+        for (key, val) in relation.raw_tags() {
281
+            if bi.0.binary_search(&key).is_ok() && bi.1.binary_search(&val).is_ok() {
282
+                return true;
283
+            }
284
+        }
285
+        return false;
286
+    }
287
+}
288
+
194
 pub fn find_query_matches<Q: Query>(
289
 pub fn find_query_matches<Q: Query>(
195
     block: &PrimitiveBlock,
290
     block: &PrimitiveBlock,
196
     query: &Q,
291
     query: &Q,

+ 3
- 0
src/search.rs View File

96
         &QueryKind::KeyValue(ref query) => {
96
         &QueryKind::KeyValue(ref query) => {
97
             find_query_matches(block, query, &mut matches, &mut way_node_ids);
97
             find_query_matches(block, query, &mut matches, &mut way_node_ids);
98
         },
98
         },
99
+        &QueryKind::KeyValueRegex(ref query) => {
100
+            find_query_matches(block, query, &mut matches, &mut way_node_ids);
101
+        },
99
         &QueryKind::Intersection(ref queries) => {
102
         &QueryKind::Intersection(ref queries) => {
100
             let mut q_iter = queries.iter();
103
             let mut q_iter = queries.iter();
101
 
104