コード例 #1
0
/* {{{ MongoCursor->explain
 */
PHP_METHOD(MongoCursor, explain) {
  int temp_limit;
  zval *explain, *yes;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  MONGO_METHOD(MongoCursor, reset, return_value, getThis());

  // make explain use a hard limit
  temp_limit = cursor->limit;
  if (cursor->limit > 0) {
    cursor->limit *= -1;
  }

  MAKE_STD_ZVAL(explain);
  ZVAL_STRING(explain, "$explain", 1);
  MAKE_STD_ZVAL(yes);
  ZVAL_TRUE(yes); 

  MONGO_METHOD2(MongoCursor, addOption, return_value, getThis(), explain, yes);

  zval_ptr_dtor(&explain);
  zval_ptr_dtor(&yes);

  MONGO_METHOD(MongoCursor, getNext, return_value, getThis());

  // reset to original limit
  cursor->limit = temp_limit;
}
コード例 #2
0
ファイル: cursor.c プロジェクト: crash783/mongo-php-driver
/* {{{ MongoCursor->explain
 */
PHP_METHOD(MongoCursor, explain) {
  int temp_limit;
  zval *explain, *yes, *temp = 0;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  MONGO_METHOD(MongoCursor, reset, return_value, getThis());

  // make explain use a hard limit
  temp_limit = cursor->limit;
  if (cursor->limit > 0) {
    cursor->limit *= -1;
  }

  MAKE_STD_ZVAL(explain);
  ZVAL_STRING(explain, "$explain", 1);
  MAKE_STD_ZVAL(yes);
  ZVAL_TRUE(yes);

  MONGO_METHOD2(MongoCursor, addOption, return_value, getThis(), explain, yes);

  zval_ptr_dtor(&explain);
  zval_ptr_dtor(&yes);

  MONGO_METHOD(MongoCursor, getNext, return_value, getThis());

  // reset cursor to original state
  cursor->limit = temp_limit;
  zend_hash_del(HASH_P(cursor->query), "$explain", strlen("$explain")+1);

  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);
  MONGO_METHOD(MongoCursor, reset, temp, getThis());
  zval_ptr_dtor(&temp);
}
コード例 #3
0
/* {{{ MongoCursor::getNext
 */
PHP_METHOD(MongoCursor, getNext) {
  MONGO_METHOD(MongoCursor, next)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  // will be null unless there was an error
  if (Z_TYPE_P(return_value) == IS_BOOL &&
      Z_BVAL_P(return_value) == 0) {
    return;
  }
  MONGO_METHOD(MongoCursor, current)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
コード例 #4
0
/* {{{ MongoCursor::getNext
 */
PHP_METHOD(MongoCursor, getNext) {
  MONGO_METHOD(MongoCursor, next, return_value, getThis());
  // will be null unless there was an error
  if (EG(exception) ||
      (Z_TYPE_P(return_value) == IS_BOOL && Z_BVAL_P(return_value) == 0)) {
    return;
  }
  MONGO_METHOD(MongoCursor, current, return_value, getThis());
}
コード例 #5
0
/* {{{ MongoCursor->explain
 */
PHP_METHOD(MongoCursor, explain) {
  zval *query;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  query = cursor->query;
  add_assoc_bool(query, "$explain", 1);

  MONGO_METHOD(MongoCursor, reset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  MONGO_METHOD(MongoCursor, getNext)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
コード例 #6
0
/* {{{ MongoCursor->next
 */
PHP_METHOD(MongoCursor, next) {
  zval has_next;
  mongo_cursor *cursor;

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  if (!cursor->started_iterating) {
    MONGO_METHOD(MongoCursor, doQuery)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
    cursor->started_iterating = 1;
  }

  // destroy old current
  if (cursor->current) {
    zval_ptr_dtor(&cursor->current);
    cursor->current = 0;
  }

  // check for results
  MONGO_METHOD(MongoCursor, hasNext)(0, &has_next, NULL, getThis(), 0 TSRMLS_CC);
  if (!Z_BVAL(has_next)) {
    // we're out of results
    RETURN_NULL();
  }

  // we got more results
  if (cursor->at < cursor->num) {
    zval **err;
    MAKE_STD_ZVAL(cursor->current);
    array_init(cursor->current);
    cursor->buf.pos = (unsigned char*)bson_to_zval((char*)cursor->buf.pos, Z_ARRVAL_P(cursor->current) TSRMLS_CC);

    // increment cursor position
    cursor->at++;

    // check for err
    if (cursor->num == 1 &&
        zend_hash_find(Z_ARRVAL_P(cursor->current), "$err", 5, (void**)&err) == SUCCESS) {
      zend_throw_exception(mongo_ce_CursorException, Z_STRVAL_PP(err), 0 TSRMLS_CC);
      RETURN_FALSE;
    }
  }

  RETURN_NULL();
}
コード例 #7
0
/* {{{ MongoCursor::hasNext
 */
PHP_METHOD(MongoCursor, hasNext) {
  mongo_msg_header header;
  buffer buf;
  int size;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  if (!cursor->started_iterating) {
    MONGO_METHOD(MongoCursor, doQuery)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
    cursor->started_iterating = 1;
  }

  if ((cursor->limit > 0 && cursor->at >= cursor->limit) || 
      cursor->num == 0) {
    RETURN_FALSE;
  }
  if (cursor->at < cursor->num) {
    RETURN_TRUE;
  }
  else if (cursor->cursor_id == 0) {
    RETURN_FALSE;
  }


  // we have to go and check with the db
  size = 34+strlen(cursor->ns);
  buf.start = (unsigned char*)emalloc(size);
  buf.pos = buf.start;
  buf.end = buf.start + size;

  CREATE_RESPONSE_HEADER(buf, cursor->ns, strlen(cursor->ns), cursor->header.request_id, OP_GET_MORE);
  serialize_int(&buf, cursor->limit);
  serialize_long(&buf, cursor->cursor_id);
  serialize_size(buf.start, &buf);

  // fails if we're out of elems
  if(mongo_say(cursor->link, &buf TSRMLS_CC) == FAILURE) {
    efree(buf.start);
    RETURN_FALSE;
  }

  efree(buf.start);

  // if we have cursor->at == cursor->num && recv fails,
  // we're probably just out of results
  RETURN_BOOL(get_reply(cursor TSRMLS_CC) == SUCCESS);
}
コード例 #8
0
ファイル: cursor.c プロジェクト: crash783/mongo-php-driver
/* {{{ MongoCursor->doQuery
 */
PHP_METHOD(MongoCursor, doQuery) {
  mongo_cursor *cursor;

  PHP_MONGO_GET_CURSOR(getThis());

  do {
    MONGO_METHOD(MongoCursor, reset, return_value, getThis());
    if (mongo_cursor__do_query(getThis(), return_value TSRMLS_CC) == SUCCESS ||
        EG(exception)) {
      return;
    }
  } while (mongo_cursor__should_retry(cursor));

  if (strcmp(".$cmd", cursor->ns+(strlen(cursor->ns)-5)) == 0) {
    mongo_cursor_throw(cursor->server, 19 TSRMLS_CC, "couldn't send command");
    return;
  }

  mongo_cursor_throw(cursor->server, 19 TSRMLS_CC, "max number of retries exhausted, couldn't send query");
}
コード例 #9
0
ファイル: db.cpp プロジェクト: 191919/hhvm
PHP_METHOD(MongoDB, dropCollection)
{
	zval *collection;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &collection) == FAILURE) {
		return;
	}

	if (Z_TYPE_P(collection) != IS_OBJECT || Z_OBJCE_P(collection) != mongo_ce_Collection) {
		zval *temp;

		MAKE_STD_ZVAL(temp);
		MONGO_METHOD1(MongoDB, selectCollection, temp, getThis(), collection);
		collection = temp;
	} else {
		zval_add_ref(&collection);
	}

	MONGO_METHOD(MongoCollection, drop, return_value, collection);

	zval_ptr_dtor(&collection);
}
コード例 #10
0
static int apply_to_cursor(zval *cursor, apply_copy_func_t apply_copy_func, void *to, int max TSRMLS_DC)
{
	int total = 0;
	zval *next;

	MAKE_STD_ZVAL(next);
	MONGO_METHOD(MongoCursor, getNext, next, cursor);

	if (EG(exception)) {
		return FAILURE;
	}
    
	if (Z_TYPE_P(next) != IS_ARRAY) {
		zval_ptr_dtor(&next);
		return FAILURE;
	}

	while (Z_TYPE_P(next) == IS_ARRAY) {
		zval **zdata;

		/* Check if data field exists. If it doesn't, we've probably got an
		 * error message from the db, so return that */
		if (zend_hash_find(HASH_P(next), "data", 5, (void**)&zdata) == FAILURE) {
			if (zend_hash_exists(HASH_P(next), "$err", 5)) {
				zval_ptr_dtor(&next);
				return FAILURE;
			}
			continue;
		}

		/* This copies the next chunk -> *to
		 * Due to a talent I have for not reading directions, older versions of
		 * the driver store files as raw bytes, not MongoBinData. So, we'll
		 * check for and handle both cases. */
		if (Z_TYPE_PP(zdata) == IS_STRING) {
			/* raw bytes */
			if (total + Z_STRLEN_PP(zdata) > max) {
				zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies");
				return FAILURE;
			}
			total += apply_copy_func(to, Z_STRVAL_PP(zdata), Z_STRLEN_PP(zdata));

		} else if (Z_TYPE_PP(zdata) == IS_OBJECT && Z_OBJCE_PP(zdata) == mongo_ce_BinData) {
			/* MongoBinData */
			zval *bin = zend_read_property(mongo_ce_BinData, *zdata, "bin", strlen("bin"), NOISY TSRMLS_CC);

			if (total + Z_STRLEN_P(bin) > max) {
				zval **n;

				if (zend_hash_find(HASH_P(next), "n", strlen("n") + 1, (void**)&n) == SUCCESS) {
					convert_to_long_ex(n);
					zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies (reading chunk %d)", Z_LVAL_PP(n));
				} else {
					zend_throw_exception_ex(mongo_ce_GridFSException, 1 TSRMLS_CC, "There is more data associated with this file than the metadata specifies");
				}
				zval_ptr_dtor(&next);

				return FAILURE;
			}
			total += apply_copy_func(to, Z_STRVAL_P(bin), Z_STRLEN_P(bin));

		} else {
			/* If it's not a string or a MongoBinData, give up */
			zval_ptr_dtor(&next);
			return FAILURE;
		}

		/* get ready for the next iteration */
		zval_ptr_dtor(&next);
		MAKE_STD_ZVAL(next);
		MONGO_METHOD(MongoCursor, getNext, next, cursor);
	}
	zval_ptr_dtor(&next);

	/* return the number of bytes copied */
	return total;
}
コード例 #11
0
/* {{{ proto MongoGridFSFile MongoGridFSCursor::getNext()
   Return the next file to which this cursor points, and advance the cursor */
PHP_METHOD(MongoGridFSCursor, getNext)
{
	MONGO_METHOD(MongoCursor, next, return_value, getThis());
	MONGO_METHOD(MongoGridFSCursor, current, return_value, getThis());
}
コード例 #12
0
/* {{{ MongoCursor->rewind
 */
PHP_METHOD(MongoCursor, rewind) {
  MONGO_METHOD(MongoCursor, reset, return_value, getThis());
  MONGO_METHOD(MongoCursor, next, return_value, getThis());
}
コード例 #13
0
/* {{{ MongoCursor->next
 */
PHP_METHOD(MongoCursor, next) {
  zval has_next;
  mongo_cursor *cursor;

  PHP_MONGO_GET_CURSOR(getThis());

  if (!cursor->started_iterating) {
    MONGO_METHOD(MongoCursor, doQuery, return_value, getThis());
    if (EG(exception)) {
      return;
    }
    cursor->started_iterating = 1;
  }

  // destroy old current
  if (cursor->current) {
    zval_ptr_dtor(&cursor->current);
    cursor->current = 0;
  }

  // check for results
  MONGO_METHOD(MongoCursor, hasNext, &has_next, getThis());
  if (EG(exception)) {
    return;
  }
  if (!Z_BVAL(has_next)) {
    // we're out of results
    RETURN_NULL();
  }

  // we got more results
  if (cursor->at < cursor->num) {
    zval **err;
    MAKE_STD_ZVAL(cursor->current);
    array_init(cursor->current);
    cursor->buf.pos = bson_to_zval((char*)cursor->buf.pos, Z_ARRVAL_P(cursor->current) TSRMLS_CC);

    if (EG(exception)) {
      zval_ptr_dtor(&cursor->current);
      cursor->current = 0;
      return;
    }

    // increment cursor position
    cursor->at++;

    // check for err
    if (cursor->num == 1 &&
        zend_hash_find(Z_ARRVAL_P(cursor->current), "$err", strlen("$err")+1, (void**)&err) == SUCCESS) {
      zval **code_z;
      // default error code
      int code = 4;
      
      if (zend_hash_find(Z_ARRVAL_P(cursor->current), "code", strlen("code")+1, (void**)&code_z) == SUCCESS) {
        // check for not master
        if (Z_TYPE_PP(code_z) == IS_LONG) {
          code = Z_LVAL_PP(code_z);
        }
        else if (Z_TYPE_PP(code_z) == IS_DOUBLE) {
          code = (int)Z_DVAL_PP(code_z);
        }
        // else code == 4
        
        // this shouldn't be necessary after 1.7.* is standard, it forces
        // failover in case the master steps down.
        // not master: 10107
        // not master and slaveok=false (more recent): 13435
        // not master or secondary: 13436
        if (cursor->link->rs && (code == 10107 || code == 13435 || code == 13436)) {
          php_mongo_disconnect_server(cursor->server);
        }
      }

      zend_throw_exception(mongo_ce_CursorException, Z_STRVAL_PP(err), code TSRMLS_CC);
      zval_ptr_dtor(&cursor->current);
      cursor->current = 0;
      RETURN_FALSE;
    }
  }

  RETURN_NULL();
}
コード例 #14
0
/* {{{ MongoCursor->__construct
 */
PHP_METHOD(MongoCursor, __construct) {
  zval *zlink = 0, *zns = 0, *zquery = 0, *zfields = 0, *empty, *timeout;
  zval **data;
  mongo_cursor *cursor;
  mongo_link *link;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Oz|zz", &zlink,
                            mongo_ce_Mongo, &zns, &zquery, &zfields) == FAILURE) {
    return;
  }
  if ((zquery && IS_SCALAR_P(zquery)) || (zfields && IS_SCALAR_P(zfields))) {
    zend_error(E_WARNING, "MongoCursor::__construct() expects parameters 3 and 4 to be arrays or objects");
    return;
  }

  // if query or fields weren't passed, make them default to an empty array
  MAKE_STD_ZVAL(empty);
  object_init(empty);

  // these are both initialized to the same zval, but that's okay because 
  // there's no way to change them without creating a new cursor
  if (!zquery || (Z_TYPE_P(zquery) == IS_ARRAY && zend_hash_num_elements(HASH_P(zquery)) == 0)) {
    zquery = empty;
  }
  if (!zfields) {
    zfields = empty;
  }

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
  // db connection
  cursor->resource = zlink;
  zval_add_ref(&zlink);

  // db connection resource
  PHP_MONGO_GET_LINK(zlink);
  cursor->link = link;

  // change ['x', 'y', 'z'] into {'x' : 1, 'y' : 1, 'z' : 1}
  if (Z_TYPE_P(zfields) == IS_ARRAY) {
    HashPosition pointer;
    zval *fields;

    MAKE_STD_ZVAL(fields);
    array_init(fields);

    // fields to return
    for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zfields), &pointer); 
        zend_hash_get_current_data_ex(Z_ARRVAL_P(zfields), (void**) &data, &pointer) == SUCCESS; 
        zend_hash_move_forward_ex(Z_ARRVAL_P(zfields), &pointer)) {
      int key_type, key_len;
      ulong index;
      char *key;
      
      key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zfields), &key, (uint*)&key_len, &index, NO_DUP, &pointer);

      if (key_type == HASH_KEY_IS_LONG) {
        if (Z_TYPE_PP(data) == IS_STRING) {
          add_assoc_long(fields, Z_STRVAL_PP(data), 1);
        }
        else {
          zval_ptr_dtor(&empty);
          zval_ptr_dtor(&fields);
          zend_throw_exception(mongo_ce_Exception, "field names must be strings", 0 TSRMLS_CC);
          return;
        }
      }
      else {
        add_assoc_zval(fields, key, *data);
        zval_add_ref(data);
      }
    }
    cursor->fields = fields;
  }
  // if it's already an object, we don't have to worry
  else {
    cursor->fields = zfields;
    zval_add_ref(&zfields);
  }

  // ns
  convert_to_string(zns);
  cursor->ns = estrdup(Z_STRVAL_P(zns));

  // query
  cursor->query = zquery;
  zval_add_ref(&zquery);

  // reset iteration pointer, just in case
  MONGO_METHOD(MongoCursor, reset, return_value, getThis());

  cursor->at = 0;
  cursor->num = 0;
  cursor->special = 0;
  cursor->persist = 0;
  
  timeout = zend_read_static_property(mongo_ce_Cursor, "timeout", strlen("timeout"), NOISY TSRMLS_CC);
  cursor->timeout = Z_LVAL_P(timeout);

  cursor->opts = link->slave_okay ? (1 << 2) : 0;
  
  // get rid of extra ref
  zval_ptr_dtor(&empty);
}
コード例 #15
0
/* {{{ MongoCursor->__construct
 */
PHP_METHOD(MongoCursor, __construct) {
  zval *zlink = 0, *zns = 0, *zquery = 0, *zfields = 0, *empty, *q, *slave_okay;
  zval **data;
  mongo_cursor *cursor;
  mongo_link *link;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|zz", &zlink, &zns, &zquery, &zfields) == FAILURE) {
    return;
  }

  // if query or fields weren't passed, make them default to an empty array
  MAKE_STD_ZVAL(empty);
  object_init(empty);

  // these are both initialized to the same zval, but that's okay because 
  // there's no way to change them without creating a new cursor
  if (!zquery) {
    zquery = empty;
  }
  if (!zfields) {
    zfields = empty;
  }

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
 
  // db connection
  cursor->resource = zlink;
  zval_add_ref(&zlink);

  // db connection resource
  ZEND_FETCH_RESOURCE2(link, mongo_link*, &zlink, -1, PHP_CONNECTION_RES_NAME, le_connection, le_pconnection); 
  cursor->link = link;

  // change ['x', 'y', 'z'] into {'x' : 1, 'y' : 1, 'z' : 1}
  if (Z_TYPE_P(zfields) == IS_ARRAY) {
    HashPosition pointer;
    zval *fields;

    MAKE_STD_ZVAL(fields);
    object_init(fields);

    // fields to return
    for(zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zfields), &pointer); 
        zend_hash_get_current_data_ex(Z_ARRVAL_P(zfields), (void**) &data, &pointer) == SUCCESS; 
        zend_hash_move_forward_ex(Z_ARRVAL_P(zfields), &pointer)) {
      int key_type, key_len;
      ulong index;
      char *key;
      
      key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(zfields), &key, (uint*)&key_len, &index, NO_DUP, &pointer);

      if (key_type == HASH_KEY_IS_LONG &&
          Z_TYPE_PP(data) == IS_STRING) {
        add_property_long(fields, Z_STRVAL_PP(data), 1);
      }
      else {
        add_property_long(fields, key, 1);
      }
    }
    cursor->fields = fields;
  }
  // if it's already an object, we don't have to worry
  else {
    cursor->fields = zfields;
    zval_add_ref(&zfields);
  }

  // ns
  convert_to_string(zns);
  cursor->ns = estrdup(Z_STRVAL_P(zns));

  // query
  MAKE_STD_ZVAL(q);
  array_init(q);

  add_assoc_zval(q, "query", zquery);
  zval_add_ref(&zquery);
  cursor->query = q;

  // reset iteration pointer, just in case
  MONGO_METHOD(MongoCursor, reset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);

  cursor->at = 0;
  cursor->num = 0;

  slave_okay = zend_read_static_property(mongo_ce_Cursor, "slaveOkay", strlen("slaveOkay"), NOISY TSRMLS_CC);
  cursor->opts = Z_BVAL_P(slave_okay) ? (1 << 2) : 0;

  // get rid of extra ref
  zval_ptr_dtor(&empty);
}
コード例 #16
0
/* {{{ MongoCursor->rewind
 */
PHP_METHOD(MongoCursor, rewind) {
  MONGO_METHOD(MongoCursor, reset)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
  MONGO_METHOD(MongoCursor, next)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
}
コード例 #17
0
/* {{{ MongoCursor::hasNext
 */
PHP_METHOD(MongoCursor, hasNext) {
  buffer buf;
  int size;
  mongo_cursor *cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  zval *temp;

  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);

  if (!cursor->started_iterating) {
    MONGO_METHOD(MongoCursor, doQuery, return_value, getThis());
    cursor->started_iterating = 1;
  }

  if ((cursor->limit > 0 && cursor->at >= cursor->limit) || 
      cursor->num == 0) {
    RETURN_FALSE;
  }
  if (cursor->at < cursor->num) {
    RETURN_TRUE;
  }
  else if (cursor->cursor_id == 0) {
    RETURN_FALSE;
  }
  // if we have a cursor_id, we should have a server
  else if (cursor->server == 0) {
    zend_throw_exception(mongo_ce_CursorException, "Trying to get more, but cannot find server", 18 TSRMLS_CC);
    return;
  }

  // we have to go and check with the db
  size = 34+strlen(cursor->ns);
  CREATE_BUF(buf, size);
  if (FAILURE == php_mongo_write_get_more(&buf, cursor TSRMLS_CC)) {
    efree(buf.start);
    return;
  }
  
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  if(mongo_say(cursor->server->socket, &buf, temp TSRMLS_CC) == FAILURE) {
    php_mongo_disconnect_server(cursor->server);
    efree(buf.start);
    zend_throw_exception(mongo_ce_CursorException, Z_STRVAL_P(temp), 1 TSRMLS_CC);
    zval_ptr_dtor(&temp);
    return;
  }

  efree(buf.start);

  if (php_mongo_get_reply(cursor, temp TSRMLS_CC) != SUCCESS) {
    zval_ptr_dtor(&temp);
    return;
  }

  zval_ptr_dtor(&temp);

  if (cursor->cursor_id == 0) {
    php_mongo_free_cursor_le(cursor, MONGO_CURSOR TSRMLS_CC);
  }
  // if cursor_id != 0, server should stay the same
  
  if (cursor->flag & 1) {
    zend_throw_exception(mongo_ce_CursorException, "Cursor not found", 2 TSRMLS_CC);
    return;
  }

  // sometimes we'll have a cursor_id but there won't be any more results
  if (cursor->at >= cursor->num) {
    RETURN_FALSE;
  }
  // but sometimes there will be
  else {
    RETURN_TRUE;
  }
}
コード例 #18
0
PHP_METHOD(MongoCursor, count) {
  zval *response, *data, *db;
  zval **n;
  mongo_cursor *cursor;
  mongo_db *db_struct;

  cursor = (mongo_cursor*)zend_object_store_get_object(getThis() TSRMLS_CC);
  MONGO_CHECK_INITIALIZED(cursor->link, MongoCursor);


  // fake a MongoDB object
  MAKE_STD_ZVAL(db);
  object_init_ex(db, mongo_ce_DB);
  db_struct = (mongo_db*)zend_object_store_get_object(db TSRMLS_CC);

  db_struct->link = cursor->resource;
  zval_add_ref(&cursor->resource);
  MAKE_STD_ZVAL(db_struct->name);
  ZVAL_STRING(db_struct->name, estrndup(cursor->ns, strchr(cursor->ns, '.') - cursor->ns), 0);


  // create query
  MAKE_STD_ZVAL(data);
  object_init(data);

  // "count" => "collectionName"
  add_property_string(data, "count", strchr(cursor->ns, '.')+1, 1);

  if (cursor->query) {
    zval **inner_query;
    if (zend_hash_find(HASH_P(cursor->query), "query", strlen("query")+1, (void**)&inner_query) == SUCCESS) {
      add_property_zval(data, "query", *inner_query);
      zval_add_ref(inner_query);
    }
  }
  if (cursor->fields) {
    add_property_zval(data, "fields", cursor->fields);
    zval_add_ref(&cursor->fields);
  }

  MAKE_STD_ZVAL(response);

  PUSH_PARAM(data); PUSH_PARAM((void*)1);
  PUSH_EO_PARAM();
  MONGO_METHOD(MongoDB, command)(1, response, &response, db, return_value_used TSRMLS_CC);
  POP_EO_PARAM();
  POP_PARAM(); POP_PARAM();

  zval_ptr_dtor(&data);

  // prep results
  if (zend_hash_find(HASH_P(response), "n", 2, (void**)&n) == SUCCESS) {
    // don't allow count to return more than cursor->limit
    if (cursor->limit > 0 && Z_DVAL_PP(n) > cursor->limit) {
      RETVAL_LONG(cursor->limit);
    }
    else {
      convert_to_long(*n);
      RETVAL_ZVAL(*n, 1, 0);
    }
    zval_ptr_dtor(&response);
  }
  else {
    RETURN_ZVAL(response, 0, 0);
  }

  zend_objects_store_del_ref(db TSRMLS_CC);
  zval_ptr_dtor(&db);
}
コード例 #19
0
ファイル: db.c プロジェクト: cockatoo-org/mongo-php-driver
static void php_mongo_enumerate_collections(INTERNAL_FUNCTION_PARAMETERS, int full_collection)
{
	zend_bool system_col = 0;
	zval *nss, *collection, *cursor, *list, *next;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &system_col) == FAILURE) {
		return;
	}

  // select db.system.namespaces collection
  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if (!system_col && (system && first_dot == system) ||
      (name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

	if (full_collection) {
		MAKE_STD_ZVAL(c);
		ZVAL_NULL(c);

		MAKE_STD_ZVAL(zname);
		ZVAL_NULL(zname);

		// name must be copied because it is a substring of
		// a string that will be garbage collected in a sec
		ZVAL_STRING(zname, name, 1);
		MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

		add_next_index_zval(list, c);

		zval_ptr_dtor(&zname);
	} else {
		add_next_index_string(list, name, 1);
	}
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}
コード例 #20
0
ファイル: db.c プロジェクト: crodas/mongo-php-driver
PHP_METHOD(MongoDB, listCollections) {
  // select db.system.namespaces collection
  zval *nss, *collection, *cursor, *list, *next;

  MAKE_STD_ZVAL(nss);
  ZVAL_STRING(nss, "system.namespaces", 1);

  MAKE_STD_ZVAL(collection);
  MONGO_METHOD1(MongoDB, selectCollection, collection, getThis(), nss);

  // list to return
  MAKE_STD_ZVAL(list);
  array_init(list);

  // do find
  MAKE_STD_ZVAL(cursor);
  MONGO_METHOD(MongoCollection, find, cursor, collection);

  // populate list
  MAKE_STD_ZVAL(next);
  MONGO_METHOD(MongoCursor, getNext, next, cursor);
  while (!IS_SCALAR_P(next)) {
    zval *c, *zname;
    zval **collection;
    char *name, *first_dot, *system;

    // check that the ns is valid and not an index (contains $)
    if (zend_hash_find(HASH_P(next), "name", 5, (void**)&collection) == FAILURE ||
        strchr(Z_STRVAL_PP(collection), '$')) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    first_dot = strchr(Z_STRVAL_PP(collection), '.');
    system = strstr(Z_STRVAL_PP(collection), ".system.");
    // check that this isn't a system ns
    if ((system && first_dot == system) ||
	(name = strchr(Z_STRVAL_PP(collection), '.')) == 0) {

      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    // take a substring after the first "."
    name++;

    // "foo." was allowed in earlier versions
    if (name == '\0') {
      zval_ptr_dtor(&next);
      MAKE_STD_ZVAL(next);
      ZVAL_NULL(next);

      MONGO_METHOD(MongoCursor, getNext, next, cursor);
      continue;
    }

    MAKE_STD_ZVAL(c);
    ZVAL_NULL(c);

    MAKE_STD_ZVAL(zname);
    ZVAL_NULL(zname);

    // name must be copied because it is a substring of
    // a string that will be garbage collected in a sec
    ZVAL_STRING(zname, name, 1);
    MONGO_METHOD1(MongoDB, selectCollection, c, getThis(), zname);

    add_next_index_zval(list, c);

    zval_ptr_dtor(&zname);
    zval_ptr_dtor(&next);
    MAKE_STD_ZVAL(next);

    MONGO_METHOD(MongoCursor, getNext, next, cursor);
  }

  zval_ptr_dtor(&next);
  zval_ptr_dtor(&nss);
  zval_ptr_dtor(&cursor);
  zval_ptr_dtor(&collection);

  RETURN_ZVAL(list, 0, 1);
}
コード例 #21
0
ファイル: db.c プロジェクト: cockatoo-org/mongo-php-driver
PHP_METHOD(MongoDB, command) {
  zval limit, *temp, *cmd, *cursor, *ns, *options = 0;
  mongo_db *db;
  mongo_link *link;
  char *cmd_ns;

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) {
    return;
  }
  if (IS_SCALAR_P(cmd)) {
    zend_error(E_WARNING, "MongoDB::command() expects parameter 1 to be an array or object");
    return;
  }

  PHP_MONGO_GET_DB(getThis());

  // create db.$cmd
  MAKE_STD_ZVAL(ns);
  cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name));
  ZVAL_STRING(ns, cmd_ns, 0);

  // create cursor
  MAKE_STD_ZVAL(cursor);
  object_init_ex(cursor, mongo_ce_Cursor);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd);

  zval_ptr_dtor(&ns);
  zval_ptr_dtor(&temp);
  MAKE_STD_ZVAL(temp);
  ZVAL_NULL(temp);

  // limit
  Z_TYPE(limit) = IS_LONG;
  Z_LVAL(limit) = -1;
  MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit);

  zval_ptr_dtor(&temp);

  if (options) {
    zval **timeout;
    if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) {
      MAKE_STD_ZVAL(temp);
      ZVAL_NULL(temp);
      MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout);
      zval_ptr_dtor(&temp);
    }
  }

  // make sure commands aren't be sent to slaves
  PHP_MONGO_GET_LINK(db->link);
  if (link->rs) {
    zval slave_okay;
    Z_TYPE(slave_okay) = IS_BOOL;
    Z_LVAL(slave_okay) = 0;

    MAKE_STD_ZVAL(temp);
    ZVAL_NULL(temp);
    MONGO_METHOD1(MongoCursor, slaveOkay, temp, cursor, &slave_okay);
    zval_ptr_dtor(&temp);
  }

  // query
  MONGO_METHOD(MongoCursor, getNext, return_value, cursor);
  clear_exception(return_value TSRMLS_CC);

  zend_objects_store_del_ref(cursor TSRMLS_CC);
  zval_ptr_dtor(&cursor);
}
コード例 #22
0
ファイル: db.c プロジェクト: shaddyz/mongo-php-driver
PHP_METHOD(MongoDB, command) {
    zval limit, *temp, *cmd, *cursor, *ns, *options = 0;
    mongo_db *db;
    mongoclient *link;
    char *cmd_ns;
    mongo_cursor *cursor_tmp;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &cmd, &options) == FAILURE) {
        return;
    }

    MUST_BE_ARRAY_OR_OBJECT(1, cmd);

    PHP_MONGO_GET_DB(getThis());

    // create db.$cmd
    MAKE_STD_ZVAL(ns);
    cmd_ns = get_cmd_ns(Z_STRVAL_P(db->name), Z_STRLEN_P(db->name));
    ZVAL_STRING(ns, cmd_ns, 0);

    // create cursor
    MAKE_STD_ZVAL(cursor);
    object_init_ex(cursor, mongo_ce_Cursor);
    MAKE_STD_ZVAL(temp);
    ZVAL_NULL(temp);

    MONGO_METHOD3(MongoCursor, __construct, temp, cursor, db->link, ns, cmd);

    zval_ptr_dtor(&ns);
    zval_ptr_dtor(&temp);
    MAKE_STD_ZVAL(temp);
    ZVAL_NULL(temp);

    // limit
    Z_TYPE(limit) = IS_LONG;
    Z_LVAL(limit) = -1;
    MONGO_METHOD1(MongoCursor, limit, temp, cursor, &limit);

    zval_ptr_dtor(&temp);

    if (options) {
        zval **timeout;
        if (zend_hash_find(HASH_P(options), "timeout", strlen("timeout")+1, (void**)&timeout) == SUCCESS) {
            MAKE_STD_ZVAL(temp);
            ZVAL_NULL(temp);
            MONGO_METHOD1(MongoCursor, timeout, temp, cursor, *timeout);
            zval_ptr_dtor(&temp);
        }
    }

    /* Make sure commands aren't be sent to slaves */
    /* TODO: The read preferences spec has a list of commands that *can* be send
     * to slave */
    /* This should be refactored alongside with the getLastError redirection in
     * collection.c/append_getlasterror. The Cursor creation should be done through
     * an init method. */
    PHP_MONGO_GET_LINK(db->link);
    cursor_tmp = (mongo_cursor*)zend_object_store_get_object(cursor TSRMLS_CC);
    mongo_manager_log(link->manager, MLOG_CON, MLOG_INFO, "forcing primary for command");
    php_mongo_connection_force_primary(cursor_tmp);


    // query
    MONGO_METHOD(MongoCursor, getNext, return_value, cursor);
    clear_exception(return_value TSRMLS_CC);

    zend_objects_store_del_ref(cursor TSRMLS_CC);
    zval_ptr_dtor(&cursor);
}