Issues (52)

src/Queries/ScanQuery.php (3 issues)

1
<?php
2
declare(strict_types=1);
3
4
namespace Level23\Druid\Queries;
5
6
use Level23\Druid\Context\QueryContext;
7
use Level23\Druid\Types\OrderByDirection;
8
use Level23\Druid\Filters\FilterInterface;
9
use Level23\Druid\Types\ScanQueryResultFormat;
10
use Level23\Druid\Responses\ScanQueryResponse;
11
use Level23\Druid\Collections\IntervalCollection;
12
use Level23\Druid\DataSources\DataSourceInterface;
13
use Level23\Druid\Collections\VirtualColumnCollection;
14
15
/**
16
 * Class ScanQuery
17
 *
18
 * @see     https://druid.apache.org/docs/latest/querying/scan-query.html
19
 * @package Level23\Druid\Queries
20
 */
21
class ScanQuery implements QueryInterface
22
{
23
    protected DataSourceInterface $dataSource;
24
25
    protected IntervalCollection $intervals;
26
27
    protected ScanQueryResultFormat $resultFormat = ScanQueryResultFormat::NORMAL_LIST;
28
29
    /**
30
     * How many rows buffered before return to client. Default is 20480
31
     *
32
     * @var int
33
     */
34
    protected int $batchSize;
35
36
    /**
37
     * Return results consistent with the legacy "scan-query" contrib extension. Defaults to the value set by
38
     * druid.query.scan.legacy, which in turn defaults to false. See Legacy mode for details.
39
     *
40
     * @var bool
41
     */
42
    protected bool $legacy;
43
44
    /**
45
     * The ordering of returned rows based on timestamp. "ascending", "descending" are supported. When not supplied,
46
     * "none" is used. Currently, "ascending" and "descending" are only supported for queries where the __time column
47
     * is included in the columns field and the requirements outlined in the time ordering section are met.
48
     *
49
     * @var OrderByDirection
50
     */
51
    protected OrderByDirection $order;
52
53
    /**
54
     * How many rows to return. If not specified, all rows will be returned.
55
     *
56
     * @var int
57
     */
58
    protected int $limit;
59
60
    /**
61
     * Skip this many rows when returning results.
62
     *
63
     * @var int
64
     */
65
    protected int $offset;
66
67
    protected ?QueryContext $context;
68
69
    protected ?FilterInterface $filter;
70
71
    /**
72
     * A String array of dimensions and metrics to scan. If left empty, all dimensions and metrics are returned.
73
     *
74
     * @var array|string[]
75
     */
76
    protected array $columns = [];
77
78
    protected ?VirtualColumnCollection $virtualColumns;
79
80 9
    public function __construct(DataSourceInterface $dataSource, IntervalCollection $intervals)
81
    {
82 9
        $this->dataSource = $dataSource;
83 9
        $this->intervals  = $intervals;
84
    }
85
86
    /**
87
     * Return the query in array format, so we can fire it to druid.
88
     *
89
     * @return array<string,string|array<mixed>|int|bool>
90
     */
91 5
    public function toArray(): array
92
    {
93 5
        $result = [
94 5
            'queryType'    => 'scan',
95 5
            'dataSource'   => $this->dataSource->toArray(),
96 5
            'intervals'    => $this->intervals->toArray(),
97 5
            'resultFormat' => $this->resultFormat->value,
98 5
            'columns'      => $this->columns,
99 5
        ];
100
101 5
        if (isset($this->virtualColumns)) {
102 2
            $result['virtualColumns'] = $this->virtualColumns->toArray();
0 ignored issues
show
The method toArray() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

102
            /** @scrutinizer ignore-call */ 
103
            $result['virtualColumns'] = $this->virtualColumns->toArray();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
103
        }
104
105 5
        if (isset($this->filter)) {
106 4
            $result['filter'] = $this->filter->toArray();
0 ignored issues
show
The method toArray() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

106
            /** @scrutinizer ignore-call */ 
107
            $result['filter'] = $this->filter->toArray();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
107
        }
108
109 5
        if (isset($this->batchSize)) {
110 2
            $result['batchSize'] = $this->batchSize;
111
        }
112
113 5
        if (isset($this->limit)) {
114 2
            $result['limit'] = $this->limit;
115
        }
116
117 5
        if (isset($this->offset)) {
118 2
            $result['offset'] = $this->offset;
119
        }
120
121 5
        if (isset($this->legacy)) {
122 5
            $result['legacy'] = $this->legacy;
123
        }
124
125 5
        if (isset($this->context)) {
126 2
            $context = $this->context->toArray();
0 ignored issues
show
The method toArray() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

126
            /** @scrutinizer ignore-call */ 
127
            $context = $this->context->toArray();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
127 2
            if (sizeof($context) > 0) {
128 2
                $result['context'] = $context;
129
            }
130
        }
131
132 5
        if (isset($this->order)) {
133 2
            $result['order'] = $this->order->value;
134
        }
135
136 5
        return $result;
137
    }
138
139
    /**
140
     * Parse the response into something we can return to the user.
141
     *
142
     * @param array<string|int,string|int|array<mixed>> $response
143
     *
144
     * @return ScanQueryResponse
145
     */
146 2
    public function parseResponse(array $response): ScanQueryResponse
147
    {
148 2
        return new ScanQueryResponse($response);
149
    }
150
151
    /**
152
     * How the results are represented. Use one of the ScanQueryResultFormat constants
153
     *
154
     * @param string|ScanQueryResultFormat $resultFormat
155
     */
156 6
    public function setResultFormat(string|ScanQueryResultFormat $resultFormat): void
157
    {
158 6
        $this->resultFormat = is_string($resultFormat) ? ScanQueryResultFormat::from(strtolower($resultFormat)) : $resultFormat;
159
    }
160
161
    /**
162
     * How many rows buffered before return to client. Default is 20480
163
     *
164
     * @param int $batchSize
165
     */
166 2
    public function setBatchSize(int $batchSize): void
167
    {
168 2
        $this->batchSize = $batchSize;
169
    }
170
171
    /**
172
     * How many rows to return. If not specified, all rows will be returned.
173
     *
174
     * @param int $limit
175
     */
176 2
    public function setLimit(int $limit): void
177
    {
178 2
        $this->limit = $limit;
179
    }
180
181
    /**
182
     * Skip this many rows when returning results. Skipped rows will still need to be generated internally and then
183
     * discarded, meaning that raising offsets to high values can cause queries to use additional resources.
184
     *
185
     * Together, "limit" and "offset" can be used to implement pagination. However, note that if the underlying
186
     * datasource is modified in between page fetches in ways that affect overall query results, then the
187
     * different pages will not necessarily align with each other.
188
     *
189
     * @param int $offset
190
     */
191 2
    public function setOffset(int $offset): void
192
    {
193 2
        $this->offset = $offset;
194
    }
195
196
    /**
197
     * @param bool $legacy
198
     */
199 5
    public function setLegacy(bool $legacy): void
200
    {
201 5
        $this->legacy = $legacy;
202
    }
203
204
    /**
205
     * @param \Level23\Druid\Context\QueryContext $context
206
     */
207 2
    public function setContext(QueryContext $context): void
208
    {
209 2
        $this->context = $context;
210
    }
211
212
    /**
213
     * @param \Level23\Druid\Collections\VirtualColumnCollection $virtualColumns
214
     */
215 2
    public function setVirtualColumns(VirtualColumnCollection $virtualColumns): void
216
    {
217 2
        $this->virtualColumns = $virtualColumns;
218
    }
219
220
    /**
221
     * @param \Level23\Druid\Filters\FilterInterface $filter
222
     */
223 4
    public function setFilter(FilterInterface $filter): void
224
    {
225 4
        $this->filter = $filter;
226
    }
227
228
    /**
229
     * The ordering of returned rows based on timestamp. "ascending", "descending", and "none" (default) are supported.
230
     * Currently, "ascending" and "descending" are only supported for queries where the __time column is included in
231
     * the columns field and the requirements outlined in the time ordering section are met.
232
     *
233
     * @param string|OrderByDirection $order
234
     */
235 2
    public function setOrder(string|OrderByDirection $order): void
236
    {
237 2
        $this->order = is_string($order) ? OrderByDirection::make($order) : $order;
238
    }
239
240
    /**
241
     * A String array of dimensions and metrics to scan. If left empty, all dimensions and metrics are returned.
242
     *
243
     * @param array|string[] $columns
244
     */
245 2
    public function setColumns(array $columns): void
246
    {
247 2
        $this->columns = $columns;
248
    }
249
}