1010use Illuminate \Database \QueryException ;
1111use Bilaliqbalr \Athena \Query \Grammar as QueryGrammar ;
1212use Bilaliqbalr \Athena \Query \Processor ;
13+ use Illuminate \Support \Arr ;
1314use Illuminate \Support \Facades \Config ;
1415use Bilaliqbalr \Athena \Schema \Builder ;
1516use Bilaliqbalr \Athena \Schema \Grammar as SchemaGrammar ;
@@ -181,11 +182,11 @@ public function formatCSVFileQueryResults($filePath)
181182 }
182183
183184 /**
184- * @param \Illuminate\Database\Query\Builder $builder
185185 * @param null $query
186186 * @param null $binding
187187 *
188188 * @return mixed
189+ * @throws Exception
189190 */
190191 protected function prepareQuery ($ query , $ binding )
191192 {
@@ -197,6 +198,29 @@ protected function prepareQuery($query, $binding)
197198 }
198199 }
199200
201+ // Modifying query & preparing it for LIMIT as per Athena
202+ if (is_int (stripos ($ query , 'BETWEENLIMIT ' ))) {
203+ // Checking if ROW_NUMBER() OVER() window function applied, then take it as LIMIT query
204+ if (!is_int (stripos ($ query , 'ROW_NUMBER() ' )) || !is_int (stripos ($ query , ' rn ' ))) {
205+ throw new Exception ("Error: Required `ROW_NUMBER() OVER(...) as rn` to implement LIMIT functionality " );
206+ } else {
207+ $ queryParts = preg_split ("/BETWEENLIMIT/i " , $ query );
208+ preg_match_all ('!\d+! ' , array_pop ($ queryParts ), $ matches );
209+ // Calculating offset and limit for Athena
210+ $ perPage = ($ matches [0 ][0 ] - 1 );
211+
212+ // Only apply this limit if we have per page greater than 0.
213+ // This prevent BETWEEN as WHERE clause to be treated like LIMIT & OFFSET, which occurs if we have
214+ // both BETWEEN and ROW_NUMBER() in query but that no LIMIT
215+ if ($ perPage > 0 ) {
216+ $ page = ($ matches [0 ][1 ] / $ perPage ) + 1 ;
217+ $ from = ($ perPage * ($ page - 1 )) + 1 ;
218+ $ to = ($ perPage * $ page );
219+ $ query = "SELECT * FROM ( " . Arr::first ($ queryParts ) . " ) WHERE rn BETWEEN $ from AND $ to " ;
220+ }
221+ }
222+ }
223+
200224 return str_replace ('` ' , '' , $ query );
201225 }
202226
@@ -216,7 +240,7 @@ public function getDownloadedFilePath()
216240 * @return array|\Aws\Result
217241 * @throws Exception
218242 */
219- protected function executeQuery ($ query , $ bindings )
243+ protected function executeQuery (& $ query , $ bindings )
220244 {
221245 $ query = $ this ->prepareQuery ($ query , $ bindings );
222246
@@ -275,7 +299,7 @@ public function statement($query, $bindings = [])
275299 $ this ->executeQuery ($ query , $ bindings );
276300
277301 $ this ->logQuery (
278- $ query , $ bindings , $ this ->getElapsedTime ($ start )
302+ $ query , [] , $ this ->getElapsedTime ($ start )
279303 );
280304
281305 return true ;
@@ -306,12 +330,11 @@ public function select($query, $bindings = [], $useReadPdo = true)
306330
307331 if ($ this ->downloadFileFromS3ToLocalServer ($ s3FilePath , $ localFilePath )) {
308332 $ this ->localFilePath = $ localFilePath ;
309- dd ($ s3FilePath , $ this ->localFilePath );
310333 $ result = $ this ->formatCSVFileQueryResults ($ this ->localFilePath );
311334 }
312335 }
313336 $ this ->logQuery (
314- $ query , $ bindings , $ this ->getElapsedTime ($ start )
337+ $ query , [] , $ this ->getElapsedTime ($ start )
315338 );
316339
317340 return $ result ;
0 commit comments