libasynql  3.2.0
Asynchronous MySQL access library for PocketMine plugins.
Sqlite3Thread.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * libasynql
5  *
6  * Copyright (C) 2018 SOFe
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 declare(strict_types=1);
22 
24 
25 use Closure;
26 use Exception;
38 use SQLite3;
39 use function array_values;
40 use function assert;
41 use function is_array;
42 use const INF;
43 use const NAN;
44 use const SQLITE3_ASSOC;
45 use const SQLITE3_BLOB;
46 use const SQLITE3_FLOAT;
47 use const SQLITE3_INTEGER;
48 use const SQLITE3_NULL;
49 use const SQLITE3_TEXT;
50 
53  private $path;
54 
55  public static function createFactory(string $path) : Closure{
56  return function(QuerySendQueue $send, QueryRecvQueue $recv) use ($path){
57  return new Sqlite3Thread($path, $send, $recv);
58  };
59  }
60 
61  public function __construct(string $path, QuerySendQueue $send = null, QueryRecvQueue $recv = null){
62  parent::__construct($send, $recv);
63  $this->path = $path;
64  }
65 
66  protected function createConn(&$sqlite) : ?string{
67  try{
68  $sqlite = new SQLite3($this->path);
69  $sqlite->busyTimeout(60000); // default value in SQLite2
70  return null;
71  }catch(Exception $e){
72  return $e->getMessage();
73  }
74  }
75 
76  protected function executeQuery($sqlite, int $mode, string $query, array $params) : SqlResult{
77  assert($sqlite instanceof SQLite3);
78  $stmt = $sqlite->prepare($query);
79  if($stmt === false){
80  throw new SqlError(SqlError::STAGE_PREPARE, $sqlite->lastErrorMsg(), $query, $params);
81  }
82  foreach($params as $paramName => $param){
83  $bind = $stmt->bindValue($paramName, $param);
84  if(!$bind){
85  throw new SqlError(SqlError::STAGE_PREPARE, "when binding $paramName: " . $sqlite->lastErrorMsg(), $query, $params);
86  }
87  }
88  $result = $stmt->execute();
89  if($result === false){
90  throw new SqlError(SqlError::STAGE_EXECUTE, $sqlite->lastErrorMsg(), $query, $params);
91  }
92  switch($mode){
94  $ret = new SqlResult();
95  $result->finalize();
96  $stmt->close();
97  return $ret;
99  $ret = new SqlChangeResult($sqlite->changes());
100  $result->finalize();
101  $stmt->close();
102  return $ret;
104  $ret = new SqlInsertResult($sqlite->changes(), $sqlite->lastInsertRowID());
105  $result->finalize();
106  $stmt->close();
107  return $ret;
110  $colInfo = [];
111  for($i = 0, $iMax = $result->numColumns(); $i < $iMax; ++$i){
112  static $columnTypeMap = [
118  ];
119  $colInfo[] = new SqlColumnInfo($result->columnName($i), $columnTypeMap[$result->columnType($i)]);
120  }
121  $rows = [];
122  while(is_array($row = $result->fetchArray(SQLITE3_ASSOC))){
123  foreach(array_values($row) as $i => &$value){
124  if($colInfo[$i]->getType() === SqlColumnInfo::TYPE_FLOAT){
125  if($value === "NAN"){
126  $value = NAN;
127  }elseif($value === "INF"){
128  $value = INF;
129  }elseif($value === "-INF"){
130  $value = -INF;
131  }
132  }
133  }
134  unset($value);
135  $rows[] = $row;
136  }
137  $ret = new SqlSelectResult($colInfo, $rows);
138  $result->finalize();
139  $stmt->close();
140  return $ret;
141  }
142 
143  throw new InvalidArgumentException("Unknown mode $mode");
144  }
145 
146  protected function close(&$resource) : void{
147  assert($resource instanceof SQLite3);
148  $resource->close();
149  }
150 
151  public function getThreadName() : string{
152  return __NAMESPACE__ . " connector #$this->slaveNumber";
153  }
154 }
executeQuery($resource, int $mode, string $query, array $params)
__construct(string $path, QuerySendQueue $send=null, QueryRecvQueue $recv=null)