├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.xml
├── composer.json
├── composer.lock
├── docs
├── html-timeboundary-output.png
└── sequence-diagram.png
├── examples
├── _examples-config.php
├── compare-transformation-and-not.php
├── healthcheck.php
├── html-query-printer-improved.php
├── html-query-printer.php
├── html-timeboundary-printer.php
├── src
│ ├── ExampleGroupByQueries
│ │ ├── ReferralsByCompanyGroupByQueryGenerator.php
│ │ ├── ReferralsByCompanyGroupByQueryParameters.php
│ │ ├── ReferralsByCompanyGroupByResponseHandler.php
│ │ └── ReferralsByCompanyGroupByWithResponseObject.php
│ └── ExampleResponseObjects
│ │ └── ExampleReferralByCompanyResponseObject.php
└── stdout-timeboundary-printer.php
├── phpunit.xml
├── src
└── DruidFamiliar
│ ├── Abstracts
│ └── AbstractTaskParameters.php
│ ├── DruidTime.php
│ ├── Exception
│ ├── ConnectionLostException.php
│ ├── DruidBusyException.php
│ ├── DruidUnavailableException.php
│ ├── EmptyParametersException.php
│ ├── MalformedQueryException.php
│ ├── MissingParametersException.php
│ └── UnexpectedTypeException.php
│ ├── Interfaces
│ ├── IDruidQueryExecutor.php
│ ├── IDruidQueryGenerator.php
│ ├── IDruidQueryParameters.php
│ └── IDruidQueryResponseHandler.php
│ ├── Interval.php
│ ├── QueryExecutor
│ ├── DruidNodeDruidQueryExecutor.php
│ └── JSONDruidNodeDruidQueryExecutor.php
│ ├── QueryGenerator
│ ├── GroupByQueryGenerator.php
│ ├── SegmentMetadataDruidQueryGenerator.php
│ ├── SimpleGroupByDruidQueryGenerator.php
│ └── TimeBoundaryDruidQueryGenerator.php
│ ├── QueryParameters
│ ├── GroupByQueryParameters.php
│ ├── SegmentMetadataQueryParameters.php
│ ├── SimpleGroupByQueryParameters.php
│ └── TimeBoundaryQueryParameters.php
│ ├── Response
│ ├── GroupByResponse.php
│ └── TimeBoundaryResponse.php
│ └── ResponseHandler
│ ├── DoNothingResponseHandler.php
│ ├── GroupByResponseHandler.php
│ ├── JsonFormattingResponseHandler.php
│ └── TimeBoundaryResponseHandler.php
└── tests
└── DruidFamiliar
└── Test
├── Abstracts
└── AbstractTaskParametersTest.php
├── DruidTimeTest.php
├── Exception
├── EmptyParametersExceptionTest.php
└── MissingParametersExceptionTest.php
├── IntervalTest.php
├── QueryExecutor
└── DruidNodeDruidQueryExecutorTest.php
├── QueryGenerator
├── GroupByQueryGeneratorTest.php
├── SegmentMetadataDruidQueryGeneratorTest.php
├── SimpleGroupByDruidQueryGeneratorTest.php
└── TimeBoundaryDruidQueryGeneratorTest.php
├── QueryParameters
├── GroupByQueryParametersTest.php
├── SegmentMetadataQueryParametersTest.php
├── SimpleGroupByQueryParametersTest.php
└── TimeBoundaryQueryParametersTest.php
├── ResponseHandler
├── DoNothingResponseHandlerTest.php
├── GroupByResponseHandlerTest.php
└── TimeBoundaryResponseHandlerTest.php
├── bootstrap.php
└── phpunit.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.phar
2 | vendor/
3 | build/
4 | .idea/
5 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - '5.3'
4 | - '5.5'
5 | - '7.0'
6 | - hhvm
7 | - nightly
8 | before_script: composer install
9 | script: vendor/bin/phpunit tests
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Jasmine Hegman
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | php-druid-query
2 | ===============
3 |
4 | PHP wrapper around executing HTTP requests to [Druid](http://druid.io). Usually this will be for queries, but can be
5 | used for other purposes (such as [ingestion](https://github.com/r4j4h/php-druid-ingest)).
6 |
7 |
8 | Overview
9 | ---------------
10 |
11 | The wrapper lives in the namespace `DruidFamiliar`. Druid itself was named in the sprit of the D&D character, and that
12 | character could have a familiar - a spiritually linked animal companion. This wrapper in a sense lives as a companion to
13 | Druid, and thus the name.
14 |
15 | I think the repo name should reflect the namespace for clarity, it currently is `php-druid-query` while
16 | the namespace is `DruidFamiliar`. This would be pretty breaking change and will be saved for the future. If you have
17 | other suggestions for naming of project or namespaces, feel free to suggest before then.
18 |
19 |
20 | Changelog
21 | -----------
22 |
23 | 0.2.1
24 |
25 | - `DruidTime`/`Interval` classes added to make it easier to work with varieties of time inputs to Druid compatible time output.
26 |
27 | 0.2.0 Major refactoring
28 |
29 | - Query and Response Handling separated. All interfaces renamed and redesigned.
30 | - `IDruidConnection` is now `IDruidQueryExecutor`.
31 | - `IDruidQuery` is split into `IDruidQueryGenerator` and `IDruidQueryParameters` and `IDruidQueryResponseHandler`.
32 | - `BaseQuery` is no longer needed, many similar classes were deprecated or removed.
33 | - `DruidNodeConnection` is now `DruidNodeDruidQueryExecutor`.
34 |
35 | 0.1.0 Initial release
36 |
37 | - Quick sketch for sharing early.
38 |
39 |
40 | Typical Use
41 | ---------------
42 |
43 | In general, this wrapper's purpose is to streamline the execution of queries by encapsulating the cruft from the `HTTP` nature of Druid and the analytical grammar in query configuration.
44 |
45 | 1. Instantiate a connection, configured to hit a Druid endpoint.
46 | 2. Instantiate a query generator object for the desired query.
47 | 3. Instantiate a query parameters object, configured with desired query parameters.
48 | 4. Instantiate a result handler to format the results (otherwise use `DoNothingResponseHandler`)
49 | 5. Combine the connection, query, parameters, and response handler to execute it, getting the result from the result handler.
50 |
51 | Interface wise, this looks like:
52 |
53 | 1. Instantiate a `IDruidQueryExecutor`, configured to hit a Druid endpoint.
54 | 2. Instantiate a `IDruidQueryGenerator`.
55 | 3. Instantiate a `IDruidQueryParameters`, configured with parameters.
56 | 4. Instantiate a `IDruidQueryResponseHandler`.
57 | 5. Run the `IDruidQueryExecutor`'s `executeQuery` function with the `IDruidQueryGenerator`, `IDruidQueryParameters`, and the `IDruidQueryResponseHandler`, getting the result from the `IDruidQueryResponseHandler`.
58 |
59 | Implementation wise, this can look like:
60 |
61 | 1. Instantiate a `DruidNodeDruidQueryExecutor`, configured to hit a Druid endpoint.
62 | 2. Instantiate a `SegmentMetadataDruidQuery`.
63 | 3. Instantiate a `SegmentMetadataDruidQueryParameters`, configured with parameters.
64 | 4. Instantiate a `SegmentMetadataResponseHandler`.
65 | 5. Run the `DruidNodeDruidQueryExecutor`'s `executeQuery` function with the classes spawned in the previous steps, getting the result from `SegmentMetadataResponseHandler`.
66 |
67 |
68 | How to Install
69 | ---------------
70 |
71 | Right now, there is no tagged version. To be ready for it when it comes, branch-aliases are in place.
72 |
73 | - Stable branch: `~1.0@dev`
74 | - Cutting edge: `~1.1@dev`
75 |
76 |
77 | To install, it is suggested to use [Composer](http://getcomposer.org). If you have it installed, then the following instructions
78 | in a composer.json should be all you need to get started:
79 |
80 | ```json
81 | {
82 | "require": {
83 | "r4j4h/php-druid-query": "~1.0@dev"
84 | }
85 | }
86 | ```
87 |
88 | Once that is in, `composer install` and `composer update` should work.
89 |
90 | Once those are run, require Composer's autoloader and you are off to the races, or tree circles as it were (bad Druid reference):
91 |
92 | 1. `require 'vendor/autoload.php';`
93 | 2. `$yay = new \DruidFamiliar\Query\TimeBoundaryDruidQuery('my-cool-data-source');`
94 | 3. Refer to the [Typical Use](#typical-use) section above.
95 |
96 |
97 | How to Test
98 | -------------
99 |
100 | Once `composer install` has finished, from the root directory in a command terminal run:
101 |
102 | `vendor/bin/phing`
103 |
104 | or
105 |
106 | `vendor/bin/phpunit tests`
107 |
108 |
109 | Generate Documentation
110 | -------------
111 |
112 | From the root directory, in a command terminal run: `php vendor/bin/phing docs`.
113 |
114 |
115 | Examples
116 | ---------------
117 |
118 | Examples are located in the [\examples](examples) folder.
119 |
120 | They share connection information from `_examples-config.php`.
121 | Change that match your Druid instance's connection info.
122 |
123 | Right now most are designed to run via the CLI, but will work in a browser if a web server running php serves them.
124 |
125 | The HTML outputting ones should print the query results to HTML:
126 |
127 | 
128 |
129 |
130 |
131 |
132 | How it Works & How to Extend
133 | ---------------
134 |
135 | Please refer to this diagram for an overview of how this works underneath the hood.
136 |
137 | 
138 |
139 | (From this [Dynamic LucidChart Source URL](https://www.lucidchart.com/publicSegments/view/542c92a6-f14c-4520-b004-04920a00caaf/image.png))
140 |
141 | In general, to add support for a new query all you need to do is create a new class wherever you want that implements `IDruidQuery`.
142 |
143 | By wherever you want, that could be in a fork of this repo, or outside of this repo using this repo's interfaces. That is up to you. :)
144 |
145 |
146 |
147 |
148 | References
149 | ---------------
150 |
151 | - [Druid](http://druid.io)
152 | - [Composer](http://getcomposer.org)
153 | - [Guzzle](http://guzzle.readthedocs.org)
154 |
155 |
156 | Appendix A. Composer.json example that does not rely on Packagist.org:
157 | ---------------
158 |
159 | ```json
160 | {
161 | "repositories": [
162 | {
163 | "type": "vcs",
164 | "url": "git@github.com:r4j4h/php-druid-query"
165 | }
166 | ],
167 | "require": {
168 | "r4j4h/php-druid-query": "~1.0@dev"
169 | }
170 | }
171 | ```
172 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "r4j4h/php-druid-query",
3 | "description": "Experimental PHP wrapper around querying druid",
4 | "keywords": ["druid", "querying", "query", "parameterized query"],
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Jasmine Hegman",
9 | "email": "hegpetz@gmail.com",
10 | "role": "Developer"
11 | }
12 | ],
13 | "require": {
14 | "php": ">=5.3.0",
15 | "guzzle/guzzle": "~3.9"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "~4",
19 | "phing/phing": "~2",
20 | "phpmd/phpmd": "~2",
21 | "phploc/phploc": "~2"
22 | },
23 | "autoload": {
24 | "psr-4": {
25 | "DruidFamiliar\\": "src/DruidFamiliar/"
26 | }
27 | },
28 | "autoload-dev": {
29 | "psr-4": {
30 | "DruidFamiliar\\": ["tests/DruidFamiliar/", "examples/src/"]
31 | }
32 | },
33 | "extra": {
34 | "branch-alias": {
35 | "dev-develop": "1.1.x-dev",
36 | "dev-master": "1.0.x-dev"
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/docs/html-timeboundary-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r4j4h/php-druid-query/c5f9f5b8c3efd233eada7f3ca0b38baea5407e83/docs/html-timeboundary-output.png
--------------------------------------------------------------------------------
/docs/sequence-diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r4j4h/php-druid-query/c5f9f5b8c3efd233eada7f3ca0b38baea5407e83/docs/sequence-diagram.png
--------------------------------------------------------------------------------
/examples/_examples-config.php:
--------------------------------------------------------------------------------
1 | '10.20.30.119',
5 | // 'druid-port' => '9001',
6 | // 'druid-dataSource' => 'referral-visit-test-data',
7 | 'druid-host' => 'devdruid.webpt.com',
8 | 'druid-port' => '8080',
9 | 'druid-dataSource' => 'referral-visit-old-format'
10 | );
--------------------------------------------------------------------------------
/examples/compare-transformation-and-not.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $p, new DruidFamiliar\ResponseHandler\JsonFormattingResponseHandler());
18 |
19 | var_dump( $r );
20 |
21 | //array(1) {
22 | // [0]=>
23 | // array(2) {
24 | // ["timestamp"]=>
25 | // string(24) "2011-06-01T00:00:11.000Z"
26 | // ["result"]=>
27 | // array(2) {
28 | // ["minTime"]=>
29 | // string(24) "2011-06-01T00:00:11.000Z"
30 | // ["maxTime"]=>
31 | // string(24) "2011-11-30T23:55:34.000Z"
32 | // }
33 | // }
34 | //}
35 |
36 |
37 | $q = new \DruidFamiliar\QueryGenerator\TimeBoundaryDruidQueryGenerator($druidDataSource);
38 | $p = new \DruidFamiliar\QueryParameters\TimeBoundaryQueryParameters($druidDataSource);
39 | $r = $c->executeQuery($q, $p, new DruidFamiliar\ResponseHandler\TimeBoundaryResponseHandler());
40 |
41 |
42 | var_dump( $r );
43 |
44 | //object(DruidFamiliar\Response\TimeBoundaryResponse)#11 (2) {
45 | // ["minTime"]=>
46 | // string(24) "2008-02-06T11:47:39.000Z"
47 | // ["maxTime"]=>
48 | // string(24) "2008-12-31T19:36:48.000Z"
49 | //}
50 |
--------------------------------------------------------------------------------
/examples/healthcheck.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $params, $responseHandler);
37 |
38 | echo "DruidFamiliar\n";
39 | echo "Talking to $druidHost on port $druidPort.\n";
40 |
41 | if ( isset( $timeBoundaryResponse->minTime ) ) {
42 | echo "Good to go!\n";
43 | } else {
44 | echo "Problem encountered :(\n";
45 | echo "Talked to something, but it didn't seem to be druid.";
46 | }
47 |
48 | }
49 | catch ( Guzzle\Common\Exception\InvalidArgumentException $e ) {
50 |
51 | }
52 | catch ( Guzzle\Http\Exception\CurlException $e ) {
53 | echo "Problem encountered :(\n";
54 | echo "Am I really pointed at a Druid broker node?\n";
55 | }
56 | catch ( \Exception $e )
57 | {
58 | $message = $e->getMessage();
59 |
60 | if ( $message === 'Unexpected response format' )
61 | {
62 | echo "Problem encountered :(\n";
63 | echo "Does your Data Source exist?";
64 | }
65 | else if ( $message === 'Unknown data source' )
66 | {
67 | echo "Should be okay, did you point to a non-existant data source?\n";
68 | }
69 | else
70 | {
71 | throw $e;
72 | }
73 |
74 | }
75 |
76 |
77 |
--------------------------------------------------------------------------------
/examples/html-query-printer-improved.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $p, new DruidFamiliar\ResponseHandler\TimeBoundaryResponseHandler());
31 |
32 | $q2 = new \DruidFamiliar\ExampleGroupByQueries\ReferralsByCompanyGroupByQueryGenerator();
33 | $p2 = new ReferralsByCompanyGroupByQueryParameters( $druidDataSource, '2006-01-01T00:00', '2015-01-01T00' );
34 | /**
35 | * @var ExampleReferralByCompanyResponseObject $r2
36 | */
37 | $r2 = $c->executeQuery($q2, $p2, new ReferralsByCompanyGroupByResponseHandler());
38 |
39 |
40 | $startTime = new DateTime( $r->minTime );
41 | $endTime = new DateTime( $r->maxTime );
42 |
43 | $formattedStartTime = $startTime->format("F m, Y h:i:s A");
44 | $formattedEndTime = $endTime->format("F m, Y h:i:s A");
45 |
46 | $groupByBodyRows = '';
47 |
48 | foreach ( $r2 as $index => $val)
49 | {
50 | /**
51 | * @var \DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject $exampleReferralByCompanyResponseObject
52 | */
53 | $exampleReferralByCompanyResponseObject = $val;
54 |
55 | $timestamp = $exampleReferralByCompanyResponseObject->getTimestamp();
56 | $companyId = $exampleReferralByCompanyResponseObject->getCompanyId();
57 | $facilityId = $exampleReferralByCompanyResponseObject->getFacilityId();
58 | $referrals = $exampleReferralByCompanyResponseObject->getReferrals();
59 |
60 | $groupByBodyRows .= <<
62 | $timestamp |
63 | $companyId |
64 | $facilityId |
65 | $referrals |
66 |
67 | TABLEROW;
68 |
69 | }
70 |
71 |
72 | echo <<
74 |
75 |
76 |
105 |
106 |
107 | TimeBoundary data for DataSource "$druidDataSource":
108 |
109 |
110 |
111 | DataSource |
112 | Start |
113 | End |
114 |
115 |
116 |
117 |
118 | $druidDataSource |
119 | $formattedStartTime |
120 | $formattedEndTime |
121 |
122 |
123 |
124 |
125 |
Raw Group By Query Results
126 |
127 |
128 |
129 | timestamp |
130 | companyId |
131 | facilityId |
132 | referrals |
133 |
134 |
135 |
136 | $groupByBodyRows
137 |
138 |
139 |
140 |
141 |
142 |
143 | HTML_BODY;
144 |
--------------------------------------------------------------------------------
/examples/html-query-printer.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $p, new DruidFamiliar\ResponseHandler\TimeBoundaryResponseHandler());
30 |
31 | $q2 = new \DruidFamiliar\ExampleGroupByQueries\ReferralsByCompanyGroupByQueryGenerator();
32 | $p2 = new ReferralsByCompanyGroupByQueryParameters( $druidDataSource, '2006-01-01T00:00', '2015-01-01T00' );
33 | $r2 = $c->executeQuery($q2, $p2, new \DruidFamiliar\ResponseHandler\JsonFormattingResponseHandler());
34 |
35 |
36 | $startTime = new DateTime( $r->minTime );
37 | $endTime = new DateTime( $r->maxTime );
38 |
39 | $formattedStartTime = $startTime->format("F m, Y h:i:s A");
40 | $formattedEndTime = $endTime->format("F m, Y h:i:s A");
41 |
42 | $groupByHeadRows = <<
44 | timestamp |
45 | companyId |
46 | facilityId |
47 | referrals |
48 |
49 | TABLEHEADROW;
50 | ;
51 | $groupByBodyRows = '';
52 |
53 | foreach ( $r2 as $index => $chunk)
54 | {
55 | $timestamp = $chunk['timestamp'];
56 | $companyId = $chunk['event']['company_id'];
57 | $facilityId = $chunk['event']['facility_id'];
58 | $referrals = $chunk['event']['referral_count'];
59 |
60 | $groupByBodyRows .= <<
62 | $timestamp |
63 | $companyId |
64 | $facilityId |
65 | $referrals |
66 |
67 | TABLEROW;
68 |
69 | }
70 |
71 |
72 | echo <<
74 |
75 |
76 |
105 |
106 |
107 | TimeBoundary data for DataSource "$druidDataSource":
108 |
109 |
110 |
111 | DataSource |
112 | Start |
113 | End |
114 |
115 |
116 |
117 |
118 | $druidDataSource |
119 | $formattedStartTime |
120 | $formattedEndTime |
121 |
122 |
123 |
124 |
125 |
Raw Group By Query Results
126 |
127 |
128 | $groupByHeadRows
129 |
130 |
131 | $groupByBodyRows
132 |
133 |
134 |
135 |
136 |
137 |
138 | HTML_BODY;
139 |
--------------------------------------------------------------------------------
/examples/html-timeboundary-printer.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $p, new DruidFamiliar\ResponseHandler\TimeBoundaryResponseHandler());
28 |
29 | $startTime = new DateTime( $r->minTime );
30 | $endTime = new DateTime( $r->maxTime );
31 |
32 | $formattedStartTime = $startTime->format("F m, Y h:i:s A");
33 | $formattedEndTime = $endTime->format("F m, Y h:i:s A");
34 |
35 | echo <<
37 |
38 |
39 |
68 |
69 |
70 | TimeBoundary data for DataSource "$druidDataSource":
71 |
72 |
73 |
74 | DataSource |
75 | Start |
76 | End |
77 |
78 |
79 |
80 |
81 | $druidDataSource |
82 | $formattedStartTime |
83 | $formattedEndTime |
84 |
85 |
86 |
87 |
88 |
89 |
90 | HTML_BODY;
91 |
--------------------------------------------------------------------------------
/examples/src/ExampleGroupByQueries/ReferralsByCompanyGroupByQueryGenerator.php:
--------------------------------------------------------------------------------
1 | queryTemplate;
43 |
44 | $query = str_replace('{DATASOURCE}', $params->dataSource, $query);
45 | $query = str_replace('{STARTINTERVAL}', $params->startInterval, $query);
46 | $query = str_replace('{ENDINTERVAL}', $params->endInterval, $query);
47 |
48 | return $query;
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/examples/src/ExampleGroupByQueries/ReferralsByCompanyGroupByQueryParameters.php:
--------------------------------------------------------------------------------
1 | dataSource = $dataSource;
34 | $this->startInterval = $startInterval;
35 | $this->endInterval = $endInterval;
36 | }
37 |
38 | /**
39 | * @throws MissingParametersException
40 | */
41 | public function validate()
42 | {
43 | $missingParams = array();
44 |
45 | if ( !isset( $this->dataSource ) ) {
46 | $missingParams[] = 'dataSource';
47 | }
48 | if ( !isset( $this->startInterval ) ) {
49 | $missingParams[] = 'startInterval';
50 | }
51 | if ( !isset( $this->endInterval ) ) {
52 | $missingParams[] = 'endInterval';
53 | }
54 |
55 | if ( count( $missingParams ) > 0 ) {
56 | throw new MissingParametersException($missingParams);
57 | }
58 |
59 | return true;
60 | }
61 | }
--------------------------------------------------------------------------------
/examples/src/ExampleGroupByQueries/ReferralsByCompanyGroupByResponseHandler.php:
--------------------------------------------------------------------------------
1 | json();
28 |
29 | if ( empty( $response ) ) {
30 | throw new \Exception('Unknown data source.');
31 | }
32 |
33 | $responseArray = array();
34 |
35 | foreach ( $response as $index => $chunk)
36 | {
37 | $timestamp = $chunk['timestamp'];
38 | $companyId = $chunk['event']['company_id'];
39 | $facilityId = $chunk['event']['facility_id'];
40 | $referrals = $chunk['event']['referral_count'];
41 |
42 | $responseObj = new \DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject(
43 | $companyId, $facilityId, $referrals, $timestamp
44 | );
45 |
46 | $responseArray[] = $responseObj;
47 | }
48 |
49 | return $responseArray;
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/examples/src/ExampleGroupByQueries/ReferralsByCompanyGroupByWithResponseObject.php:
--------------------------------------------------------------------------------
1 | $chunk)
21 | {
22 | $timestamp = $chunk['timestamp'];
23 | $companyId = $chunk['event']['company_id'];
24 | $facilityId = $chunk['event']['facility_id'];
25 | $referrals = $chunk['event']['referral_count'];
26 |
27 | $dto = new \DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject(
28 | $companyId, $facilityId, $referrals, $timestamp
29 | );
30 |
31 | $responseArray[] = $dto;
32 | }
33 |
34 | return $responseArray;
35 | }
36 |
37 |
38 | }
--------------------------------------------------------------------------------
/examples/src/ExampleResponseObjects/ExampleReferralByCompanyResponseObject.php:
--------------------------------------------------------------------------------
1 | companyId = $companyId;
19 | $this->facilityId = $facilityId;
20 | $this->referrals = $referrals;
21 | $this->timestamp = $timestamp;
22 | }
23 |
24 | /**
25 | * @return mixed
26 | */
27 | public function getCompanyId()
28 | {
29 | return $this->companyId;
30 | }
31 |
32 | /**
33 | * @return mixed
34 | */
35 | public function getFacilityId()
36 | {
37 | return $this->facilityId;
38 | }
39 |
40 | /**
41 | * @return mixed
42 | */
43 | public function getReferrals()
44 | {
45 | return $this->referrals;
46 | }
47 |
48 | /**
49 | * @return mixed
50 | */
51 | public function getTimestamp()
52 | {
53 | return $this->timestamp;
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/examples/stdout-timeboundary-printer.php:
--------------------------------------------------------------------------------
1 | executeQuery($q, $p, new DruidFamiliar\ResponseHandler\TimeBoundaryResponseHandler());
29 |
30 | echo "TimeBoundary data for DataSource \"$druidDataSource\": ";
31 |
32 | $startTime = new DateTime( $r->minTime );
33 | $endTime = new DateTime( $r->maxTime );
34 |
35 | $formattedStartTime = $startTime->format("F m, Y h:i:s A");
36 | $formattedEndTime = $endTime->format("F m, Y h:i:s A");
37 |
38 |
39 | echo $formattedStartTime . " to " . $formattedEndTime . "\n";
40 |
41 | // Outputs:
42 | // TimeBoundary data for DataSource "referral-visit-test-data": June 06, 2011 12:00:11 AM to June 06, 2011 12:00:11 AM
43 |
44 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./tests/
6 |
7 |
8 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/Abstracts/AbstractTaskParameters.php:
--------------------------------------------------------------------------------
1 | validate();
24 | }
25 | catch(MissingParametersException $e)
26 | {
27 | return false;
28 | }
29 |
30 | return true;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/DruidTime.php:
--------------------------------------------------------------------------------
1 | setTime($time);
31 | }
32 |
33 | public function __toString()
34 | {
35 | // Format
36 | return $this->formatTimeForDruid();
37 | }
38 |
39 | public function formatTimeForDruid()
40 | {
41 | // Missing params
42 | $missingParams = array();
43 | if ( !isset( $this->time ) ) { $missingParams[] = 'time'; }
44 | if ( count( $missingParams ) > 0 ) { throw new MissingParametersException($missingParams); }
45 |
46 | // Invalid params
47 | if ( !$this->time instanceof DateTime ) {
48 | throw new UnexpectedTypeException($this->time, 'DateTime', 'For parameter time.');
49 | }
50 |
51 | // Format
52 | return $this->time->format("Y-m-d\TH:i:s\Z");
53 | }
54 |
55 | /**
56 | * @param string|DateTime $time
57 | * @throws RuntimeException
58 | */
59 | public function setTime($time)
60 | {
61 |
62 | if ( is_string($time ) )
63 | {
64 | $time = new DateTime( $time );
65 | }
66 |
67 | if ( is_a($time, 'DateTime') )
68 | {
69 | $this->time = $time;
70 | }
71 | else if ( is_a($time, 'DruidFamiliar\DruidTime') )
72 | {
73 | /** @var \DruidFamiliar\DruidTime $time */
74 | $this->time = $time->getTime();
75 | }
76 | else
77 | {
78 | throw new RuntimeException('Encountered unexpected time. Expected either string or DateTime.');
79 | }
80 |
81 | }
82 |
83 | public function getTime()
84 | {
85 | return $this->time;
86 | }
87 |
88 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/Exception/ConnectionLostException.php:
--------------------------------------------------------------------------------
1 | emptyParameters = $emptyParameters;
34 | parent::__construct("Empty parameters: " . join(", ", $this->emptyParameters), count($this->emptyParameters), $previous);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/Exception/MalformedQueryException.php:
--------------------------------------------------------------------------------
1 | missingParameters = $missingParameters;
21 | parent::__construct("Missing parameters: " . join(", ", $this->missingParameters), count($this->missingParameters), $previous);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/Exception/UnexpectedTypeException.php:
--------------------------------------------------------------------------------
1 |
7 | *
8 | * For the full copyright and license information, please view the LICENSE
9 | * file that was distributed with this source code.
10 | */
11 |
12 | namespace DruidFamiliar\Exception;
13 |
14 | use Exception;
15 |
16 | class UnexpectedTypeException extends Exception
17 | {
18 | public function __construct($value, $expectedType, $extraMessage = "", $previous = NULL)
19 | {
20 | $message = sprintf('Expected argument of type "%s", "%s" given.', $expectedType, is_object($value) ? get_class($value) : gettype($value));
21 |
22 | if($extraMessage)
23 | {
24 | $message .= " " . $extraMessage;
25 | }
26 | parent::__construct( $message, 0, $previous );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/Interfaces/IDruidQueryExecutor.php:
--------------------------------------------------------------------------------
1 | setInterval($intervalStart, $intervalEnd);
40 | }
41 |
42 |
43 | /**
44 | * @param string|DateTime|DruidTime $intervalStart
45 | * @param string|DateTime|DruidTime $intervalEnd
46 | */
47 | public function setInterval($intervalStart = "1970-01-01 01:30:00", $intervalEnd = "3030-01-01 01:30:00")
48 | {
49 | $this->setStart($intervalStart);
50 | $this->setEnd($intervalEnd);
51 | }
52 |
53 | /**
54 | * @param string|DateTime|DruidTime $intervalStart
55 | */
56 | public function setStart($intervalStart = "1970-01-01 01:30:00")
57 | {
58 | if ( is_string($intervalStart ) )
59 | {
60 | $intervalStart = new DateTime( $intervalStart );
61 | }
62 |
63 | if ( is_a($intervalStart, 'DateTime') )
64 | {
65 | $intervalStart = new DruidTime( $intervalStart );
66 | }
67 |
68 | if ( is_a($intervalStart, 'DruidFamiliar\DruidTime') )
69 | {
70 | $this->intervalStart = $intervalStart;
71 | }
72 | else
73 | {
74 | throw new RuntimeException('Encountered unexpected start time. Expected either string, DateTime, or DruidTime.');
75 | }
76 | }
77 |
78 | /**
79 | * @param string|DateTime|DruidTime $intervalEnd
80 | */
81 | public function setEnd($intervalEnd = "3030-01-01 01:30:00")
82 | {
83 | if ( is_string($intervalEnd ) )
84 | {
85 | $intervalEnd = new DateTime( $intervalEnd );
86 | }
87 |
88 | if ( is_a($intervalEnd, 'DateTime') )
89 | {
90 | $intervalEnd = new DruidTime( $intervalEnd );
91 | }
92 |
93 | if ( is_a($intervalEnd, 'DruidFamiliar\DruidTime') )
94 | {
95 | $this->intervalEnd = $intervalEnd;
96 | }
97 | else
98 | {
99 | throw new RuntimeException('Encountered unexpected end time. Expected either string, DateTime, or DruidTime.');
100 | }
101 | }
102 |
103 |
104 | /**
105 | * @return string
106 | * @throws MissingParametersException
107 | * @throws UnexpectedTypeException
108 | */
109 | function __toString()
110 | {
111 | return $this->getIntervalsString();
112 | }
113 |
114 | /**
115 | * @return string
116 | * @throws MissingParametersException
117 | * @throws UnexpectedTypeException
118 | */
119 | public function getIntervalsString()
120 | {
121 | // Missing params
122 | $missingParams = array();
123 | if ( !isset( $this->intervalStart ) ) { $missingParams[] = 'intervalStart'; }
124 | if ( !isset( $this->intervalEnd ) ) { $missingParams[] = 'intervalEnd'; }
125 | if ( count( $missingParams ) > 0 ) { throw new MissingParametersException($missingParams); }
126 |
127 | // Invalid params
128 | if ( !$this->intervalStart instanceof DruidTime ) {
129 | throw new UnexpectedTypeException($this->intervalStart, 'DruidTime', 'For parameter intervalStart.');
130 | }
131 | if ( !$this->intervalEnd instanceof DruidTime ) {
132 | throw new UnexpectedTypeException($this->intervalEnd, 'DruidTime', 'For parameter intervalEnd.');
133 | }
134 |
135 | // Format
136 | return $this->intervalStart . '/' . $this->intervalEnd;
137 | }
138 |
139 |
140 | /**
141 | * @return DruidTime
142 | */
143 | public function getStart()
144 | {
145 | return $this->intervalStart;
146 | }
147 |
148 | /**
149 | * @return DruidTime
150 | */
151 | public function getEnd()
152 | {
153 | return $this->intervalEnd;
154 | }
155 |
156 | }
157 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryExecutor/DruidNodeDruidQueryExecutor.php:
--------------------------------------------------------------------------------
1 | "application/json;charset=utf-8");
55 |
56 | public function __construct($ip, $port, $endpoint = '/druid/v2/', $protocol = 'http', $httpMethod = 'POST') {
57 | $this->ip = $ip;
58 | $this->port = $port;
59 | $this->endpoint = $endpoint;
60 | $this->setProtocol($protocol);
61 | $this->setHttpMethod($httpMethod);
62 | }
63 |
64 | public function getBaseUrl()
65 | {
66 | $baseUrl = $this->protocol . '://' . $this->ip . ':' . $this->port;
67 | $url = $baseUrl . $this->endpoint;
68 | return $url;
69 | }
70 |
71 | /**
72 | * Create a Guzzle Request object using the given JSON parameters
73 | *
74 | * @param string $query JSON String
75 | * @return \Guzzle\Http\Message\RequestInterface
76 | * @throws \Exception
77 | */
78 | public function createRequest($query)
79 | {
80 | $client = new \Guzzle\Http\Client();
81 |
82 | $method = $this->httpMethod;
83 | $uri = $this->getBaseUrl();
84 | $headers = $this->getHeaders();
85 | $options = array();
86 |
87 | if ( $method === 'POST' )
88 | {
89 | $postBody = $query;
90 | $request = $client->createRequest( $method, $uri, $headers, $postBody, $options );
91 | }
92 | else if ( $method === 'GET' )
93 | {
94 | $request = $client->createRequest( $method, $uri, $headers, null, $options );
95 | if ( $query ) {
96 | $queryObject = json_decode($query, true);
97 | $query = $request->getQuery();
98 | foreach ($queryObject as $key => $val) {
99 | $query->set($key, $val);
100 | }
101 | }
102 | }
103 | else
104 | {
105 | throw new Exception('Unexpected HTTP Method: ' . $method);
106 | }
107 |
108 | return $request;
109 | }
110 |
111 | /**
112 | * Execute a Druid query using the provided query generator, parameters, and response payload handler.
113 | *
114 | * See DruidFamiliar\ResponseHandler\DoNothingResponseHandler.
115 | *
116 | * @param IDruidQueryGenerator $queryGenerator
117 | * @param IDruidQueryParameters $params
118 | * @param IDruidQueryResponseHandler $responseHandler
119 | * @return mixed
120 | */
121 | public function executeQuery(IDruidQueryGenerator $queryGenerator, IDruidQueryParameters $params, IDruidQueryResponseHandler $responseHandler)
122 | {
123 | $params->validate();
124 |
125 | $generatedQuery = $queryGenerator->generateQuery($params);
126 |
127 | // Create a request
128 | $request = $this->createRequest( $generatedQuery );
129 |
130 | // Send the request and parse the JSON response into an array
131 | try
132 | {
133 | $response = $request->send();
134 | }
135 | catch (\Guzzle\Http\Exception\CurlException $curlException)
136 | {
137 | throw new $curlException;
138 | }
139 |
140 | $formattedResponse = $responseHandler->handleResponse($response);
141 |
142 | return $formattedResponse;
143 | }
144 |
145 | /**
146 | * Get the HTTP Method.
147 | *
148 | * @return string
149 | */
150 | public function getHttpMethod()
151 | {
152 | return $this->httpMethod;
153 | }
154 |
155 | /**
156 | * Set the HTTP Method.
157 | *
158 | * Supported methods are: GET, POST
159 | *
160 | * @param $method
161 | * @throws \Exception
162 | */
163 | public function setHttpMethod($method)
164 | {
165 | $allowed_methods = array('GET', 'POST');
166 |
167 | $method = strtoupper( $method );
168 |
169 | if ( !in_array( $method, $allowed_methods ) ) {
170 | throw new Exception('Unsupported HTTP Method: ' . $method . '. Supported methods are: ' . join($allowed_methods, ', '));
171 | }
172 |
173 | $this->httpMethod = $method;
174 | }
175 |
176 | /**
177 | * Get the protocol.
178 | *
179 | * @return string
180 | */
181 | public function getProtocol()
182 | {
183 | return $this->protocol;
184 | }
185 |
186 | /**
187 | * Set the protocol.
188 | *
189 | * Supported protocols are: http, https
190 | *
191 | * @param string $protocol
192 | */
193 | public function setProtocol($protocol)
194 | {
195 | $allowedProtocols = array('http', 'https');
196 |
197 | $protocol = strtolower( $protocol );
198 |
199 | if ( !in_array( $protocol,$allowedProtocols ) ) {
200 | throw new Exception('Unsupported Protocol: ' . $protocol . '. Supported protocols are: ' . join($allowedProtocols, ', '));
201 | }
202 |
203 | $this->protocol = $protocol;
204 | }
205 |
206 | /**
207 | * @return String
208 | */
209 | public function getIp()
210 | {
211 | return $this->ip;
212 | }
213 |
214 | /**
215 | * @param String $ip
216 | */
217 | public function setIp($ip)
218 | {
219 | $this->ip = $ip;
220 | }
221 |
222 | /**
223 | * @return Number
224 | */
225 | public function getPort()
226 | {
227 | return $this->port;
228 | }
229 |
230 | /**
231 | * @param Number $port
232 | */
233 | public function setPort($port)
234 | {
235 | $this->port = $port;
236 | }
237 |
238 | /**
239 | * @return string
240 | */
241 | public function getEndpoint()
242 | {
243 | return $this->endpoint;
244 | }
245 |
246 | /**
247 | * @param string $endpoint
248 | */
249 | public function setEndpoint($endpoint)
250 | {
251 | $this->endpoint = $endpoint;
252 | }
253 |
254 | /**
255 | * @return array
256 | */
257 | public function getHeaders()
258 | {
259 | return $this->headers;
260 | }
261 |
262 | /**
263 | * @param array $headers
264 | */
265 | public function setHeaders(array $headers)
266 | {
267 | $this->headers = $headers;
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryExecutor/JSONDruidNodeDruidQueryExecutor.php:
--------------------------------------------------------------------------------
1 | ip = $ip;
55 | $this->port = $port;
56 | $this->endpoint = $endpoint;
57 | $this->protocol = $protocol;
58 | }
59 |
60 | /**
61 | * @return string
62 | */
63 | public function getBaseUrl()
64 | {
65 | $baseUrl = $this->protocol . '://' . $this->ip . ':' . $this->port;
66 | $url = $baseUrl . $this->endpoint;
67 | return $url;
68 | }
69 |
70 | /**
71 | * @param $query
72 | *
73 | * @return \Guzzle\Http\Message\RequestInterface
74 | */
75 | public function createRequest($query)
76 | {
77 | $client = new Client();
78 |
79 | $request = $client->post($this->getBaseUrl(), array("content-type" => "application/json"), json_encode($query));
80 |
81 | return $request;
82 | }
83 |
84 |
85 | public function executeQuery(IDruidQueryGenerator $queryGenerator, IDruidQueryParameters $params, IDruidQueryResponseHandler $responseHandler)
86 | {
87 | $params->validate();
88 |
89 | $generatedQuery = $queryGenerator->generateQuery($params);
90 |
91 | // Create a POST request
92 | $request = $this->createRequest($generatedQuery);
93 |
94 | // Send the request and parse the JSON response into an array
95 | try
96 | {
97 | $response = $request->send();
98 | }
99 | catch(CurlException $curlException)
100 | {
101 | throw new $curlException;
102 | }
103 |
104 | $data = $this->parseResponse($response);
105 |
106 | $formattedResponse = $responseHandler->handleResponse($data);
107 |
108 | return $formattedResponse;
109 | }
110 |
111 | /**
112 | * @param Response $rawResponse
113 | *
114 | * @return mixed
115 | */
116 | protected function parseResponse($rawResponse)
117 | {
118 | $formattedResponse = $rawResponse->json();
119 |
120 | return $formattedResponse;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryGenerator/GroupByQueryGenerator.php:
--------------------------------------------------------------------------------
1 | validate();
36 | $query = $params->getJSONString();
37 | return $query;
38 | }
39 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryGenerator/SegmentMetadataDruidQueryGenerator.php:
--------------------------------------------------------------------------------
1 | validate();
42 |
43 | $responseObj = array(
44 | 'queryType' => 'segmentMetadata',
45 | "dataSource" => $params->dataSource,
46 | "intervals" => $params->intervals->__toString()
47 | );
48 |
49 | $responseString = json_encode( $responseObj );
50 |
51 | return $responseString;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryGenerator/SimpleGroupByDruidQueryGenerator.php:
--------------------------------------------------------------------------------
1 | validate();
53 |
54 | $query = $this->queryTemplate;
55 |
56 | // Assemble the query instead
57 | $queryKeys = array();
58 |
59 | // We always have these keys
60 | $queryKeys[] = '"queryType": "{QUERYTYPE}"';
61 | $queryKeys[] = '"dataSource": "{DATASOURCE}"';
62 |
63 | if ( is_array( $params->granularity ) && count( $params->granularity ) > 0 ) {
64 | $queryKeys[] = '"granularity": {GRANULARITYSPEC.GRAN}';
65 | } else {
66 | $queryKeys[] = '"granularity": "{GRANULARITYSPEC.GRAN}"';
67 | }
68 |
69 | $queryKeys[] = '"dimensions": [ "{NON_TIME_DIMENSIONS}" ]';
70 |
71 | if ( count( $params->filters ) > 0 ) {
72 | $queryKeys[] = '"filter": {FILTERS}';
73 | }
74 |
75 | if ( count( $params->aggregators ) > 0 ) {
76 | $queryKeys[] = '"aggregations": [{AGGREGATORS}]';
77 | }
78 |
79 | if ( count( $params->postAggregators ) > 0 ) {
80 | $queryKeys[] = '"postAggregations": [{POSTAGGREGATORS}]';
81 | }
82 |
83 | $queryKeys[] = '"intervals": ["{INTERVALS}"]';
84 |
85 | $query = "{" . join(",\n", $queryKeys) . "}";
86 |
87 |
88 | $query = str_replace('{QUERYTYPE}', $params->queryType, $query);
89 |
90 | $query = str_replace('{DATASOURCE}', $params->dataSource, $query);
91 | $query = str_replace('{INTERVALS}', $params->intervals, $query);
92 |
93 |
94 | if ( is_array( $params->granularity ) && count( $params->granularity ) > 0 ) {
95 | $query = str_replace('{GRANULARITYSPEC.GRAN}', json_encode( $params->granularity ), $query);
96 | } else {
97 | $query = str_replace('{GRANULARITYSPEC.GRAN}', $params->granularity, $query);
98 | }
99 |
100 | $query = str_replace('{NON_TIME_DIMENSIONS}', join('","', $params->dimensions), $query);
101 | $query = str_replace('{FILTERS}', join(",", $params->filters), $query);
102 | $query = str_replace('{AGGREGATORS}', join(",", $params->aggregators), $query);
103 | $query = str_replace('{POSTAGGREGATORS}', join(",", $params->postAggregators), $query);
104 |
105 | return $query;
106 | }
107 |
108 | }
109 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryGenerator/TimeBoundaryDruidQueryGenerator.php:
--------------------------------------------------------------------------------
1 | validate();
32 |
33 | $responseObj = array(
34 | 'queryType' => 'timeBoundary',
35 | "dataSource" => $params->dataSource
36 | );
37 |
38 | $responseString = json_encode( $responseObj );
39 |
40 | return $responseString;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryParameters/GroupByQueryParameters.php:
--------------------------------------------------------------------------------
1 | queryType = 'groupBy';
119 | }
120 |
121 | /**
122 | * Class constructor
123 | */
124 | public function __construct()
125 | {
126 | $this->initialize();
127 | }
128 |
129 | /**
130 | * Validates the query has the necessary parameters
131 | *
132 | * @throws MissingParametersException
133 | */
134 | public function validate()
135 | {
136 | $flag = true;
137 | foreach($this->requiredParams as $param)
138 | {
139 | if(!isset($this->$param))
140 | {
141 | $this->missingParameters[] = $param;
142 | $flag = false;
143 | }
144 | else
145 | {
146 | $val = $this->$param;
147 | if(!is_array($val))
148 | {
149 | $val = trim($val);
150 | }
151 | if(empty($val))
152 | {
153 | $this->emptyParameters[] = $param;
154 | $flag = false;
155 | }
156 | }
157 | }
158 | if(count($this->missingParameters) > 0)
159 | {
160 | throw new MissingParametersException($this->missingParameters);
161 | }
162 | if(count($this->emptyParameters) > 0)
163 | {
164 | throw new EmptyParametersException($this->emptyParameters);
165 | }
166 | return $flag;
167 | }
168 |
169 | /**
170 | * Converts the current object into a JSON representation to be used as a query
171 | * @return mixed|string
172 | */
173 | public function getJSONString()
174 | {
175 | $retString = '{[DATA]}';
176 | $buffStringArray = array();
177 | foreach($this->allParameters as $param)
178 | {
179 | if(isset($this->$param))
180 | {
181 | $buffStringArray[] = "\"{$param}\":" . json_encode($this->$param);
182 | }
183 | }
184 | $buffString = implode(',', $buffStringArray);
185 | $retString = str_replace('[DATA]', $buffString, $retString);
186 | return $retString;
187 | }
188 |
189 | /**
190 | * Returns the aggregations
191 | *
192 | * @return array
193 | */
194 | public function getAggregations()
195 | {
196 | return $this->aggregations;
197 | }
198 |
199 | /**
200 | * Sets the aggregations
201 | *
202 | * @param array $aggregations
203 | *
204 | * @return $this
205 | */
206 | public function setAggregations(array $aggregations)
207 | {
208 | foreach($aggregations as $aggregator)
209 | {
210 | $this->addAggregator($aggregator);
211 | }
212 | return $this;
213 | }
214 |
215 | /**
216 | * Adds a new aggregator to the aggregators array
217 | *
218 | * @param stdClass $aggregator
219 | *
220 | * @return $this
221 | */
222 | public function addAggregator($aggregator)
223 | {
224 | if(is_object($aggregator))
225 | {
226 | $this->aggregations[] = $aggregator;
227 | }
228 | return $this;
229 | }
230 |
231 | /**
232 | * Returns the context
233 | *
234 | * @return array
235 | */
236 | public function getContext()
237 | {
238 | return $this->context;
239 | }
240 |
241 | /**
242 | * Sets the context
243 | *
244 | * @param array $contexts
245 | *
246 | * @return $this
247 | */
248 | public function setContext(array $contexts)
249 | {
250 | foreach($contexts as $context)
251 | {
252 | $this->addContext($context);
253 | }
254 | return $this;
255 | }
256 |
257 | /**
258 | * Adds a new context to the contexts array
259 | *
260 | * @param string $context
261 | *
262 | * @return $this
263 | */
264 | public function addContext($context)
265 | {
266 | $this->context[] = $context;
267 | return $this;
268 | }
269 |
270 | /**
271 | * Returns the dataSource
272 | *
273 | * @return string
274 | */
275 | public function getDataSource()
276 | {
277 | return $this->dataSource;
278 | }
279 |
280 | /**
281 | * Sets the dataSource
282 | *
283 | * @param string $dataSource
284 | *
285 | * @return $this
286 | */
287 | public function setDataSource($dataSource)
288 | {
289 | $this->dataSource = $dataSource;
290 | return $this;
291 | }
292 |
293 | /**
294 | * Returns the dimensions
295 | *
296 | * @return array
297 | */
298 | public function getDimensions()
299 | {
300 | return $this->dimensions;
301 | }
302 |
303 | /**
304 | * Sets the dimensions
305 | *
306 | * @param array $dimensions
307 | *
308 | * @return $this
309 | */
310 | public function setDimensions(array $dimensions)
311 | {
312 | $this->dimensions = $dimensions;
313 | return $this;
314 | }
315 |
316 | /**
317 | * Adds a new dimension to the dimensions array
318 | *
319 | * @param string $dimension
320 | *
321 | * @return $this
322 | */
323 | public function addDimension($dimension)
324 | {
325 | $this->dimensions[] = $dimension;
326 | return $this;
327 | }
328 |
329 | /**
330 | * Returns the filter
331 | *
332 | * @return stdClass
333 | */
334 | public function getFilter()
335 | {
336 | return $this->filter;
337 | }
338 |
339 | /**
340 | * Sets the filter
341 | *
342 | * @param stdClass $filter
343 | *
344 | * @return $this
345 | */
346 | public function setFilter($filter)
347 | {
348 | if(is_object($filter))
349 | {
350 | $this->filter = $filter;
351 | }
352 | return $this;
353 | }
354 |
355 | /**
356 | * Returns the granularity
357 | *
358 | * @return string
359 | */
360 | public function getGranularity()
361 | {
362 | return $this->granularity;
363 | }
364 |
365 | /**
366 | * Sets the granularity
367 | *
368 | * @param string $granularity
369 | *
370 | * @return $this
371 | */
372 | public function setGranularity($granularity)
373 | {
374 | $this->granularity = $granularity;
375 | return $this;
376 | }
377 |
378 | /**
379 | * Returns the having
380 | *
381 | * @return stdClass
382 | */
383 | public function getHaving()
384 | {
385 | return $this->having;
386 | }
387 |
388 | /**
389 | * Sets the having
390 | *
391 | * @param stdClass $having
392 | *
393 | * @return $this
394 | */
395 | public function setHaving($having)
396 | {
397 | if(is_object($having))
398 | {
399 | $this->having = $having;
400 | }
401 | return $this;
402 | }
403 |
404 | /**
405 | * Returns the intervals
406 | *
407 | * @return array
408 | */
409 | public function getIntervals()
410 | {
411 | return $this->intervals;
412 | }
413 |
414 | /**
415 | * Sets the intervals
416 | *
417 | * @param array $intervals
418 | *
419 | * @return $this
420 | */
421 | public function setIntervals(array $intervals)
422 | {
423 | foreach($intervals as $interval)
424 | {
425 | $this->addInterval($interval);
426 | }
427 | return $this;
428 | }
429 |
430 | /**
431 | * Adds a new interval to the intervals array
432 | *
433 | * @param string $interval
434 | *
435 | * @return $this
436 | */
437 | public function addInterval($interval)
438 | {
439 | $this->intervals[] = $interval;
440 | return $this;
441 | }
442 |
443 | /**
444 | * Returns the limitSpec
445 | *
446 | * @return stdClass
447 | */
448 | public function getLimitSpec()
449 | {
450 | return $this->limitSpec;
451 | }
452 |
453 | /**
454 | * Sets the limitSpec
455 | *
456 | * @param stdClass $limitSpec
457 | *
458 | * @return $this
459 | */
460 | public function setLimitSpec($limitSpec)
461 | {
462 | $this->limitSpec = $limitSpec;
463 | return $this;
464 | }
465 |
466 | /**
467 | * Returns the postAggregations
468 | *
469 | * @return array
470 | */
471 | public function getPostAggregations()
472 | {
473 | return $this->postAggregations;
474 | }
475 |
476 | /**
477 | * Sets the postAggregations
478 | *
479 | * @param array $postAggregations
480 | *
481 | * @return $this
482 | */
483 | public function setPostAggregations(array $postAggregations)
484 | {
485 | foreach($postAggregations as $aggregator)
486 | {
487 | $this->addPostAggregator($aggregator);
488 | }
489 | return $this;
490 | }
491 |
492 | /**
493 | * Adds a new postaggregator to the postaggregators array
494 | *
495 | * @param stdClass $aggregator
496 | *
497 | * @return $this
498 | */
499 | public function addPostAggregator($aggregator)
500 | {
501 | if(is_object($aggregator))
502 | {
503 | $this->postAggregations[] = $aggregator;
504 | }
505 | return $this;
506 | }
507 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryParameters/SegmentMetadataQueryParameters.php:
--------------------------------------------------------------------------------
1 | dataSource = $dataSource;
29 | $this->intervals = new Interval($intervalStart, $intervalEnd);
30 | }
31 |
32 |
33 | /**
34 | * @throws MissingParametersException
35 | */
36 | public function validate()
37 | {
38 | $missingParams = array();
39 |
40 | if(!isset($this->dataSource))
41 | {
42 | $missingParams[] = 'dataSource';
43 | }
44 | if(!isset($this->intervals))
45 | {
46 | $missingParams[] = 'interval';
47 | }
48 |
49 | if(count($missingParams) > 0)
50 | {
51 | throw new MissingParametersException($missingParams);
52 | }
53 |
54 | if(!$this->intervals instanceof Interval)
55 | {
56 | throw new UnexpectedTypeException($this->intervals, 'DruidFamiliar\Interval', 'For parameter intervals.');
57 | }
58 |
59 | return true;
60 | }
61 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryParameters/SimpleGroupByQueryParameters.php:
--------------------------------------------------------------------------------
1 | setFilters(...).
71 | *
72 | * @var array
73 | */
74 | public $filters = array();
75 |
76 | /**
77 | * Array of json encoded strings
78 | *
79 | * Intended to be set through $this->setAggregators(...).
80 | *
81 | * @var array
82 | */
83 | public $aggregators = array();
84 |
85 |
86 | /**
87 | * Array of json encoded strings
88 | *
89 | * Intended to be set through $this->setPostAggregators(...).
90 | *
91 | * @var array
92 | */
93 | public $postAggregators = array();
94 |
95 |
96 | public function setFilePath($path) {
97 | $fileInfo = pathinfo($path);
98 | $this->baseDir = $fileInfo['dirname'];
99 | $this->filePath = $fileInfo['basename'];
100 | }
101 |
102 | /**
103 | * Configure the aggregators for this request.
104 | *
105 | * @param $aggregatorsArray array PHP Array of aggregators
106 | */
107 | public function setAggregators($aggregatorsArray)
108 | {
109 | $this->aggregators = array();
110 |
111 | foreach( $aggregatorsArray as $aggregator)
112 | {
113 | $this->aggregators[] = json_encode( $aggregator );
114 | }
115 |
116 | }
117 |
118 | /**
119 | * Configure the filters for this request.
120 | *
121 | * @param $filtersArray PHP Array of aggregators
122 | */
123 | public function setFilters($filtersArray)
124 | {
125 | $this->filters = array();
126 |
127 | foreach( $filtersArray as $filter)
128 | {
129 | $this->filters[] = json_encode( $filter );
130 | }
131 |
132 | }
133 |
134 | /**
135 | * Configure the post aggregators for this request.
136 | *
137 | * @param $postAggregatorsArray array PHP Array of post aggregators
138 | */
139 | public function setPostAggregators($postAggregatorsArray)
140 | {
141 | $this->postAggregators = array();
142 |
143 | foreach( $postAggregatorsArray as $postAggregator)
144 | {
145 | $this->postAggregators[] = json_encode( $postAggregator );
146 | }
147 |
148 | }
149 |
150 | /**
151 | * @throws MissingParametersException
152 | */
153 | public function validate()
154 | {
155 | $this->validateForMissingParameters();
156 |
157 | $this->validateForEmptyParameters();
158 | }
159 |
160 | /**
161 | * @throws MissingParametersException
162 | */
163 | protected function validateForMissingParameters()
164 | {
165 | // Validate missing params
166 | $missingParams = array();
167 |
168 | $requiredParams = array(
169 | 'queryType',
170 | 'dataSource',
171 | 'intervals',
172 | 'granularity',
173 | 'dimensions',
174 | 'aggregators',
175 | 'filters',
176 | 'postAggregators'
177 | );
178 |
179 | foreach ($requiredParams as $requiredParam) {
180 | if ( !isset( $this->$requiredParam ) ) {
181 | $missingParams[] = $requiredParam;
182 | }
183 | }
184 |
185 | if ( count($missingParams) > 0 ) {
186 | throw new \DruidFamiliar\Exception\MissingParametersException($missingParams);
187 | }
188 | }
189 |
190 | /**
191 | * @throws MissingParametersException
192 | */
193 | protected function validateForEmptyParameters()
194 | {
195 | // Validate empty params
196 | $emptyParams = array();
197 |
198 | $requiredNonEmptyParams = array(
199 | 'queryType',
200 | 'dataSource'
201 | );
202 |
203 | foreach ($requiredNonEmptyParams as $requiredNonEmptyParam) {
204 | if ( !isset( $this->$requiredNonEmptyParam ) ) {
205 | $emptyParams[] = $requiredNonEmptyParam;
206 | }
207 | }
208 |
209 | if ( count($emptyParams) > 0 ) {
210 | throw new \DruidFamiliar\Exception\MissingParametersException($emptyParams);
211 | }
212 | }
213 |
214 | /**
215 | * @return Interval
216 | */
217 | public function getIntervals()
218 | {
219 | return $this->intervals;
220 | }
221 |
222 | /**
223 | * @param Interval $intervals
224 | */
225 | public function setIntervals(Interval $intervals)
226 | {
227 | $this->intervals = $intervals;
228 | }
229 |
230 | /**
231 | * @param string|\DateTime|DruidTime $intervalStart
232 | * @param string|\DateTime|DruidTime $intervalEnd
233 | */
234 | public function setIntervalByStartAndEnd($intervalStart, $intervalEnd)
235 | {
236 | $this->setIntervals(new Interval($intervalStart, $intervalEnd));
237 | }
238 |
239 | /**
240 | * Adjusts the datetime to make the interval "exclusive" of the datetime.
241 | * e.g., given
242 | * startDateTime=2014-06-18T12:30:01Z and
243 | * endDateTime=2014-06-18T01:00:00Z
244 | * return and Interval containing
245 | * startDateTime=2014-06-18T12:30:00Z and
246 | * endDateTime=2014-06-18T01:00:01Z
247 | *
248 | * @param $startDateTime
249 | * @param $endDateTime
250 | * @return void
251 | */
252 | public function setIntervalForQueryingUsingExclusiveTimes($startDateTime, $endDateTime)
253 | {
254 | $adjustedEndDateTime = new \DateTime($endDateTime);
255 | $adjustedEndDateTime->add(new \DateInterval('PT1S'));
256 |
257 | $this->setIntervals(new Interval($startDateTime, $adjustedEndDateTime));
258 | }
259 | }
260 |
--------------------------------------------------------------------------------
/src/DruidFamiliar/QueryParameters/TimeBoundaryQueryParameters.php:
--------------------------------------------------------------------------------
1 | dataSource = $dataSource;
20 | }
21 |
22 | /**
23 | * @throws MissingParametersException
24 | */
25 | public function validate()
26 | {
27 | $missingParams = array();
28 |
29 | if(!isset($this->dataSource))
30 | {
31 | $missingParams[] = 'dataSource';
32 | }
33 |
34 | if(count($missingParams) > 0)
35 | {
36 | throw new MissingParametersException($missingParams);
37 | }
38 |
39 | return true;
40 | }
41 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/Response/GroupByResponse.php:
--------------------------------------------------------------------------------
1 | data;
37 | }
38 |
39 | /**
40 | * Sets the data
41 | *
42 | * @param array $data
43 | *
44 | * @return $this
45 | */
46 | public function setData(array $data)
47 | {
48 | foreach($data as $anObject)
49 | {
50 | $this->addData($anObject);
51 | }
52 | return $this;
53 | }
54 |
55 | /**
56 | * Adds an element to the data array
57 | *
58 | * @param stdClass $data
59 | *
60 | * @return $this
61 | */
62 | public function addData($data)
63 | {
64 | if(is_object($data))
65 | {
66 | $complete = true;
67 | foreach($this->requiredObjectFields as $property)
68 | {
69 | if(!isset($data->$property))
70 | {
71 | $complete = false;
72 | break;
73 | }
74 | }
75 | if($complete)
76 | {
77 | $this->data[] = $data;
78 | }
79 | }
80 | else
81 | {
82 | if(is_array($data))
83 | {
84 | $complete = true;
85 | foreach($this->requiredObjectFields as $property)
86 | {
87 | if(!isset($data[$property]))
88 | {
89 | $complete = false;
90 | break;
91 | }
92 | }
93 | if($complete)
94 | {
95 | $this->data[] = $data;
96 | }
97 | }
98 | }
99 | return $this;
100 | }
101 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/Response/TimeBoundaryResponse.php:
--------------------------------------------------------------------------------
1 | json();
31 |
32 | $responseObj = new GroupByResponse();
33 | $responseObj->setData($response);
34 |
35 | return $responseObj;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/ResponseHandler/JsonFormattingResponseHandler.php:
--------------------------------------------------------------------------------
1 | json();
27 | return $response;
28 | }
29 | }
--------------------------------------------------------------------------------
/src/DruidFamiliar/ResponseHandler/TimeBoundaryResponseHandler.php:
--------------------------------------------------------------------------------
1 | json();
30 |
31 | if(empty($response))
32 | {
33 | throw new Exception('Unknown data source.');
34 | }
35 |
36 | if(!isset ($response[0]['result']))
37 | {
38 | throw new Exception('Unexpected response format.');
39 | }
40 | if(!isset ($response[0]['result']['minTime']))
41 | {
42 | throw new Exception('Unexpected response format - response did not include minTime.');
43 | }
44 | if(!isset ($response[0]['result']['maxTime']))
45 | {
46 | throw new Exception('Unexpected response format - response did not include maxTime.');
47 | }
48 |
49 | $responseObj = new TimeBoundaryResponse();
50 |
51 | $responseObj->minTime = $response[0]['result']['minTime'];
52 | $responseObj->maxTime = $response[0]['result']['maxTime'];
53 |
54 | return $responseObj;
55 | }
56 |
57 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/Abstracts/AbstractTaskParametersTest.php:
--------------------------------------------------------------------------------
1 | getMockForAbstractClass('DruidFamiliar\Abstracts\AbstractTaskParameters');
17 | $stub->expects($this->once())->method('validate')->will($this->returnValue(true));
18 |
19 | $isValid = $stub->isValid();
20 |
21 | $this->assertTrue($isValid);
22 | }
23 |
24 | public function testIsNotValid()
25 | {
26 | /**
27 | * @var AbstractTaskParameters $stub
28 | */
29 | $stub = $this->getMockForAbstractClass('DruidFamiliar\Abstracts\AbstractTaskParameters');
30 | $stub->expects($this->once())->method('validate')->will($this->throwException(new MissingParametersException(array('a_missing_parameter_name'))));
31 |
32 | $isValid = $stub->isValid();
33 |
34 | $this->assertFalse($isValid);
35 | }
36 | }
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/DruidTimeTest.php:
--------------------------------------------------------------------------------
1 | getMock('DruidFamiliar\DruidTime', array('formatTimeForDruid'), array(new \DateTime('2014-01-01T04:20')));
21 |
22 | $mockInterval
23 | ->expects($this->once())
24 | ->method('formatTimeForDruid');
25 |
26 | /**
27 | * @var Interval $mockInterval
28 | */
29 | $mockInterval->__toString();
30 | }
31 |
32 | public function testFormatTimeForDruid()
33 | {
34 | $interval = new DruidTime(new DateTime('2014-01-01'));
35 | $this->assertEquals('2014-01-01T00:00:00Z', $interval->formatTimeForDruid());
36 |
37 | $interval = new DruidTime(new DateTime('2014-01-01 04:20'));
38 | $this->assertEquals('2014-01-01T04:20:00Z', $interval->formatTimeForDruid());
39 |
40 | $interval = new DruidTime(new DateTime('2014-01-01T04:20'));
41 | $this->assertEquals('2014-01-01T04:20:00Z', $interval->formatTimeForDruid());
42 | }
43 |
44 | /**
45 | * Standard date time strings will default to local time zone.
46 | *
47 | * We want UTC time only. At least the output should not be modified.
48 | */
49 | public function testCanUseStandardDateTimeStrings()
50 | {
51 | $interval = new DruidTime(new DateTime('2014-01-01 00:00'));
52 |
53 | $this->assertEquals('2014-01-01T00:00:00Z', $interval->formatTimeForDruid());
54 | }
55 |
56 | /**
57 | * Common ISO style seen on many web services, including Druid.
58 | *
59 | * Take ISO, replace time zone offsets with 'Z'. We always work in Zulu/UTC/GMT time here.
60 | *
61 | * Y-m-d\TH:i:s\Z
62 | *
63 | * eBay and Amazon also use this style.
64 | *
65 | */
66 | public function testCanUseDruidDateTimeStrings()
67 | {
68 | $interval = new DruidTime(new DateTime('2014-01-01T00:00:10Z'));
69 |
70 | $this->assertEquals('2014-01-01T00:00:10Z', $interval->formatTimeForDruid());
71 | }
72 |
73 | /**
74 | * Actual ISO 8601 standard spec includes time zone offsets.
75 | *
76 | * Y-m-d\TH:i:sO
77 | *
78 | */
79 | public function testCanUseISO8601DateTimeStrings()
80 | {
81 | $interval = new DruidTime(new DateTime('2014-01-01T00:20:00-0000'));
82 |
83 | $this->assertEquals('2014-01-01T00:20:00Z', $interval->formatTimeForDruid());
84 | }
85 |
86 | public function testCanSetWithString()
87 | {
88 | $interval = new DruidTime( '2014-01-01T00:20' );
89 |
90 | $this->assertEquals('2014-01-01T00:20:00Z', $interval->formatTimeForDruid());
91 | }
92 |
93 | public function testCanSetWithDateTime()
94 | {
95 | $interval = new DruidTime( new DateTime( '2014-01-01T00:20' ) );
96 |
97 | $this->assertEquals('2014-01-01T00:20:00Z', $interval->formatTimeForDruid());
98 | }
99 |
100 | public function testCanSetWithAnotherDruidTime()
101 | {
102 | $dtA = new DruidTime( '2014-01-02T00:20' );
103 | $interval = new DruidTime( $dtA );
104 |
105 | $this->assertEquals('2014-01-02T00:20:00Z', $interval->formatTimeForDruid());
106 |
107 | }
108 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/Exception/EmptyParametersExceptionTest.php:
--------------------------------------------------------------------------------
1 | getMessage();
26 |
27 | $this->assertContains('Empty parameters', $msg, '', true); // Case insensitive
28 | $this->assertContains('param1', $msg, '', false); // Case sensitive (they are parameters!)
29 | $this->assertContains('param2', $msg, '', false); // Case sensitive (they are parameters!)
30 | }
31 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/Exception/MissingParametersExceptionTest.php:
--------------------------------------------------------------------------------
1 | getMessage();
15 |
16 | $this->assertContains('Missing parameters', $msg, '', true); // Case insensitive
17 | $this->assertContains('param1', $msg, '', false); // Case sensitive (they are parameters!)
18 | $this->assertContains('param2', $msg, '', false); // Case sensitive (they are parameters!)
19 | }
20 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/IntervalTest.php:
--------------------------------------------------------------------------------
1 | getMock('DruidFamiliar\Interval', array('getIntervalsString'), array('2014-01-01T04:20', '2015-01-01T4:20'));
18 |
19 | $mockInterval->expects($this->once())->method('getIntervalsString');
20 |
21 | /**
22 | * @var Interval $mockInterval
23 | */
24 | $mockInterval->__toString();
25 |
26 | }
27 |
28 | public function testGetIntervalsString()
29 | {
30 | $interval = new Interval('2014-01-01', '2015-01-01');
31 | $this->assertEquals('2014-01-01T00:00:00Z/2015-01-01T00:00:00Z', $interval->getIntervalsString());
32 |
33 | $interval = new Interval('2014-01-01 04:20', '2015-01-01 4:20');
34 | $this->assertEquals('2014-01-01T04:20:00Z/2015-01-01T04:20:00Z', $interval->getIntervalsString());
35 |
36 | $interval = new Interval('2014-01-01T04:20', '2015-01-01T4:20');
37 | $this->assertEquals('2014-01-01T04:20:00Z/2015-01-01T04:20:00Z', $interval->getIntervalsString());
38 | }
39 |
40 | /**
41 | * Standard date time strings will default to local time zone.
42 | *
43 | * We want UTC time only. At least the output should not be modified.
44 | */
45 | public function testCanUseStandardDateTimeStrings()
46 | {
47 | $interval = new Interval('2014-01-01 00:00', '2015-01-01 04:20');
48 |
49 | $this->assertEquals('2014-01-01T00:00:00Z/2015-01-01T04:20:00Z', $interval->getIntervalsString());
50 | }
51 |
52 | /**
53 | * Common ISO style seen on many web services, including Druid.
54 | *
55 | * Take ISO, replace time zone offsets with 'Z'. We always work in Zulu/UTC/GMT time here.
56 | *
57 | * Y-m-d\TH:i:s\Z
58 | *
59 | * eBay and Amazon also use this style.
60 | *
61 | */
62 | public function testCanUseDruidDateTimeStrings()
63 | {
64 | $interval = new Interval('2014-01-01T00:00:00Z', '2015-01-01T04:20:00Z');
65 |
66 | $this->assertEquals('2014-01-01T00:00:00Z/2015-01-01T04:20:00Z', $interval->getIntervalsString());
67 | }
68 |
69 | /**
70 | * Actual ISO 8601 standard spec includes time zone offsets.
71 | *
72 | * Y-m-d\TH:i:sO
73 | *
74 | */
75 | public function testCanUseISO8601DateTimeStrings()
76 | {
77 | $interval = new Interval('2014-01-01T00:00:00-0000', '2015-01-01T04:20:00-0700');
78 |
79 | $this->assertEquals('2014-01-01T00:00:00Z/2015-01-01T04:20:00Z', $interval->getIntervalsString());
80 | }
81 |
82 | public function testGetIntervalsStringWithMissingData()
83 | {
84 | $interval = new Interval('2014-01-01T00:00:00-0000', '2015-01-01T04:20:00-0700');
85 | $interval->intervalStart = NULL;
86 | $this->setExpectedException('DruidFamiliar\Exception\MissingParametersException', "intervalStart");
87 | $interval->getIntervalsString();
88 | }
89 |
90 | public function testGetIntervalsStringWithInvalidData()
91 | {
92 | $interval = new Interval('2014-01-01T00:00:00-0000', '2015-01-01T04:20:00-0700');
93 | $interval->intervalStart = '2014-01-01T00:00:00-0000';
94 | $this->setExpectedException('DruidFamiliar\Exception\UnexpectedTypeException', "intervalStart");
95 | $interval->getIntervalsString();
96 | }
97 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryExecutor/DruidNodeDruidQueryExecutorTest.php:
--------------------------------------------------------------------------------
1 | getBaseUrl();
25 | $this->assertEquals('https://1.2.3.4:1234/home/', $b);
26 | }
27 |
28 | /**
29 | * @depends testGetBaseUrlAssemblesCorrectEndpoint
30 | */
31 | public function testDefaultsToDruidV2Endpoint()
32 | {
33 | $c = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
34 | $b = $c->getBaseUrl();
35 | $this->assertEquals('http://1.2.3.4:1234/druid/v2/', $b);
36 | }
37 |
38 | /**
39 | * @depends testGetBaseUrlAssemblesCorrectEndpoint
40 | */
41 | public function testDefaultsToHttp()
42 | {
43 | $c = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234', '/home/');
44 | $b = $c->getBaseUrl();
45 | $h = array("content-type" => "application/json;charset=utf-8");
46 | $this->assertEquals('http://1.2.3.4:1234/home/', $b);
47 | $this->assertEquals($h, $c->getHeaders());
48 | }
49 |
50 | public function testCreateRequest()
51 | {
52 | $c = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234', '/mypath/');
53 | $queryGenerator = new TimeBoundaryDruidQueryGenerator();
54 | $params = new TimeBoundaryQueryParameters('some-datasource');
55 | $query = $queryGenerator->generateQuery($params);
56 |
57 | $req = $c->createRequest( $query );
58 |
59 | $this->assertEquals('1.2.3.4', $req->getHost() );
60 | $this->assertEquals('POST', $req->getMethod() );
61 | $this->assertEquals('/mypath/', $req->getPath() );
62 | $this->assertEquals('1234', $req->getPort() );
63 | }
64 |
65 | public function testExecuteQueryPassesResponseToHandleResponse()
66 | {
67 | // Create fake json response
68 | $mockResponse = new Response(200);
69 |
70 | // Create fake request
71 | $mockRequest = $this->getMockBuilder('MockRequest')
72 | ->setMethods(array('send'))
73 | ->getMock();
74 | $mockRequest->expects($this->once())
75 | ->method('send')
76 | ->willReturn($mockResponse);
77 |
78 | // Create fake connection
79 | $mockDruidQueryExecutor = $this->getMockBuilder('\DruidFamiliar\QueryExecutor\DruidNodeDruidQueryExecutor')
80 | ->setConstructorArgs(array('1.2.3.4', '1234'))
81 | ->setMethods(array('createRequest'))
82 | ->getMock();
83 | $mockDruidQueryExecutor->expects($this->once())
84 | ->method('createRequest')
85 | ->willReturn( $mockRequest );
86 | /**
87 | * @var \DruidFamiliar\QueryExecutor\DruidNodeDruidQueryExecutor $mockDruidQueryExecutor
88 | */
89 |
90 | // Create fake query params
91 | $mockQueryParams = $this->getMockBuilder('DruidFamiliar\Interfaces\IDruidQueryParameters')
92 | ->getMock();
93 |
94 | // Create fake query generator
95 | $mockGeneratedQuery = '{"hey":123}';
96 | $mockQueryGenerator = $this->getMockBuilder('DruidFamiliar\Interfaces\IDruidQueryGenerator')
97 | ->setMethods(array('generateQuery'))
98 | ->getMock();
99 | // Expect it to be called with given query params and return the json body
100 | $mockQueryGenerator->expects($this->once())
101 | ->method('generateQuery')
102 | ->with($mockQueryParams)
103 | ->willReturn($mockGeneratedQuery);
104 |
105 | // Create fake response handler to verify it is called with the returned json body
106 | $mockResponseHandler = $this->getMock('DruidFamiliar\Interfaces\IDruidQueryResponseHandler');
107 | $mockResponseHandler->expects($this->once())
108 | ->method('handleResponse')
109 | ->with($mockResponse);
110 |
111 | $mockDruidQueryExecutor->executeQuery($mockQueryGenerator, $mockQueryParams, $mockResponseHandler);
112 | }
113 |
114 | public function testDefaultsToPostMethod()
115 | {
116 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
117 | $this->assertEquals('POST', $a->getHttpMethod());
118 | }
119 |
120 | public function testSendingUsingPostMethod()
121 | {
122 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
123 | $a->setHttpMethod('POST');
124 | $request = $a->createRequest('{"hey":123}');
125 | $this->assertEquals( 'POST', $request->getMethod() );
126 | }
127 |
128 | public function testSendingUsingPostMethodIsCaseInsensitive()
129 | {
130 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
131 | $a->setHttpMethod('post');
132 | $request = $a->createRequest('{"hey":123}');
133 | $this->assertEquals( 'POST', $request->getMethod() );
134 | }
135 |
136 | public function testProvidesBodyWhenPosting()
137 | {
138 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
139 | $a->setHttpMethod('POST');
140 | $request = $a->createRequest('{"hey":123}');
141 | $this->assertEquals( 'POST', $request->getMethod() );
142 |
143 | $this->assertContains( 'hey', $request->getBody()->__toString() );
144 | $this->assertContains( '123', $request->getBody()->__toString() );
145 | }
146 |
147 | public function testSendingUsingGetMethod()
148 | {
149 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
150 | $a->setHttpMethod('GET');
151 | $request = $a->createRequest('{"hey":123}');
152 | $this->assertEquals( 'GET', $request->getMethod() );
153 | }
154 |
155 | public function testSendingUsingGetMethodIsCaseInsensitive()
156 | {
157 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
158 | $a->setHttpMethod('get');
159 | $request = $a->createRequest('{"hey":123}');
160 | $this->assertEquals( 'GET', $request->getMethod() );
161 |
162 | }
163 |
164 | public function testSendingUsingGetMethodPutsRequestInQueryParameters()
165 | {
166 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
167 | $a->setHttpMethod('GET');
168 | $a->setEndPoint('/somewhere/some/place');
169 | $request = $a->createRequest('{"hey":123}');
170 |
171 | $query = $request->getQuery()->getAll();
172 | $this->assertArrayHasKey('hey', $query );
173 | $this->assertEquals( '123', $query['hey'] );
174 | }
175 |
176 | public function testSendingUsingGetMethodMaintainsQueryParameters()
177 | {
178 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
179 | $a->setHttpMethod('GET');
180 | $a->setEndPoint('/somewhere/some/place?query=test&stuff=works');
181 | $request = $a->createRequest('{"hey":123}');
182 |
183 | $query = $request->getQuery()->getAll();
184 | $this->assertArrayHasKey('query', $query );
185 | $this->assertEquals( 'test', $query['query'] );
186 | $this->assertArrayHasKey('stuff', $query );
187 | $this->assertEquals( 'works', $query['stuff'] );
188 |
189 | // Does not stomp the query params from request
190 | $this->assertArrayHasKey('hey', $query );
191 | $this->assertEquals( '123', $query['hey'] );
192 | }
193 |
194 | public function testSendingUsingGetMethodPrefersRequestOverQueryParameters()
195 | {
196 | $a = new DruidNodeDruidQueryExecutor('1.2.3.4', '1234');
197 | $a->setHttpMethod('GET');
198 | $a->setEndPoint('/somewhere/some/place?hey=abc');
199 | $request = $a->createRequest('{"hey":123}');
200 |
201 | $query = $request->getQuery()->getAll();
202 | // Does not stomp the query params from request
203 | $this->assertArrayHasKey('hey', $query );
204 | $this->assertEquals( '123', $query['hey'] );
205 | $this->assertNotEquals( 'abc', $query['hey'] );
206 | }
207 | }
208 |
209 |
210 |
211 |
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryGenerator/GroupByQueryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | setDataSource('referral-visit-old-format');
28 | $parametersInstance->setGranularity('all');
29 | $parametersInstance->setDimensions(array('facility_id', 'referral_id', 'group'));
30 |
31 | $filter = new stdClass();
32 | $filter->type = 'selector';
33 | $filter->dimension = 'company_id';
34 | $filter->value = 1;
35 | $parametersInstance->setFilter($filter);
36 |
37 | $anAggregation = new stdClass();
38 | $anAggregation->type = 'longSum';
39 | $anAggregation->name = 'quantity';
40 | $anAggregation->fieldName = 'count';
41 |
42 | $parametersInstance->setAggregations(array($anAggregation));
43 | $parametersInstance->setIntervals(array('2008-01-01T00:00:00.000/2012-01-03T00:00:00.000'));
44 |
45 | $queryInstance = new GroupByQueryGenerator();
46 | $expectedQuery = '{"queryType":"groupBy","dataSource":"referral-visit-old-format","dimensions":["facility_id","referral_id","group"],"granularity":"all","filter":{"type":"selector","dimension":"company_id","value":1},"aggregations":[{"type":"longSum","name":"quantity","fieldName":"count"}],"intervals":["2008-01-01T00:00:00.000\/2012-01-03T00:00:00.000"]}';
47 |
48 | $query = $queryInstance->generateQuery($parametersInstance);
49 | $this->assertEquals($expectedQuery, $query);
50 | }
51 |
52 | /**
53 | * @expectedException Exception
54 | */
55 | public function testGenerateQueryInstanceofMismatch()
56 | {
57 | $paramsInstance = $this->getMock('DruidFamiliar\Interfaces\IDruidQueryParameters');
58 |
59 | $queryInstance = new GroupByQueryGenerator();
60 | $queryInstance->generateQuery($paramsInstance);
61 | }
62 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryGenerator/SegmentMetadataDruidQueryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | generateQuery($p);
20 |
21 | $query = json_decode( $query, true );
22 |
23 | $this->assertArrayHasKey('queryType', $query);
24 | $this->assertArrayHasKey('intervals', $query);
25 | $this->assertArrayHasKey('dataSource', $query, "Generated query must include required parameters.");
26 |
27 | $this->assertEquals( 'segmentMetadata', $query['queryType'], "Generated query must have segmentMetadata for its queryType.");
28 | $this->assertEquals( $mockDataSourceName, $query['dataSource'], "Generated query must use provided dataSource.");
29 | $this->assertEquals('1970-01-01T01:30:00Z/3030-01-01T01:30:00Z', $query['intervals'] );
30 | }
31 |
32 | }
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryGenerator/SimpleGroupByDruidQueryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | setIntervalByStartAndEnd('1981-01-01T4:20', '2012-03-01T3:00');
19 | $params->granularityType = 'uniform';
20 | $params->granularity = 'DAY';
21 | $params->dataSource = $this->mockDataSourceName;
22 | $params->format = 'json';
23 | $params->timeDimension = 'date_dim';
24 | $params->dimensions = array('one_dim', 'two_dim');
25 |
26 | $params->setFilePath('/another/file/path/to/a/file.bebop');
27 |
28 | $params->setFilters(array(
29 | array('type' => 'or', 'fields' => array(
30 | array('type' => 'selector', 'dimension' => 'one_dim', 'value' => '10'),
31 | array('type' => 'selector', 'dimension' => 'one_dim', 'value' => '11')
32 | ))
33 | ));
34 |
35 | $params->setAggregators(array(
36 | array('type' => 'count', 'name' => 'count'),
37 | array('type' => 'longSum', 'name' => 'total_referral_count', 'fieldName' => 'referral_count')
38 | ));
39 |
40 | $params->setPostAggregators(array(
41 | array(
42 | 'type' => 'arithmetic',
43 | 'name' => 'inactive_patients',
44 | 'fn' => '-', // Subtraction operator
45 | 'fields' => array(
46 | array('type' => 'fieldAccess', 'fieldName' => 'referral_count'),
47 | array('type' => 'fieldAccess', 'fieldName' => 'active_patients'),
48 | ),
49 | ),
50 | array(
51 | 'type' => 'javascript',
52 | 'name' => 'shrinkage',
53 | 'fieldNames' => array("referral_count", "discharged_patients"),
54 | 'function' => 'function(total, discharge) { return 100 * (total /w discharge); }'
55 | ),
56 | ));
57 |
58 | return $params;
59 | }
60 |
61 | public function testGenerateQueryReturnsJSONString()
62 | {
63 | $params = $this->getMockSimpleGroupByQueryParameters();
64 |
65 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator();
66 |
67 | $query = $q->generateQuery($params);
68 |
69 | $this->assertJson( $query );
70 | return $query;
71 | }
72 |
73 | /**
74 | * @depends testGenerateQueryReturnsJSONString
75 | */
76 | public function testGenerateQueryIncludesDataSource($jsonString)
77 | {
78 | $query = json_decode( $jsonString, true );
79 |
80 | $this->assertArrayHasKey('queryType', $query);
81 | $this->assertArrayHasKey('dataSource', $query, "Generated query must include required parameters.");
82 | }
83 |
84 | /**
85 | * @depends testGenerateQueryReturnsJSONString
86 | */
87 | public function testGenerateQueryIncludesAggregations($jsonString)
88 | {
89 |
90 | $query = json_decode( $jsonString, true );
91 |
92 | $this->assertArrayHasKey('aggregations', $query);
93 | $this->assertCount( 2, $query['aggregations'] );
94 |
95 | $aggs = $query['aggregations'];
96 |
97 | $firstAgg = $aggs[0];
98 | $secondAgg = $aggs[1];
99 |
100 | $this->assertEquals( "count", $firstAgg['type'] );
101 | $this->assertEquals( "count", $firstAgg['name'] );
102 | $this->assertEquals( "longSum", $secondAgg['type'] );
103 | $this->assertEquals( "total_referral_count", $secondAgg['name'] );
104 | $this->assertEquals( "referral_count", $secondAgg['fieldName'] );
105 | }
106 |
107 | /**
108 | * @depends testGenerateQueryReturnsJSONString
109 | */
110 | public function testGenerateQueryIncludesFilters($jsonString)
111 | {
112 |
113 | $query = json_decode( $jsonString, true );
114 |
115 | $this->assertArrayHasKey('filter', $query);
116 | $firstFilter = $query['filter'];
117 |
118 | $this->assertEquals( "or", $firstFilter['type'] );
119 | $this->assertArrayHasKey('fields', $firstFilter );
120 | $this->assertCount( 2, $firstFilter['fields'] );
121 |
122 | $orFilters = $firstFilter['fields'];
123 | $this->assertCount( 2, $orFilters );
124 |
125 | $firstOrFilter = $orFilters[0];
126 | $secondOrFilter = $orFilters[1];
127 |
128 | $this->assertEquals( "selector", $firstOrFilter['type'] );
129 | $this->assertEquals( "one_dim", $firstOrFilter['dimension'] );
130 | $this->assertEquals( "10", $firstOrFilter['value'] );
131 | $this->assertEquals( "selector", $secondOrFilter['type'] );
132 | $this->assertEquals( "one_dim", $secondOrFilter['dimension'] );
133 | $this->assertEquals( "11", $secondOrFilter['value'] );
134 |
135 | }
136 |
137 | /**
138 | * @depends testGenerateQueryReturnsJSONString
139 | */
140 | public function testGenerateQueryIncludesPostAggregations($jsonString)
141 | {
142 |
143 | $query = json_decode( $jsonString, true );
144 |
145 | $this->assertArrayHasKey('postAggregations', $query);
146 | $this->assertCount( 2, $query['postAggregations'] );
147 |
148 | $postAggs = $query['postAggregations'];
149 |
150 | $firstPostAgg = $postAggs[0];
151 | $secondPostAgg = $postAggs[1];
152 |
153 | $this->assertEquals( "arithmetic", $firstPostAgg['type'] );
154 | $this->assertEquals( "inactive_patients", $firstPostAgg['name'] );
155 | $this->assertEquals( "-", $firstPostAgg['fn'] );
156 | $this->assertEquals( "fieldAccess", $firstPostAgg['fields'][0]['type'] );
157 | $this->assertEquals( "referral_count", $firstPostAgg['fields'][0]['fieldName'] );
158 | $this->assertEquals( "fieldAccess", $firstPostAgg['fields'][1]['type'] );
159 | $this->assertEquals( "active_patients", $firstPostAgg['fields'][1]['fieldName'] );
160 |
161 | $this->assertEquals( "javascript", $secondPostAgg['type'] );
162 | $this->assertEquals( "shrinkage", $secondPostAgg['name'] );
163 | $this->assertCount( 2, $secondPostAgg['fieldNames'] );
164 | $this->assertEquals( "referral_count", $secondPostAgg['fieldNames'][0] );
165 | $this->assertEquals( "discharged_patients", $secondPostAgg['fieldNames'][1] );
166 | $this->assertEquals(
167 | "function(total, discharge) { return 100 * (total /w discharge); }",
168 | $secondPostAgg['function']
169 | );
170 |
171 | }
172 |
173 | public function testGenerateQueryRequiresDataSource()
174 | {
175 | try {
176 | $params = $this->getMockSimpleGroupByQueryParameters();
177 | $params->dataSource = NULL;
178 |
179 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator();
180 | $query = $q->generateQuery($params);
181 | } catch (MissingParametersException $e) {
182 | $this->assertContains('dataSource', $e->missingParameters, "Returned missing parameters: " . join(',', $e->missingParameters));
183 | return;
184 | }
185 |
186 | $this->fail('An expected exception was not raised');
187 | }
188 |
189 | public function testGenerateQueryRequiresQueryType()
190 | {
191 | try {
192 | $params = $this->getMockSimpleGroupByQueryParameters();
193 | $params->queryType = NULL;
194 |
195 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator($params);
196 | $query = $q->generateQuery($params);
197 | } catch (MissingParametersException $e) {
198 | $this->assertContains('queryType', $e->missingParameters);
199 | return;
200 | }
201 |
202 | $this->fail('An expected exception was not raised');
203 | }
204 |
205 | public function testGenerateQueryRequiresIntervals()
206 | {
207 | $this->setExpectedException('\DruidFamiliar\Exception\MissingParametersException');
208 |
209 | $params = new SimpleGroupByQueryParameters();
210 |
211 | $params = $this->getMockSimpleGroupByQueryParameters();
212 | $params->intervals = NULL;
213 |
214 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator($params);
215 | $q->generateQuery($params);
216 | }
217 |
218 |
219 | public function testGenerateQueryHandlesNotHavingAggregations()
220 | {
221 | $params = $this->getMockSimpleGroupByQueryParameters();
222 | $params->setAggregators(array());
223 |
224 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator($params);
225 |
226 | $query = $q->generateQuery($params);
227 |
228 | $this->assertJson( $query );
229 |
230 | $query = json_decode( $query, true );
231 |
232 | $this->assertArrayNotHasKey('aggregations', $query);
233 | }
234 |
235 |
236 | public function testGenerateQueryHandlesNotHavingPostAggregations()
237 | {
238 | $params = $this->getMockSimpleGroupByQueryParameters();
239 | $params->setPostAggregators(array());
240 |
241 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator($params);
242 |
243 | $query = $q->generateQuery($params);
244 |
245 | $this->assertJson( $query );
246 |
247 | $query = json_decode( $query, true );
248 |
249 | $this->assertArrayNotHasKey('postAggregations', $query);
250 | }
251 |
252 | public function testGenerateQueryHandlesStringGranularities()
253 | {
254 | $params = $this->getMockSimpleGroupByQueryParameters();
255 | $params->granularity = 'DAY';
256 |
257 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator();
258 |
259 | $query = $q->generateQuery($params);
260 |
261 |
262 | $jsonString = json_decode( $query, true );
263 |
264 | $this->assertArrayHasKey('granularity', $jsonString);
265 | $this->assertEquals( 'DAY', $jsonString['granularity'] );
266 | }
267 |
268 | public function testGenerateQueryHandlesObjectGranularities()
269 | {
270 | $params = $this->getMockSimpleGroupByQueryParameters();
271 | $params->granularity = array('type'=> "period", "period"=>"P3M");
272 |
273 | $q = new \DruidFamiliar\QueryGenerator\SimpleGroupByDruidQueryGenerator();
274 |
275 | $query = $q->generateQuery($params);
276 |
277 |
278 | $jsonString = json_decode( $query, true );
279 |
280 | $this->assertArrayHasKey('granularity', $jsonString);
281 | $this->assertCount( 2, $jsonString['granularity'] );
282 | $this->assertArrayHasKey('type', $jsonString['granularity']);
283 | $this->assertArrayHasKey('period', $jsonString['granularity']);
284 |
285 | $this->assertEquals( 'period', $jsonString['granularity']['type'] );
286 | $this->assertEquals( 'P3M', $jsonString['granularity']['period'] );
287 | }
288 | }
289 |
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryGenerator/TimeBoundaryDruidQueryGeneratorTest.php:
--------------------------------------------------------------------------------
1 | generateQuery($p);
18 |
19 | $query = json_decode( $query, true );
20 |
21 | $this->assertArrayHasKey('queryType', $query);
22 | $this->assertArrayHasKey('dataSource', $query, "Generated query must include required parameters.");
23 |
24 | $this->assertEquals('timeBoundary', $query['queryType'], "Generated query must have timeBoundary for its queryType.");
25 | $this->assertEquals($mockDataSourceName, $query['dataSource'], "Generated query must use provided dataSource.");
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryParameters/GroupByQueryParametersTest.php:
--------------------------------------------------------------------------------
1 | setDataSource('referral-visit-old-format');
26 | $parametersInstance->setGranularity('all');
27 | $parametersInstance->setDimensions(array('facility_id', 'referral_id', 'group'));
28 | $filter = new stdClass();
29 | $filter->type = 'selector';
30 | $filter->dimension = 'company_id';
31 | $filter->value = 1;
32 | $parametersInstance->setFilter($filter);
33 | $anAggregation = new stdClass();
34 | $anAggregation->type = 'longSum';
35 | $anAggregation->name = 'quantity';
36 | $anAggregation->fieldName = 'count';
37 | $parametersInstance->setAggregations(array($anAggregation));
38 | $parametersInstance->setIntervals(array('2008-01-01T00:00:00.000/2012-01-03T00:00:00.000'));
39 | $valid = $parametersInstance->validate();
40 | $this->assertTrue($valid);
41 | }
42 |
43 | /**
44 | * Missing a required parameter (filter)
45 | *
46 | * @expectedException \DruidFamiliar\Exception\MissingParametersException
47 | */
48 | public function testMissingParametersException()
49 | {
50 | $parametersInstance = new GroupByQueryParameters();
51 | $parametersInstance->setDataSource('referral-visit-old-format');
52 | $parametersInstance->setDimensions(array('facility_id', 'referral_id', 'group'));
53 | $filter = new stdClass();
54 | $filter->type = 'selector';
55 | $filter->dimension = 'company_id';
56 | $filter->value = 1;
57 | $parametersInstance->setFilter($filter);
58 | $anAggregation = new stdClass();
59 | $anAggregation->type = 'longSum';
60 | $anAggregation->name = 'quantity';
61 | $anAggregation->fieldName = 'count';
62 | $parametersInstance->setAggregations(array($anAggregation));
63 | $parametersInstance->setIntervals(array('2008-01-01T00:00:00.000/2012-01-03T00:00:00.000'));
64 | $valid = $parametersInstance->validate();
65 | }
66 |
67 | /**
68 | * A non empty parameter (granularity)
69 | *
70 | * @expectedException \DruidFamiliar\Exception\EmptyParametersException
71 | */
72 | public function testEmptyParametersException()
73 | {
74 | $parametersInstance = new GroupByQueryParameters();
75 | $parametersInstance->setDataSource('referral-visit-old-format');
76 | $parametersInstance->setGranularity('');
77 | $parametersInstance->setDimensions(array('facility_id', 'referral_id', 'group'));
78 | $filter = new stdClass();
79 | $filter->type = 'selector';
80 | $filter->dimension = 'company_id';
81 | $filter->value = 1;
82 | $parametersInstance->setFilter($filter);
83 | $anAggregation = new stdClass();
84 | $anAggregation->type = 'longSum';
85 | $anAggregation->name = 'quantity';
86 | $anAggregation->fieldName = 'count';
87 | $parametersInstance->setAggregations(array($anAggregation));
88 | $parametersInstance->setIntervals(array('2008-01-01T00:00:00.000/2012-01-03T00:00:00.000'));
89 | $valid = $parametersInstance->validate();
90 | }
91 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryParameters/SegmentMetadataQueryParametersTest.php:
--------------------------------------------------------------------------------
1 | expectedIntervalString = $this->mockStartTimeString . ':00Z/' . $this->mockEndTimeString . 'T00:00:00Z';
20 |
21 | $this->parametersInstance = new SegmentMetadataQueryParameters($this->mockDataSource, $this->mockStartTimeString, $this->mockEndTimeString);
22 | }
23 |
24 | public function testValidate()
25 | {
26 | /**
27 | * @var SegmentMetadataQueryParameters $parametersInstance
28 | */
29 | $parametersInstance = $this->parametersInstance;
30 |
31 | $parametersInstance->validate();
32 |
33 | $this->assertEquals($this->mockDataSource, $parametersInstance->dataSource);
34 | $this->assertEquals($this->expectedIntervalString, $parametersInstance->intervals);
35 |
36 | return $parametersInstance;
37 | }
38 |
39 | /**
40 | * @depends testValidate
41 | */
42 | public function testIntervalsValue()
43 | {
44 | /**
45 | * @var SegmentMetadataQueryParameters $parametersInstance
46 | */
47 | $parametersInstance = $this->parametersInstance;
48 |
49 | $this->assertInstanceOf('DruidFamiliar\Interval', $parametersInstance->intervals);
50 | $this->assertEquals($this->expectedIntervalString, $parametersInstance->intervals);
51 |
52 | return $parametersInstance;
53 | }
54 |
55 | /**
56 | * @depends testValidate
57 | */
58 | public function testValidateWithMissingDataSource()
59 | {
60 | /**
61 | * @var SegmentMetadataQueryParameters $parametersInstance
62 | */
63 | $parametersInstance = $this->parametersInstance;
64 |
65 | $parametersInstance->dataSource = NULL;
66 |
67 | $this->setExpectedException('DruidFamiliar\Exception\MissingParametersException');
68 |
69 | $parametersInstance->validate();
70 | }
71 |
72 | /**
73 | * @depends testValidate
74 | */
75 | public function testValidateWithMissingInterval()
76 | {
77 | /**
78 | * @var SegmentMetadataQueryParameters $parametersInstance
79 | */
80 | $parametersInstance = $this->parametersInstance;
81 |
82 | $parametersInstance->intervals = NULL;
83 |
84 | $this->setExpectedException('DruidFamiliar\Exception\MissingParametersException');
85 |
86 | $parametersInstance->validate();
87 | }
88 |
89 | /**
90 | * @depends testValidate
91 | */
92 | public function testValidateWithMalformedInterval()
93 | {
94 | /**
95 | * @var SegmentMetadataQueryParameters $parametersInstance
96 | */
97 | $parametersInstance = $this->parametersInstance;
98 |
99 | $parametersInstance->intervals = 1;
100 |
101 | $this->setExpectedException('DruidFamiliar\Exception\UnexpectedTypeException');
102 |
103 | $parametersInstance->validate();
104 | }
105 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryParameters/SimpleGroupByQueryParametersTest.php:
--------------------------------------------------------------------------------
1 | getMockBuilder('DruidFamiliar\QueryParameters\SimpleGroupByQueryParameters')
14 | ->setMethods(null)
15 | ->getMock();
16 |
17 | $origStartDateTime = '2014-06-18T12:30:01Z';
18 | $origEndDateTime = '2014-06-18T01:00:00Z';
19 |
20 | $expectedResults = new Interval('2014-06-18T12:30:01Z', '2014-06-18T01:00:01Z');
21 |
22 | $query->setIntervalForQueryingUsingExclusiveTimes($origStartDateTime, $origEndDateTime);
23 | $results = $query->getIntervals();
24 | $this->assertEquals($expectedResults, $results);
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/QueryParameters/TimeBoundaryQueryParametersTest.php:
--------------------------------------------------------------------------------
1 | mockDataSource);
21 |
22 | $parametersInstance->validate();
23 |
24 | $this->assertEquals($this->mockDataSource, $parametersInstance->dataSource);
25 |
26 | return $parametersInstance;
27 | }
28 |
29 | /**
30 | * @depends testValidate
31 | */
32 | public function testValidateWithMissingDataSource()
33 | {
34 | $parametersInstance = new TimeBoundaryQueryParameters($this->mockDataSource);
35 |
36 | $parametersInstance->dataSource = NULL;
37 |
38 | $this->setExpectedException('DruidFamiliar\Exception\MissingParametersException');
39 |
40 | $parametersInstance->validate();
41 | }
42 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/ResponseHandler/DoNothingResponseHandlerTest.php:
--------------------------------------------------------------------------------
1 | handleResponse($mockedResponse);
16 | $this->assertEquals($mockedResponse, $handledResponse, "Does not try to encode or decode");
17 |
18 | $mockedResponse = "a";
19 | $handledResponse = $responseHandler->handleResponse($mockedResponse);
20 | $this->assertEquals($mockedResponse, $handledResponse, "Does not try to encode or decode");
21 |
22 | $mockedResponse = '{"a":1, "b": "c"}';
23 | $handledResponse = $responseHandler->handleResponse($mockedResponse);
24 | $this->assertEquals($mockedResponse, $handledResponse);
25 |
26 | $mockedResponse = "text\nwith\nnewlines";
27 | $handledResponse = $responseHandler->handleResponse($mockedResponse);
28 | $this->assertEquals($mockedResponse, $handledResponse, "Does not strip newlines");
29 | }
30 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/ResponseHandler/GroupByResponseHandlerTest.php:
--------------------------------------------------------------------------------
1 | responseHandler = new GroupByResponseHandler();
32 | }
33 |
34 | /**
35 | * Tests that a good formed response is properly handled
36 | */
37 | public function testTranslatesGoodResponseIntoGroupByResponse()
38 | {
39 | $goodResponse = <<< 'JSONRESPONSE'
40 | [{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"10","quantity":1,"group":"2","facility_id":"1"}},{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"1002","quantity":1,"group":"2","facility_id":"1"}},{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"1011","quantity":1,"group":"2","facility_id":"1"}}]
41 |
42 | JSONRESPONSE;
43 | $mockedResponse = new Response(200, array(), $goodResponse);
44 | $handledResponse = $this->responseHandler->handleResponse($mockedResponse);
45 | $data = $handledResponse->getData();
46 | $record = $data[1];
47 | $responseCount = count($data);
48 | $this->assertEquals(3, $responseCount); //Response has 3 records??
49 | $this->assertTrue(isset($record['event'])); //Response has an event key??
50 | $this->assertEquals('v1', $record['version']); //Response version is v1???
51 | $this->assertEquals('1002', $record['event']['referral_id']); //Is the referral id the same as in the JSON object???
52 | $this->assertEquals('2', $record['event']['group']); //Is the group the same as in the JSON object???
53 | }
54 |
55 | /**
56 | * Tests that a good formed response is properly handled
57 | */
58 | public function testTranslatesGoodResponseWithBadRecordIntoGroupByResponse()
59 | {
60 | $goodResponseWithBadRecord = <<< 'JSONRESPONSE'
61 | [{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"10","quantity":1,"group":"3","facility_id":"1"}},{"fakeObject":"true","willThisAffectBehaviour":"NO"},{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"1002","quantity":1,"group":"2","facility_id":"1"}},{"version":"v1","timestamp":"2008-01-01T00:00:00.000Z","event":{"referral_id":"1011","quantity":1,"group":"2","facility_id":"1"}}]
62 |
63 | JSONRESPONSE;
64 | $mockedResponse = new Response(200, array(), $goodResponseWithBadRecord);
65 | $handledResponse = $this->responseHandler->handleResponse($mockedResponse);
66 | $data = $handledResponse->getData();
67 | $record = $data[0];
68 | $responseCount = count($data);
69 | $this->assertEquals(3, $responseCount); //Response has 3 records?? It should because it will strip the bad data and just consume good records
70 | $this->assertTrue(isset($record['event'])); //Response has an event key??
71 | $this->assertEquals('v1', $record['version']); //Response version is v1???
72 | $this->assertEquals('10', $record['event']['referral_id']); //Is the referral id the same as in the JSON object???
73 | $this->assertEquals('3', $record['event']['group']); //Is the group the same as in the JSON object???
74 | }
75 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/ResponseHandler/TimeBoundaryResponseHandlerTest.php:
--------------------------------------------------------------------------------
1 | responseHandler = new TimeBoundaryResponseHandler();
17 | }
18 |
19 | public function tearDown()
20 | {
21 | unset($this->responseHandler);
22 | }
23 |
24 | public function testHandlesNonDruidResponse()
25 | {
26 | try
27 | {
28 | $mockedResponse = new Response(200, array(), '1');
29 | $handledResponse = $this->responseHandler->handleResponse($mockedResponse);
30 | $this->assertEquals($mockedResponse, $handledResponse);
31 | }
32 | catch(\Exception $e)
33 | {
34 | if($e->getMessage() === "Unexpected response format.")
35 | {
36 | return;
37 | }
38 | }
39 |
40 | $this->fail('Did not hit an expected exception');
41 | }
42 |
43 | public function testHandlesEmptyResponse()
44 | {
45 | try
46 | {
47 | $mockedResponse = new Response(200);
48 | $handledResponse = $this->responseHandler->handleResponse($mockedResponse);
49 | $this->assertEquals($mockedResponse, $handledResponse);
50 | }
51 | catch(\Exception $e)
52 | {
53 | if($e->getMessage() === "Unknown data source.")
54 | {
55 | return;
56 | }
57 | }
58 |
59 | $this->fail('Did not hit an expected exception. Expected Exception with message "Unknown data source."');
60 | }
61 |
62 | public function testTranslatesIntoTimeBoundaryResponse()
63 | {
64 | $jsonResponse = <<responseHandler->handleResponse($mockedResponse);
76 |
77 | $this->assertInstanceOf('DruidFamiliar\Response\TimeBoundaryResponse', $handledResponse);
78 | $this->assertEquals("2013-05-09T18:24:00.000Z", $handledResponse->minTime);
79 | $this->assertEquals("2013-05-09T18:37:00.000Z", $handledResponse->maxTime);
80 | }
81 | }
--------------------------------------------------------------------------------
/tests/DruidFamiliar/Test/bootstrap.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ./
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------