début query
This commit is contained in:
parent
3bd1031dda
commit
6a0838d4fa
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
namespace nur\sery\db\sqlite;
|
namespace nur\sery\db\sqlite;
|
||||||
|
|
||||||
use nur\b\IllegalAccessException;
|
use Generator;
|
||||||
use nur\sery\cl;
|
use nur\sery\cl;
|
||||||
use SQLite3;
|
use SQLite3;
|
||||||
use SQLite3Result;
|
use SQLite3Result;
|
||||||
|
@ -15,14 +15,6 @@ class Sqlite {
|
||||||
$sqlite->db->enableExceptions(true);
|
$sqlite->db->enableExceptions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function verifix_query(&$query, ?array &$params=null): void {
|
|
||||||
if (is_array($query)) {
|
|
||||||
throw IllegalAccessException::not_implemented(); #XXX
|
|
||||||
} elseif (!is_string($query)) {
|
|
||||||
$query = strval($query);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const CONFIG = [
|
const CONFIG = [
|
||||||
[self::class, "config_enableExceptions"],
|
[self::class, "config_enableExceptions"],
|
||||||
];
|
];
|
||||||
|
@ -61,12 +53,16 @@ class Sqlite {
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $file;
|
protected $file;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
protected $flags;
|
protected $flags;
|
||||||
|
|
||||||
/** @var string */
|
/** @var string */
|
||||||
protected $encryptionKey;
|
protected $encryptionKey;
|
||||||
|
|
||||||
/** @var array|string|callable */
|
/** @var array|string|callable */
|
||||||
protected $config;
|
protected $config;
|
||||||
|
|
||||||
/** @var array|string|callable */
|
/** @var array|string|callable */
|
||||||
protected $migration;
|
protected $migration;
|
||||||
|
|
||||||
|
@ -76,8 +72,8 @@ class Sqlite {
|
||||||
function open(): self {
|
function open(): self {
|
||||||
if ($this->db === null) {
|
if ($this->db === null) {
|
||||||
$this->db = new SQLite3($this->file, $this->flags, $this->encryptionKey);
|
$this->db = new SQLite3($this->file, $this->flags, $this->encryptionKey);
|
||||||
SqliteConfig::with($this->config)->run($this);
|
SqliteConfig::with($this->config)->configure($this);
|
||||||
SqliteMigration::with($this->migration)->run($this);
|
SqliteMigration::with($this->migration)->migrate($this);
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -89,43 +85,46 @@ class Sqlite {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec($query, ?array $params=null): bool {
|
protected function checkStmt($stmt): SQLite3Stmt {
|
||||||
$this->open();
|
return SqliteException::check($this->db, $stmt);
|
||||||
self::verifix_query($query, $params);
|
|
||||||
$db = $this->db;
|
|
||||||
if ($params === null) {
|
|
||||||
return $db->exec($query);
|
|
||||||
} else {
|
|
||||||
/** @var SQLite3Stmt $stmt */
|
|
||||||
$stmt = SqliteException::check($db, $db->prepare($query));
|
|
||||||
try {
|
|
||||||
foreach ($params as $param => $value) {
|
|
||||||
SqliteException::check($db, $stmt->bindValue($param, $value));
|
|
||||||
}
|
}
|
||||||
/** @var SQLite3Result $result */
|
|
||||||
$result = SqliteException::check($db, $stmt->execute());
|
protected function checkResult($result): SQLite3Result {
|
||||||
return $result->finalize();
|
return SqliteException::check($this->db, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _exec(string $sql): bool {
|
||||||
|
$this->open();
|
||||||
|
return $this->db->exec($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exec($sql, ?array $params=null): bool {
|
||||||
|
$this->open();
|
||||||
|
$query = new SqliteQuery($sql, $params);
|
||||||
|
$db = $this->db;
|
||||||
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
|
try {
|
||||||
|
return $stmt->execute()->finalize();
|
||||||
} finally {
|
} finally {
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return $db->exec($sql);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function get($query, ?array $params=null, bool $entireRow=false) {
|
function _get(string $sql, bool $entireRow=false) {
|
||||||
$this->open();
|
$this->open();
|
||||||
self::verifix_query($query, $params);
|
return $this->db->querySingle($sql, $entireRow);
|
||||||
$db = $this->db;
|
|
||||||
if ($params === null) {
|
|
||||||
return $db->querySingle($query, $entireRow);
|
|
||||||
} else {
|
|
||||||
/** @var SQLite3Stmt $stmt */
|
|
||||||
$stmt = SqliteException::check($db, $db->prepare($query));
|
|
||||||
try {
|
|
||||||
foreach ($params as $param => $value) {
|
|
||||||
SqliteException::check($db, $stmt->bindValue($param, $value));
|
|
||||||
}
|
}
|
||||||
/** @var SQLite3Result $result */
|
|
||||||
$result = SqliteException::check($db, $stmt->execute());
|
function get($sql, ?array $params=null, bool $entireRow=false) {
|
||||||
|
$this->open();
|
||||||
|
$query = new SqliteQuery($sql, $params);
|
||||||
|
$db = $this->db;
|
||||||
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
|
try {
|
||||||
|
$result = $this->checkResult($stmt->execute());
|
||||||
try {
|
try {
|
||||||
$row = $result->fetchArray(SQLITE3_ASSOC);
|
$row = $result->fetchArray(SQLITE3_ASSOC);
|
||||||
if ($row === false) return null;
|
if ($row === false) return null;
|
||||||
|
@ -137,42 +136,35 @@ class Sqlite {
|
||||||
} finally {
|
} finally {
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return $db->querySingle($sql, $entireRow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function all($query, ?array $params=null): iterable {
|
protected function _fetchResult(SQLite3Result $result): Generator {
|
||||||
|
try {
|
||||||
|
while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) {
|
||||||
|
yield $row;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
$result->finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function all($sql, ?array $params=null): iterable {
|
||||||
$this->open();
|
$this->open();
|
||||||
self::verifix_query($query, $params);
|
$query = new SqliteQuery($sql, $params);
|
||||||
$db = $this->db;
|
$db = $this->db;
|
||||||
if ($params === null) {
|
if ($query->useStmt($db, $stmt, $sql)) {
|
||||||
/** @var SQLite3Result $result */
|
|
||||||
$result = SqliteException::check($db, $db->query($query));
|
|
||||||
try {
|
try {
|
||||||
while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) {
|
$result = $this->checkResult($stmt->execute());
|
||||||
yield $row;
|
return $this->_fetchResult($result);
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
$result->finalize();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/** @var SQLite3Stmt $stmt */
|
|
||||||
$stmt = SqliteException::check($db, $db->prepare($query));
|
|
||||||
try {
|
|
||||||
foreach ($params as $param => $value) {
|
|
||||||
SqliteException::check($db, $stmt->bindValue($param, $value));
|
|
||||||
}
|
|
||||||
/** @var SQLite3Result $result */
|
|
||||||
$result = SqliteException::check($db, $stmt->execute());
|
|
||||||
try {
|
|
||||||
while (($row = $result->fetchArray(SQLITE3_ASSOC)) !== false) {
|
|
||||||
yield $row;
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
$result->finalize();
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
$stmt->close();
|
$stmt->close();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$result = $this->checkResult($db->query($sql));
|
||||||
|
return $this->_fetchResult($result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ class SqliteConfig {
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $configs;
|
protected $configs;
|
||||||
|
|
||||||
function run(Sqlite $sqlite): void {
|
function configure(Sqlite $sqlite): void {
|
||||||
foreach ($this->configs as $key => $config) {
|
foreach ($this->configs as $key => $config) {
|
||||||
if (is_callable($config)) {
|
if (is_callable($config)) {
|
||||||
func::call($config, $sqlite, $key, $this);
|
func::call($config, $sqlite, $key, $this);
|
||||||
|
|
|
@ -23,7 +23,7 @@ class SqliteMigration {
|
||||||
/** @var callable[]|string[] */
|
/** @var callable[]|string[] */
|
||||||
protected $migrations;
|
protected $migrations;
|
||||||
|
|
||||||
function run(Sqlite $sqlite): void {
|
function migrate(Sqlite $sqlite): void {
|
||||||
$sqlite->exec("create table if not exists _migration(key varchar primary key, value varchar not null, done integer default 0)");
|
$sqlite->exec("create table if not exists _migration(key varchar primary key, value varchar not null, done integer default 0)");
|
||||||
foreach ($this->migrations as $key => $migration) {
|
foreach ($this->migrations as $key => $migration) {
|
||||||
$exists = $sqlite->get("select 1 from _migration where key = :key and done = 1", [
|
$exists = $sqlite->get("select 1 from _migration where key = :key and done = 1", [
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
namespace nur\sery\db\sqlite;
|
||||||
|
|
||||||
|
use nur\sery\StateException;
|
||||||
|
use nur\sery\ValueException;
|
||||||
|
use SQLite3;
|
||||||
|
use SQLite3Stmt;
|
||||||
|
|
||||||
|
class SqliteQuery {
|
||||||
|
static function verifix(&$query, ?array &$params=null): void {
|
||||||
|
if (is_array($query)) {
|
||||||
|
throw StateException::not_implemented(); #XXX
|
||||||
|
$prefix = $query[0] ?? null;
|
||||||
|
if ($prefix === null) {
|
||||||
|
throw new ValueException("requête invalide");
|
||||||
|
} elseif (self::is_create($prefix)) {
|
||||||
|
$query = self::parse_create($query, $params);
|
||||||
|
} elseif (self::is_select($prefix)) {
|
||||||
|
$query = self::parse_select($query, $params);
|
||||||
|
} elseif (self::is_insert($prefix)) {
|
||||||
|
$query = self::parse_insert($query, $params);
|
||||||
|
} elseif (self::is_update($prefix)) {
|
||||||
|
$query = self::parse_update($query, $params);
|
||||||
|
} elseif (self::is_delete($prefix)) {
|
||||||
|
$query = self::parse_delete($query, $params);
|
||||||
|
} else {
|
||||||
|
throw new ValueException("requête invalide");
|
||||||
|
}
|
||||||
|
} elseif (!is_string($query)) {
|
||||||
|
$query = strval($query);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const create_SCHEMA = [
|
||||||
|
"prefix" => "string",
|
||||||
|
"table" => "string",
|
||||||
|
"cols" => "array",
|
||||||
|
"suffix" => "?string",
|
||||||
|
];
|
||||||
|
static function is_create(string $sql): bool {
|
||||||
|
}
|
||||||
|
static function parse_create(array $query, ?array &$params=null): string {
|
||||||
|
}
|
||||||
|
|
||||||
|
const select_SCHEMA = [
|
||||||
|
"prefix" => "string",
|
||||||
|
"cols" => "?array",
|
||||||
|
"from" => "?string",
|
||||||
|
"where" => "?array",
|
||||||
|
"order by" => "?array",
|
||||||
|
"group by" => "?array",
|
||||||
|
"having" => "?array",
|
||||||
|
];
|
||||||
|
static function is_select(string $sql): bool {
|
||||||
|
}
|
||||||
|
static function parse_select(array $query, ?array &$params=null): string {
|
||||||
|
}
|
||||||
|
|
||||||
|
const insert_SCHEMA = [
|
||||||
|
"prefix" => "string",
|
||||||
|
"into" => "?string",
|
||||||
|
"cols" => "?array",
|
||||||
|
"values" => "?array",
|
||||||
|
];
|
||||||
|
static function is_insert(string $sql): bool {
|
||||||
|
}
|
||||||
|
static function parse_insert(array $query, ?array &$params=null): string {
|
||||||
|
}
|
||||||
|
|
||||||
|
const update_SCHEMA = [
|
||||||
|
"prefix" => "string",
|
||||||
|
"table" => "?string",
|
||||||
|
"cols" => "?array",
|
||||||
|
"values" => "?array",
|
||||||
|
"where" => "?array",
|
||||||
|
];
|
||||||
|
static function is_update(string $sql): bool {
|
||||||
|
}
|
||||||
|
static function parse_update(array $query, ?array &$params=null): string {
|
||||||
|
}
|
||||||
|
|
||||||
|
const delete_SCHEMA = [
|
||||||
|
"prefix" => "string",
|
||||||
|
"from" => "?string",
|
||||||
|
"where" => "?array",
|
||||||
|
];
|
||||||
|
static function is_delete(string $sql): bool {
|
||||||
|
}
|
||||||
|
static function parse_delete(array $query, ?array &$params=null): string {
|
||||||
|
}
|
||||||
|
|
||||||
|
function __construct($sql, ?array $params=null) {
|
||||||
|
self::verifix($sql, $params);
|
||||||
|
$this->sql = $sql;
|
||||||
|
$this->params = $params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var string */
|
||||||
|
protected $sql;
|
||||||
|
|
||||||
|
/** @var ?array */
|
||||||
|
protected $params;
|
||||||
|
|
||||||
|
function useStmt(SQLite3 $db, ?SQLite3Stmt &$stmt=null, ?string &$sql=null): bool {
|
||||||
|
if ($this->params !== null) {
|
||||||
|
/** @var SQLite3Stmt $stmt */
|
||||||
|
$stmt = SqliteException::check($db, $db->prepare($this->sql));
|
||||||
|
$close = true;
|
||||||
|
try {
|
||||||
|
foreach ($this->params as $param => $value) {
|
||||||
|
SqliteException::check($db, $stmt->bindValue($param, $value));
|
||||||
|
}
|
||||||
|
$close = false;
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
if ($close) $stmt->close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$sql = $this->sql;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue