implémenter insert
This commit is contained in:
		
							parent
							
								
									2d8a19e232
								
							
						
					
					
						commit
						bdc0ce23ed
					
				@ -93,14 +93,14 @@ class Sqlite {
 | 
			
		||||
    return SqliteException::check($this->db, $result);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function _exec(string $sql): bool {
 | 
			
		||||
  function _exec(string $query): bool {
 | 
			
		||||
    $this->open();
 | 
			
		||||
    return $this->db->exec($sql);
 | 
			
		||||
    return $this->db->exec($query);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function exec($sql, ?array $params=null): bool {
 | 
			
		||||
  function exec($query, ?array $params=null): bool {
 | 
			
		||||
    $this->open();
 | 
			
		||||
    $query = new _Query($sql, $params);
 | 
			
		||||
    $query = new _Query($query, $params);
 | 
			
		||||
    $db = $this->db;
 | 
			
		||||
    if ($query->useStmt($db, $stmt, $sql)) {
 | 
			
		||||
      try {
 | 
			
		||||
@ -113,14 +113,14 @@ class Sqlite {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function _get(string $sql, bool $entireRow=false) {
 | 
			
		||||
  function _get(string $query, bool $entireRow=false) {
 | 
			
		||||
    $this->open();
 | 
			
		||||
    return $this->db->querySingle($sql, $entireRow);
 | 
			
		||||
    return $this->db->querySingle($query, $entireRow);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function get($sql, ?array $params=null, bool $entireRow=false) {
 | 
			
		||||
  function get($query, ?array $params=null, bool $entireRow=false) {
 | 
			
		||||
    $this->open();
 | 
			
		||||
    $query = new _Query($sql, $params);
 | 
			
		||||
    $query = new _Query($query, $params);
 | 
			
		||||
    $db = $this->db;
 | 
			
		||||
    if ($query->useStmt($db, $stmt, $sql)) {
 | 
			
		||||
      try {
 | 
			
		||||
@ -151,9 +151,9 @@ class Sqlite {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function all($sql, ?array $params=null): iterable {
 | 
			
		||||
  function all($query, ?array $params=null): iterable {
 | 
			
		||||
    $this->open();
 | 
			
		||||
    $query = new _Query($sql, $params);
 | 
			
		||||
    $query = new _Query($query, $params);
 | 
			
		||||
    $db = $this->db;
 | 
			
		||||
    if ($query->useStmt($db, $stmt, $sql)) {
 | 
			
		||||
      try {
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,11 @@ class _Config {
 | 
			
		||||
 | 
			
		||||
  function configure(Sqlite $sqlite): void {
 | 
			
		||||
    foreach ($this->configs as $key => $config) {
 | 
			
		||||
      if (is_callable($config)) {
 | 
			
		||||
        func::call($config, $sqlite, $key, $this);
 | 
			
		||||
      } else {
 | 
			
		||||
      if (is_string($config) && !func::is_method($config)) {
 | 
			
		||||
        $sqlite->exec($config);
 | 
			
		||||
      } else {
 | 
			
		||||
        func::ensure_func($config, $this, $args);
 | 
			
		||||
        func::call($config, $sqlite, $key, ...$args);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,11 @@ class _Migration {
 | 
			
		||||
          "value" => $migration,
 | 
			
		||||
          "done" => 0,
 | 
			
		||||
        ]);
 | 
			
		||||
        if (is_callable($migration)) {
 | 
			
		||||
          func::call($migration, $sqlite, $key, $this);
 | 
			
		||||
        } else {
 | 
			
		||||
        if (is_string($migration) && !func::is_method($migration)) {
 | 
			
		||||
          $sqlite->exec($migration);
 | 
			
		||||
        } else {
 | 
			
		||||
          func::ensure_func($migration, $this, $args);
 | 
			
		||||
          func::call($migration, $sqlite, $key, ...$args);
 | 
			
		||||
        }
 | 
			
		||||
        $sqlite->exec("update _migration set done = 1 where key = :key", [
 | 
			
		||||
          "key" => $key,
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,8 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nur\sery\db\sqlite;
 | 
			
		||||
 | 
			
		||||
use nur\sery\StateException;
 | 
			
		||||
use nur\sery\cl;
 | 
			
		||||
use nur\sery\str;
 | 
			
		||||
use nur\sery\ValueException;
 | 
			
		||||
use SQLite3;
 | 
			
		||||
use SQLite3Stmt;
 | 
			
		||||
@ -9,7 +10,6 @@ use SQLite3Stmt;
 | 
			
		||||
class _Query {
 | 
			
		||||
  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");
 | 
			
		||||
@ -31,19 +31,28 @@ class _Query {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static function consume(string $pattern, string &$string, ?array &$ms=null): bool {
 | 
			
		||||
    if (!preg_match("/^$pattern/i", $string, $ms)) return false;
 | 
			
		||||
    $string = substr($string, strlen($ms[0]));
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const create_SCHEMA = [
 | 
			
		||||
    "prefix" => "string",
 | 
			
		||||
    "table" => "string",
 | 
			
		||||
    "cols" => "array",
 | 
			
		||||
    "schema" => "?array",
 | 
			
		||||
    "cols" => "?array",
 | 
			
		||||
    "suffix" => "?string",
 | 
			
		||||
  ];
 | 
			
		||||
  static function is_create(string $sql): bool {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  static function parse_create(array $query, ?array &$params=null): string {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const select_SCHEMA = [
 | 
			
		||||
    "prefix" => "string",
 | 
			
		||||
    "schema" => "?array",
 | 
			
		||||
    "cols" => "?array",
 | 
			
		||||
    "from" => "?string",
 | 
			
		||||
    "where" => "?array",
 | 
			
		||||
@ -52,6 +61,7 @@ class _Query {
 | 
			
		||||
    "having" => "?array",
 | 
			
		||||
  ];
 | 
			
		||||
  static function is_select(string $sql): bool {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  static function parse_select(array $query, ?array &$params=null): string {
 | 
			
		||||
  }
 | 
			
		||||
@ -59,22 +69,90 @@ class _Query {
 | 
			
		||||
  const insert_SCHEMA = [
 | 
			
		||||
    "prefix" => "string",
 | 
			
		||||
    "into" => "?string",
 | 
			
		||||
    "schema" => "?array",
 | 
			
		||||
    "cols" => "?array",
 | 
			
		||||
    "values" => "?array",
 | 
			
		||||
  ];
 | 
			
		||||
  static function is_insert(string $sql): bool {
 | 
			
		||||
    return preg_match("/^insert\b/i", $sql);
 | 
			
		||||
  }
 | 
			
		||||
  static function parse_insert(array $query, ?array &$params=null): string {
 | 
			
		||||
    # fusionner d'abord toutes les parties séquentielles
 | 
			
		||||
    $index = 0;
 | 
			
		||||
    $tmpsql = "";
 | 
			
		||||
    foreach ($query as $key => $value) {
 | 
			
		||||
      if ($key === $index) {
 | 
			
		||||
        $index++;
 | 
			
		||||
        if ($tmpsql && !str::ends_with(" ", $tmpsql) && !str::starts_with(" ", $value)) {
 | 
			
		||||
          $tmpsql .= " ";
 | 
			
		||||
        }
 | 
			
		||||
        $tmpsql .= $value;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $usersql = $tmpsql;
 | 
			
		||||
    # vérifier la présence des parties nécessaires
 | 
			
		||||
    $sql = [];
 | 
			
		||||
    if (($prefix = $query["prefix"] ?? null) !== null) {
 | 
			
		||||
      $sql["prefix"] = $prefix;
 | 
			
		||||
    }
 | 
			
		||||
    self::consume('insert\s*', $tmpsql); $sql[] = "insert";
 | 
			
		||||
    self::consume('into\s*', $tmpsql); $sql[] = "into";
 | 
			
		||||
    if (self::consume('([a-z_][a-z0-9_]*)\s*', $tmpsql, $ms)) {
 | 
			
		||||
      $sql[] = $ms[1];
 | 
			
		||||
    } elseif (($into = $query["into"] ?? null) !== null) {
 | 
			
		||||
      $sql[] = $into;
 | 
			
		||||
    } else {
 | 
			
		||||
      throw new ValueException("expected table name: $usersql");
 | 
			
		||||
    }
 | 
			
		||||
    $xcols = [];
 | 
			
		||||
    $xvalues = [];
 | 
			
		||||
    if (self::consume('\(([^)]*)\)\s*', $tmpsql, $ms)) {
 | 
			
		||||
      $xcols = array_merge($xcols, preg_split("/\s*,\s*/", $ms[1]));
 | 
			
		||||
    }
 | 
			
		||||
    $cols = cl::withn($query["cols"] ?? null);
 | 
			
		||||
    $values = cl::withn($query["values"] ?? null);
 | 
			
		||||
    $schema = $query["schema"] ?? null;
 | 
			
		||||
    if ($cols === null) {
 | 
			
		||||
      if ($xcols) {
 | 
			
		||||
        $cols = $xcols;
 | 
			
		||||
      } elseif ($values) {
 | 
			
		||||
        $cols = array_keys($values);
 | 
			
		||||
        $xcols = array_merge($xcols, $cols);
 | 
			
		||||
      } elseif ($schema && is_array($schema)) {
 | 
			
		||||
        #XXX implémenter support AssocSchema
 | 
			
		||||
        $cols = array_keys($schema);
 | 
			
		||||
        $xcols = array_merge($xcols, $cols);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (self::consume('values\s+\(\s*(.*)\s*\)\s*', $tmpsql, $ms)) {
 | 
			
		||||
      if ($ms[1]) $xvalues[] = $ms[1];
 | 
			
		||||
    }
 | 
			
		||||
    self::consume(';\s*', $tmpsql);
 | 
			
		||||
    if ($tmpsql) {
 | 
			
		||||
      throw new ValueException("unexpected value at end: $usersql");
 | 
			
		||||
    }
 | 
			
		||||
    if ($cols !== null && !$xvalues) {
 | 
			
		||||
      if (!$xcols) $xcols = $cols;
 | 
			
		||||
      foreach ($cols as $col) {
 | 
			
		||||
        $xvalues[] = ":$col";
 | 
			
		||||
        $params[$col] = $values[$col] ?? null;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $sql[] = "(".implode(", ", $xcols).")";
 | 
			
		||||
    $sql[] = "values (".implode(", ", $xvalues).")";
 | 
			
		||||
    return implode(" ", $sql);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const update_SCHEMA = [
 | 
			
		||||
    "prefix" => "string",
 | 
			
		||||
    "table" => "?string",
 | 
			
		||||
    "schema" => "?array",
 | 
			
		||||
    "cols" => "?array",
 | 
			
		||||
    "values" => "?array",
 | 
			
		||||
    "where" => "?array",
 | 
			
		||||
  ];
 | 
			
		||||
  static function is_update(string $sql): bool {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  static function parse_update(array $query, ?array &$params=null): string {
 | 
			
		||||
  }
 | 
			
		||||
@ -85,6 +163,7 @@ class _Query {
 | 
			
		||||
    "where" => "?array",
 | 
			
		||||
  ];
 | 
			
		||||
  static function is_delete(string $sql): bool {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  static function parse_delete(array $query, ?array &$params=null): string {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -33,4 +33,33 @@ class SqliteTest extends TestCase {
 | 
			
		||||
      ["key" => "1", "value" => self::INSERT_JEPHTE, "done" => 1],
 | 
			
		||||
    ], iterator_to_array($sqlite->all("select key, value, done from _migration")));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function testInsert() {
 | 
			
		||||
    $sqlite = new Sqlite(":memory:", [
 | 
			
		||||
      "migrate" => "create table mapping (i integer, s varchar)"
 | 
			
		||||
    ]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping", "values" => ["i" => 1, "s" => "un"]]);
 | 
			
		||||
    $sqlite->exec(["insert mapping", "values" => ["i" => 2, "s" => "deux"]]);
 | 
			
		||||
    $sqlite->exec(["insert into", "into" => "mapping", "values" => ["i" => 3, "s" => "trois"]]);
 | 
			
		||||
    $sqlite->exec(["insert", "into" => "mapping", "values" => ["i" => 4, "s" => "quatre"]]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping(i)", "values" => ["i" => 5, "s" => "cinq"]]);
 | 
			
		||||
    $sqlite->exec(["insert into (i)", "into" => "mapping", "values" => ["i" => 6, "s" => "six"]]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping(i) values ()", "values" => ["i" => 7, "s" => "sept"]]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping(i) values (8)", "values" => ["i" => 42, "s" => "whatever"]]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping(i, s) values (9, 'neuf')", "values" => ["i" => 43, "s" => "garbage"]]);
 | 
			
		||||
    $sqlite->exec(["insert into mapping", "cols" => ["i"], "values" => ["i" => 10, "s" => "dix"]]);
 | 
			
		||||
 | 
			
		||||
    self::assertSame([
 | 
			
		||||
      ["i" => 1, "s" => "un"],
 | 
			
		||||
      ["i" => 2, "s" => "deux"],
 | 
			
		||||
      ["i" => 3, "s" => "trois"],
 | 
			
		||||
      ["i" => 4, "s" => "quatre"],
 | 
			
		||||
      ["i" => 5, "s" => null/*"cinq"*/],
 | 
			
		||||
      ["i" => 6, "s" => null/*"six"*/],
 | 
			
		||||
      ["i" => 7, "s" => null/*"sept"*/],
 | 
			
		||||
      ["i" => 8, "s" => null/*"huit"*/],
 | 
			
		||||
      ["i" => 9, "s" => "neuf"],
 | 
			
		||||
      ["i" => 10, "s" => null/*"dix"*/],
 | 
			
		||||
    ], iterator_to_array($sqlite->all("select * from mapping")));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user