Skip to content
This repository was archived by the owner on Jun 18, 2020. It is now read-only.

Commit 91cb0d4

Browse files
authored
Merge pull request #37 from sandrokeil/feature/cursor
Add Cursor
2 parents 1fb2d49 + d14ea1d commit 91cb0d4

File tree

11 files changed

+592
-1
lines changed

11 files changed

+592
-1
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_subdirectory(deps/fuerte)
3939
## arangodb-php-driver
4040
add_library(arangodb SHARED
4141
src/connection.cpp
42+
src/cursor.cpp
4243
src/main.cpp
4344
src/request.cpp
4445
src/response.cpp

phpstorm-stubs/arangodb/arangodb.php

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ public function patch(string $path, Vpack $vpack, array $queryParams = null): Re
137137
public function options(string $path, Vpack $vpack, array $queryParams = null): Response
138138
{
139139
}
140+
141+
/**
142+
* Sends a query
143+
*
144+
* @param Vpack $vpack
145+
* @return Cursor
146+
*/
147+
public function query(Vpack $vpack): Cursor
148+
{
149+
150+
}
140151
}
141152

142153
/**
@@ -220,4 +231,84 @@ public static function fromJson(string $json): Vpack
220231
{
221232
}
222233
}
234+
235+
/**
236+
* Handles queries
237+
*
238+
* You must call rewind first to get a result
239+
*
240+
* @link https://github.com/sandrokeil/arangodb-php-driver/blob/master/src/cursorIterator.h
241+
*/
242+
final class Cursor implements \Countable
243+
{
244+
public CONST ENTRY_TYPE = 0;
245+
public CONST ENTRY_TYPE_JSON = 100;
246+
public CONST ENTRY_TYPE_ARRAY = 101;
247+
public CONST ENTRY_TYPE_OBJECT = 102;
248+
249+
/**
250+
* Returns the number of results
251+
*
252+
* Query must be run with count and fullCount = true
253+
*
254+
* @return int
255+
*/
256+
public function count()
257+
{
258+
}
259+
260+
/**
261+
* Return the current element
262+
* @link http://php.net/manual/en/iterator.current.php
263+
* @return mixed Can return any type.
264+
*/
265+
public function current()
266+
{
267+
}
268+
269+
/**
270+
* Move forward to next element
271+
* @link http://php.net/manual/en/iterator.next.php
272+
* @return void Any returned value is ignored.
273+
*/
274+
public function next()
275+
{
276+
}
277+
278+
/**
279+
* Return the key of the current element
280+
* @link http://php.net/manual/en/iterator.key.php
281+
* @return mixed scalar on success, or null on failure.
282+
*/
283+
public function key()
284+
{
285+
}
286+
287+
/**
288+
* Checks if current position is valid
289+
* @link http://php.net/manual/en/iterator.valid.php
290+
* @return boolean The return value will be casted to boolean and then evaluated.
291+
* Returns true on success or false on failure.
292+
*/
293+
public function valid()
294+
{
295+
}
296+
297+
/**
298+
* Rewind the Iterator to the first element and resets the cursor
299+
*
300+
* @link http://php.net/manual/en/iterator.rewind.php
301+
* @return void Any returned value is ignored.
302+
*/
303+
public function rewind()
304+
{
305+
}
306+
307+
/**
308+
* Rewinds the cursor and returns the result
309+
*/
310+
public function toArray(): array
311+
{
312+
}
313+
}
223314
}

src/connection.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "connection.h"
2+
#include "cursor.h"
23

34
namespace arangodb { namespace fuerte { namespace php {
45

@@ -41,6 +42,17 @@ namespace arangodb { namespace fuerte { namespace php {
4142
this->threadCount = threadCount;
4243
}
4344

45+
void Connection::setDefaultTimeout(Php::Parameters &params)
46+
{
47+
int defaultTimeout = params[0];
48+
49+
if(defaultTimeout < 1) {
50+
throw Php::Exception("Invalid defaultTimeout provided, must be >= 1");
51+
}
52+
53+
this->defaultTimeout = defaultTimeout;
54+
}
55+
4456
fu::ConnectionBuilder Connection::createConnectionBuilder()
4557
{
4658
try {
@@ -220,4 +232,18 @@ namespace arangodb { namespace fuerte { namespace php {
220232
}
221233
}
222234

235+
Php::Value Connection::query(Php::Parameters &params)
236+
{
237+
if(!params[0].instanceOf("ArangoDb\\Vpack"))
238+
throw Php::Exception("Expected vpack to be of type Vpack");
239+
240+
Cursor* cursor = new Cursor(this, (Vpack*)params[0].implementation());
241+
242+
for(auto option : params[1]) {
243+
cursor->setOption(option.first, option.second);
244+
}
245+
246+
return Php::Object("ArangoDb\\Cursor", cursor);
247+
}
248+
223249
}}}

src/connection.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ namespace arangodb { namespace fuerte { namespace php {
5454
void __construct(Php::Parameters &params);
5555

5656
void setThreadCount(Php::Parameters &params);
57+
void setDefaultTimeout(Php::Parameters &params);
5758

5859
void connect();
5960
Response* sendRequest(Request* request);
@@ -72,6 +73,8 @@ namespace arangodb { namespace fuerte { namespace php {
7273

7374
void wait();
7475

76+
Php::Value query(Php::Parameters &params);
77+
7578
};
7679

7780
}}}

src/cursor.cpp

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include "cursor.h"
2+
3+
namespace arangodb { namespace fuerte { namespace php {
4+
5+
Cursor::Cursor(Connection* connection, Vpack* vpack): vpack(*vpack), connection(connection)
6+
{
7+
}
8+
9+
void Cursor::setOption(int option, int value)
10+
{
11+
if(this->options.size() <= option) {
12+
throw Php::Exception("Invalid option provided for Cursor");
13+
}
14+
15+
this->options[option] = value;
16+
}
17+
18+
void Cursor::loadFirstBatch()
19+
{
20+
Request request("/_api/cursor", &this->vpack);
21+
request.setHttpMethod(Request::METHOD_POST);
22+
23+
Response* response = this->connection->sendRequest(&request);
24+
this->response = response;
25+
26+
if(this->response->getFuerteResponse()->slices().front().get("error").getBool()) {
27+
throw Php::Exception(
28+
"Error while executing query: " +
29+
this->response->getFuerteResponse()->slices().front().get("errorMessage").copyString()
30+
);
31+
}
32+
33+
this->hasMore = this->response->getFuerteResponse()->slices().front().get("hasMore").getBool();
34+
this->batchSize = this->response->getFuerteResponse()->slices().front().get("result").length();
35+
this->number = this->batchSize;
36+
37+
if (this->response->getFuerteResponse()->slices().front().hasKey("count")) {
38+
this->number = this->response->getFuerteResponse()->slices().front().get("count").getInt();
39+
}
40+
41+
if(this->hasMore) {
42+
this->id = this->response->getFuerteResponse()->slices().front().get("id").copyString();
43+
}
44+
}
45+
46+
void Cursor::loadMore()
47+
{
48+
Vpack emptyVpack;
49+
50+
Request request("/_api/cursor/" + this->id, &emptyVpack);
51+
request.setHttpMethod(Request::METHOD_PUT);
52+
53+
Response* response = this->connection->sendRequest(&request);
54+
55+
this->response = response;
56+
this->hasMore = this->response->getFuerteResponse()->slices().front().get("hasMore").getBool();
57+
this->batchSize = this->response->getFuerteResponse()->slices().front().get("result").length();
58+
this->number = this->batchSize;
59+
60+
if (this->response->getFuerteResponse()->slices().front().hasKey("count")) {
61+
this->number = this->response->getFuerteResponse()->slices().front().get("count").getInt();
62+
}
63+
}
64+
65+
Php::Value Cursor::valid()
66+
{
67+
if(this->batchSize > this->position) {
68+
return true;
69+
} else if(this->hasMore) {
70+
this->loadMore();
71+
this->position = 0;
72+
return true;
73+
}
74+
75+
return false;
76+
}
77+
78+
Php::Value Cursor::current()
79+
{
80+
std::string body;
81+
82+
try {
83+
vp::Slice slice = this->response->getFuerteResponse()->slices().front().get("result").at(this->position);
84+
vp::Options dumperOptions;
85+
86+
vp::StringSink sink(&body);
87+
vp::Dumper dumper(&sink, &dumperOptions);
88+
dumper.dump(slice);
89+
} catch(vp::Exception const& e) {
90+
throw Php::Exception(e.what());
91+
}
92+
93+
switch(this->options[Cursor::ENTRY_TYPE]) {
94+
case Cursor::ENTRY_TYPE_JSON:
95+
return body;
96+
case Cursor::ENTRY_TYPE_ARRAY:
97+
return Php::call("json_decode", body, true);
98+
case Cursor::ENTRY_TYPE_OBJECT:
99+
return Php::call("json_decode", body, false);
100+
default:
101+
return body;
102+
}
103+
}
104+
105+
Php::Value Cursor::key()
106+
{
107+
return this->position;
108+
}
109+
110+
void Cursor::next()
111+
{
112+
this->position++;
113+
}
114+
115+
void Cursor::rewind()
116+
{
117+
this->position = 0;
118+
this->loadFirstBatch();
119+
}
120+
121+
long Cursor::count() {
122+
return static_cast<int>(this->number);
123+
}
124+
125+
Php::Value Cursor::getCount() {
126+
return static_cast<int>(this->number);
127+
}
128+
129+
Php::Value Cursor::toArray() {
130+
this->rewind();
131+
Php::Array result;
132+
int counter = 0;
133+
while(this->valid()) {
134+
result[counter++] = this->current();
135+
this->next();
136+
}
137+
138+
return result;
139+
}
140+
141+
Php::Value Cursor::getResponse() {
142+
return Php::Object("ArangoDb\\Response", this->response);
143+
}
144+
145+
}}}

src/cursor.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#pragma once
2+
3+
#include <phpcpp.h>
4+
5+
#include <fuerte/fuerte.h>
6+
#include <fuerte/types.h>
7+
#include <stdint-gcc.h>
8+
9+
#include "connection.h"
10+
11+
namespace vp = ::arangodb::velocypack;
12+
namespace fu = ::arangodb::fuerte;
13+
14+
namespace arangodb { namespace fuerte { namespace php {
15+
16+
class Cursor : public Php::Base, public Php::Countable
17+
{
18+
private:
19+
Connection* connection;
20+
Vpack vpack;
21+
22+
bool hasMore;
23+
int position = 0;
24+
std::string id;
25+
int64_t batchSize;
26+
int64_t number;
27+
28+
Response* response;
29+
30+
void loadFirstBatch();
31+
void loadMore();
32+
33+
std::vector<int> options = {
34+
{ Cursor::ENTRY_TYPE, Cursor::ENTRY_TYPE_JSON }
35+
};
36+
37+
public:
38+
static const int ENTRY_TYPE = 0;
39+
40+
static const int ENTRY_TYPE_JSON = 100;
41+
static const int ENTRY_TYPE_ARRAY = 101;
42+
static const int ENTRY_TYPE_OBJECT = 102;
43+
44+
Cursor(Connection* connection, Vpack* vpack);
45+
46+
void setOption(int option, int value);
47+
48+
virtual long count() override;
49+
Php::Value getCount();
50+
51+
Php::Value valid();
52+
Php::Value current();
53+
Php::Value key();
54+
void next();
55+
void rewind();
56+
57+
Php::Value toArray();
58+
Php::Value getResponse();
59+
60+
virtual ~Cursor() = default;
61+
};
62+
63+
}}}

0 commit comments

Comments
 (0)