- Improved addIndex
[activemongo.git] / tests / QueryTest.php
blobfd23db667a68190aaa9bf42957fb4075658b99a3
1 <?php
3 class QueryTest extends PHPUnit_Framework_TestCase
6 function testConnect()
8 ActiveMongo::connect(DB, "localhost");
9 try {
10 Dummy::drop();
11 } catch (ActiveMongo_Exception $e) {}
12 try {
13 Model1::drop();
14 } catch (ActiveMongo_Exception $e) {}
15 try {
16 Model2::drop();
17 } catch (ActiveMongo_Exception $e) {}
18 try {
19 Model3::drop();
20 } catch (ActiveMongo_Exception $e) {}
21 $this->assertTrue(TRUE);
24 function testBulkInserts()
26 try {
27 Model3::drop();
28 } catch (ActiveMongo_Exception $e) {}
29 $data = array();
31 /* Valid data */
32 for ($i=0; $i < 5000; $i++) {
33 $data[] = array('int' => $i, 'str' => sha1(uniqid()));
36 /* Invalid data, shouldn't be inserted */
37 $data[] = array('xint' => $i, 'str' => sha1(uniqid()));
38 $data[] = array('xint' => $i, 'str' => sha1(uniqid()));
39 $data[] = array('xint' => $i, 'str' => sha1(uniqid()));
41 /* batchInsert */
42 Model3::batchInsert($data, TRUE, TRUE);
44 $c = new Model3;
45 $this->assertEquals($c->count(), 5000);
48 function testInstall()
50 ActiveMongo::install();
51 $index = Model1::getIndexes();
52 $this->assertTrue(isset($index[1]['key']['b']));
53 $this->assertTrue(isset($index[2]['key']['a']));
54 $this->assertEquals($index[1]['key']['b'], 1);
55 $this->assertEquals($index[2]['key']['a'], -1);
56 $this->asserTEquals(count($index), 3);
57 $index = Model2::getIndexes();
58 $this->assertTrue(isset($index[1]['key']['M1']));
59 $this->assertEquals($index[1]['key']['M1'], 1);
60 $this->asserTEquals(count($index), 2);
63 /**
64 * @depends testBulkInserts
66 function testReset()
68 $c = new Model3;
69 $c->doQuery();
71 $this->assertTrue(isset($c->int));
72 $this->assertTrue(isset($c['int']));
73 $c->reset();
74 $this->assertFalse(isset($c->int));
75 $this->assertFalse(isset($c['int']));
78 /**
79 * @depends testBulkInserts
81 function testModQuery()
83 $c = new Model3;
84 /* int % 2 == */
85 $c->properties('int');
86 $c->where('int %', array(2, 0));
87 $this->assertLessThan($c->count(), 0);
88 foreach ($c as $r) {
89 $this->assertEquals($r->int % 2, 0);
93 function testQuery()
95 $c = new Model1;
97 /* rand values */
98 $val1 = rand(1, 50);
99 $val2 = rand(1, 50);
100 $val3 = rand(1, 50);
101 $val4 = rand(1, 50);
102 $val5 = rand(1, 50);
105 /* prepare the query */
106 $c->properties('a,b')->where('a >', $val1)->where('b <', $val2)->where('c !=', $val3);
107 $c->where('h regexp', '/[a-f0-9]+/');
108 $c->where('x in', array(1, 2));
109 $c->where('x nin', array(4));
110 $c->where('y ==', array(4));
111 $c->where('f exists');
112 $c->where('f !=', array(5,6));
113 $c->where(array("bar exists", "a exists"));
114 $c->where('xxx ==', 5);
115 $c->where('bar >=', 5);
116 $c->sort('c DESC, a ASC')->limit($val4, $val5);
118 /* perform it */
119 $c->doQuery();
121 /* Get cursor info */
122 $sQuery = $c->getReference(TRUE);
124 /* expected cursor info */
125 $eQuery = array(
126 'ns' => DB.'.model1',
127 'limit' => $val4,
128 'skip' => $val5,
129 'query' => array(
130 '$query' => array(
131 'a' => array('$gt' => $val1, '$exists' => 1),
132 'b' => array('$lt' => $val2),
133 'c' => array('$ne' => $val3),
134 'h' => new MongoRegex('/[a-f0-9]+/'),
135 'x' => array('$in' => array(1,2), '$nin' => array(4)),
136 'y' => array('$all' => array(4)),
137 'f' => array('$exists' => 1, '$nin' => array(5,6)),
138 'xxx' => 5,
139 'bar' => array('$exists' => 1, '$gte' => 5),
141 '$orderby' => array(
142 'c' => -1,
143 'a' => 1,
146 'fields' => array(
147 'a' => 1,
148 'b' => 1,
149 '_id' => 1, /* from now on _id is included by default */
153 $this->assertEquals($sQuery['dynamic'], $eQuery);
157 function testQueryArray()
159 $c = new Model1;
161 /* rand values */
162 $val1 = rand(1, 50);
163 $val2 = rand(1, 50);
164 $val3 = rand(1, 50);
165 $val4 = rand(1, 50);
166 $val5 = rand(1, 50);
169 /* prepare the query */
170 $filter = array(
171 'a > ' => $val1,
172 'b < ' => $val2,
173 'c != ' => $val3,
174 'h regexp' => '/[a-f0-9]+/',
175 'x in ' => array(1,2),
176 'x nin ' => array(4),
177 'y == ' => array(4)
179 $c->properties('a,b')->sort('c DESC, a ASC')->limit($val4, $val5);;
180 $c->where($filter);
182 /* perform it */
183 $c->doQuery();
185 /* Get cursor info */
186 $sQuery = $c->getReference(TRUE);
188 /* expected cursor info */
189 $eQuery = array(
190 'ns' => DB.'.model1',
191 'limit' => $val4,
192 'skip' => $val5,
193 'query' => array(
194 '$query' => array(
195 'a' => array('$gt' => $val1),
196 'b' => array('$lt' => $val2),
197 'c' => array('$ne' => $val3),
198 'h' => new MongoRegex('/[a-f0-9]+/'),
199 'x' => array('$in' => array(1,2), '$nin' => array(4)),
200 'y' => array('$all' => array(4)),
202 '$orderby' => array(
203 'c' => -1,
204 'a' => 1,
207 'fields' => array(
208 'a' => 1,
209 'b' => 1,
210 '_id' => 1,
214 $this->assertEquals($sQuery['dynamic'], $eQuery);
217 function testQueryRequireArray()
219 $c = new Model1;
220 try {
221 $c->where('c near', 'string');
222 $this->assertTrue(FALSE);
223 } catch (ActiveMongo_Exception $e) {
224 $this->assertTrue(TRUE);
226 try {
227 $c->where('c in', 55);
228 $this->assertTrue(FALSE);
229 } catch (ActiveMongo_Exception $e) {
230 $this->assertTrue(TRUE);
232 try {
233 $c->where('c >', array(1));
234 $this->assertTrue(FALSE);
235 } catch (ActiveMongo_Exception $e) {
236 $this->assertTrue(TRUE);
238 try {
239 $c->where('c >>>', array(1));
240 $this->assertTrue(FALSE);
241 } catch (ActiveMongo_Exception $e) {
242 $this->assertTrue(TRUE);
244 try {
245 $c->where('c nin', 559);
246 $this->assertTrue(FALSE);
247 } catch (ActiveMongo_Exception $e) {
248 $this->assertTrue(TRUE);
252 function testMultipleOperationsPerProperty()
254 list($min, $max) = array(50, 100);
256 $c = new Model3;
257 foreach ($c->where('int >', $min)->where('int <', $max) as $item) {
258 $this->assertGreaterThan($min, $item['int']);
259 $this->assertLessThan($max, $item['int']);
262 /* this could be done with a single regexp but
263 * this test should cover the multiple ALL amoung
264 * properties
266 * str regexp '//' AND str regexp '//' AND str regexp '//'
268 $c = new Model3;
269 $c->where('str regex', '/^4/')->where('str regexp', '/a$/');
270 foreach ($c->where('str regex', '/[a-z0-9]+/') as $item) {
271 $this->assertEquals($item['str'][0], 4);
272 $this->assertEquals($item['str'][strlen($item['str'])-1], 'a');
276 $c = new Model3;
277 $c->where('int >', $min)->where('int <', $max);
278 foreach ($c->where('int nin', array($min+1, $min+2, $min+3)) as $item) {
279 $this->assertNotEquals($min+1, $item['int']);
280 $this->assertNotEquals($min+2, $item['int']);
281 $this->assertNotEquals($min+3, $item['int']);
285 function testMultipleUpdate()
287 $str = sha1(uniqid());
288 $query = array(
289 'int >' => 5,
290 'int <' => 30,
291 'int !=' => 6,
293 $c = new Model3;
294 $c->where($query);
295 $c->update(array('newproperty' => $str));
297 $c->where(array('int >' => 5, 'int <' => 30));
298 foreach ($c as $item) {
299 if ($item['int'] == 6) {
300 /* 6 is not included */
301 $this->assertFalse(isset($item['newproperty']));
302 } else {
303 $this->assertEquals($str, $item['newproperty']);
308 function testNullUpdate()
310 $id = 0;
313 $c = new Model3;
314 $c->int = 5;
315 $c->arr = array(5, array(1));
316 $c->bool = TRUE;
317 $c->null = NULL;
319 /* Testing Save also :-) */
320 $this->assertEquals(TRUE, $c->save());
321 /* Now nothing should be done */
322 $this->assertEquals(NULL, $c->save());
324 $c->int = 0;
325 $c->arr[] = 0;
326 $c->arr[1][] = 1;
327 $c->arr[1][] = 2;
328 $c->arr[1][] = 3;
329 $c->bool = FALSE;
330 $c->foobar = NULL;
331 $id = $c->getId();
333 /* Updating */
334 $this->assertEquals(TRUE, $c->save());
335 $this->assertEquals(NULL, $c->save());
337 unset($c->arr[1][1]);
338 unset($c->foobar);
340 /* Updating */
341 $this->assertEquals(TRUE, $c->save());
342 $this->assertEquals(NULL, $c->save());
345 /* now empty $c and query for `int` value */
346 $c->reset();
347 $c->where('_id', $id);
348 $c->doQuery();
349 $this->assertEquals($c->int, 0);
350 $this->assertEquals($c->arr, array(5,array(1,NULL, 2,3), 0));
351 $this->assertEquals($c->bool, FALSE);
352 $this->assertEquals($c->null, NULL);
355 function testOnQueryModifyError()
357 try {
358 $c = new Model1;
359 $c->where('a', 1);
360 $c->doQuery();
361 $c->where('b', 4);
362 $this->assertTrue(FALSE);
363 } catch (ActiveMongo_Exception $e) {
364 $this->assertTrue(TRUE);
369 * @depends testBulkInserts
371 function testClone()
373 $c = new Model1;
374 $c->a = 1;
375 $c->save();
377 $c->reset();
379 /* object with no results can't be cloned */
380 try {
381 $foo = clone $c;
382 $this->AssertTrue(FALSE);
383 } catch (ActiveMongo_Exception $e) {
384 $this->AssertTrue(TRUE);
387 foreach ($c as $item) {
388 $item_cloned = clone $item;
389 $item_cloned->c = 1;
390 $item_cloned->save();
391 try {
392 /* iterations are forbidden in cloned objects */
393 foreach ($item_cloned as $nitem) {
394 $this->assertTrue(FALSE);
396 } catch (ActiveMongo_Exception $e) {
397 $this->assertTrue(TRUE);
401 /* cloned object can't be reused */
402 try {
403 $item_cloned->reset();
404 $this->AssertTrue(FALSE);
405 } catch (ActiveMongo_Exception $e) {
406 $this->AssertTrue(TRUE);
408 try {
409 $item_cloned->where('a IN', array(1));
410 $this->AssertTrue(FALSE);
411 } catch (ActiveMongo_Exception $e) {
412 $this->AssertTrue(TRUE);
417 function testToSTring()
419 $c = new Model3;
420 $c->doQuery();
421 $this->assertEquals((string)$c, (string)$c->getID());
422 $this->assertEquals((string)$c, $c->key());
425 function testDelete()
427 /* Delete using a criteria */
428 $c = new Model3;
429 $c->where('int < ', 100);
430 $c->delete();
432 $this->assertEquals($c->count(), 4900);
434 /* delete on iteration (element by element) */
435 $c = new Model3;
436 $c->where('int', array(200, 300));
438 $i = 0;
439 foreach ($c as $d) {
440 $d->delete();
441 $this->assertFalse(isset($c->int));
442 $i++;
445 $c->reset();
447 $this->assertEquals(2, $i);
448 $this->assertEquals($c->count(), 4898);
451 function testDrop()
453 $c = new Dummy;
454 $c['foo'] = 'bar';
455 $c->save();
457 $this->assertFalse(ActiveMongo::drop());
458 $this->assertTrue(Dummy::drop());
459 try {
460 $this->assertFalse(Dummy::drop());
461 } catch (ActiveMongo_Exception $e) {
462 $this->assertTrue(TRUE);
466 function testInvalidLimits()
468 $c = new Model1;
469 $this->assertFalse($c->limit(-1, 5));
470 $this->assertFalse($c->limit(5, -1));
471 $this->assertFalse($c->limit(-1, -5));
474 function testInvalidProperties()
476 $c = new Model1;
477 $this->assertFalse($c->properties(1));
478 $this->assertFalse($c->columns(1));
479 $this->assertFalse($c->columns(NULL));
480 $this->assertFalse($c->columns(TRUE));
484 function testInvalidBatchInsert()
486 /* Invalid document for Model2 */
487 $documents = array(
488 array('foo' => 'bar'),
490 try {
491 /* Invalid call */
492 ActiveMongo::BatchInsert($documents);
493 $this->assertTrue(False);
494 } catch (ActiveMongo_Exception $e) {
495 $this->assertTrue(TRUE);
498 try {
499 Model2::BatchInsert($documents);
500 $this->assertTrue(False);
501 } catch (ActiveMongo_FilterException $e) {
502 $this->assertTrue(FALSE);
503 } catch (MongoException $e) {
504 $this->assertTrue(TRUE);
507 try {
508 Model2::BatchInsert($documents, TRUE, FALSE);
509 $this->assertTrue(False);
510 } catch (ActiveMongo_FilterException $e) {
511 $this->assertTrue(TRUE);
516 function testInvalidQueries()
518 $c = new Model3;
520 try {
521 $c->where("invalid field property", 3);
522 $this->assertTrue(FALSE);
523 } catch (ActiveMongo_Exception $e) {
524 $this->assertTrue(TRUE);
527 try {
528 $c->where(array(
529 "b" => 1,
530 ), TRUE);
531 $this->assertTrue(FALSE);
532 } catch (ActiveMongo_Exception $e) {
533 $this->assertTrue(TRUE);
537 try {
538 $c->sort(" , , ");
539 $this->assertTrue(FALSE);
540 } catch (ActiveMongo_Exception $e) {
541 $this->assertTrue(TRUE);
544 try {
545 $c->sort("c DESC, field BAR");
546 $this->assertTrue(FALSE);
547 } catch (ActiveMongo_Exception $e) {
548 $this->assertTrue(TRUE);
551 /* These are valid, so no exception should be thrown */
552 $c->sort("foo ASC, bar DESC");
553 $c->sort("foo DESC");
554 $c->sort("foo");
557 function testFindWithSingleID()
559 $d = new Model1;
560 $d->a = 5;
561 $d->save();
563 $c = new Model1;
564 $c->find($d->getID());
565 $this->assertEquals(1, $c->count());
566 $this->assertEquals($c->a, $d->a);
569 function testFindAndModify()
572 $c = new Model3;
573 $c->where('int <= ', 1000);
574 $c->where('processing exists', FALSE);
575 $c->limit(50);
576 $c->sort('int DESC');
577 $c->findAndModify(array("processing" => TRUE));
579 $i = 0;
580 $last = 0;
581 foreach ($c as $d) {
582 $this->assertEquals($d->processing, TRUE);
583 /* testing sort */
584 if ($last) {
585 $this->assertLessThan($last, $d->int);
587 $last = $d->int;
588 $i++;
590 $this->assertEquals($i, 50);
592 try {
593 $c->reset();
594 $c->where('int <= ', 1000);
595 $c->where('processing exists', FALSE);
596 $c->limit(50);
597 $c->findAndModify(array());
598 $this->assertTrue(FALSE);
599 } catch (ActiveMongo_Exception $e) {
600 $this->assertTrue(TRUE);