158 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/php
 | 
						|
<?php
 | 
						|
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
 | 
						|
 | 
						|
use nur\b\io\CacheFile;
 | 
						|
use nur\cli\Application;
 | 
						|
use nur\msg;
 | 
						|
use nur\path;
 | 
						|
use nur\sery\db\Capacitor;
 | 
						|
use nur\sery\db\CapacitorChannel;
 | 
						|
use nur\sery\db\sqlite\SqliteStorage;
 | 
						|
use nur\sery\file\Stream;
 | 
						|
use nur\yaml;
 | 
						|
 | 
						|
Application::run(new class extends Application {
 | 
						|
  const ACTION_QUERY = 0, ACTION_SQL = 1;
 | 
						|
 | 
						|
  const ARGS = [
 | 
						|
    "merge" => parent::ARGS,
 | 
						|
    "purpose" => "gestion d'un capacitor sqlite",
 | 
						|
    "usage" => [
 | 
						|
      "-f DBFILE -n CHANNEL [--query] key=value...",
 | 
						|
      "-f DBFILE -n CHANNEL --sql-create",
 | 
						|
    ],
 | 
						|
    ["-f", "--dbfile", "args" => 1,
 | 
						|
      "help" => "chemin vers la base de données",
 | 
						|
    ],
 | 
						|
    ["-n", "--name", "args" => 1,
 | 
						|
      "help" => "nom du canal de données. table-name et channel-class sont chargés depuis la base de données",
 | 
						|
    ],
 | 
						|
    ["-t", "--table-name", "args" => 1,
 | 
						|
      "help" => "nom de la table porteuse du canal de données",
 | 
						|
    ],
 | 
						|
    ["-c", "--channel-class", "args" => 1,
 | 
						|
      "help" => "nom de la classe dérivée de CapacitorChannel",
 | 
						|
    ],
 | 
						|
    ["--query", "name" => "action", "value" => self::ACTION_QUERY,
 | 
						|
      "help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut",
 | 
						|
    ],
 | 
						|
    ["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
 | 
						|
      "help" => "afficher la requête pour créer la table",
 | 
						|
    ],
 | 
						|
  ];
 | 
						|
 | 
						|
  protected ?string $dbfile = null;
 | 
						|
 | 
						|
  protected ?string $name = null;
 | 
						|
 | 
						|
  protected ?string $tableName = null;
 | 
						|
 | 
						|
  protected ?string $channelClass = null;
 | 
						|
 | 
						|
  protected int $action = self::ACTION_QUERY;
 | 
						|
 | 
						|
  protected ?array $args = null;
 | 
						|
 | 
						|
  protected static function isa_cond(string $arg, ?array &$ms=null): bool {
 | 
						|
    return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms);
 | 
						|
  }
 | 
						|
 | 
						|
  function main() {
 | 
						|
    $dbfile = $this->dbfile;
 | 
						|
    if ($dbfile === null) self::die("Vous devez spécifier la base de données");
 | 
						|
    if (!file_exists($dbfile)) self::die("$dbfile: fichier introuvable");
 | 
						|
    $storage = new SqliteStorage($dbfile);
 | 
						|
    $db = $storage->db();
 | 
						|
 | 
						|
    $haveChannels = $storage->tableExists("_channels");
 | 
						|
 | 
						|
    $name = $this->name;
 | 
						|
    $channelClass = $this->channelClass;
 | 
						|
    $tableName = $this->tableName;
 | 
						|
    if ($name !== null) {
 | 
						|
      $row = null;
 | 
						|
      if ($haveChannels) {
 | 
						|
        $row = $db->one([
 | 
						|
          "select from _channels",
 | 
						|
          "where" => ["name" => $name],
 | 
						|
        ]);
 | 
						|
      }
 | 
						|
      if ($row === null) self::die("$name: nom de canal de données introuvable");
 | 
						|
      if ($row["class"] !== "class@anonymous") $channelClass = $row["class"];
 | 
						|
      else $tableName = $row["table_name"];
 | 
						|
    }
 | 
						|
    if ($channelClass !== null) {
 | 
						|
      $channelClass = str_replace("/", "\\", $channelClass);
 | 
						|
      $channel = new $channelClass;
 | 
						|
    } elseif ($tableName !== null) {
 | 
						|
      $channel = new class($tableName) extends CapacitorChannel {
 | 
						|
        function __construct(?string $name=null) {
 | 
						|
          parent::__construct($name);
 | 
						|
          $this->tableName = $name;
 | 
						|
        }
 | 
						|
      };
 | 
						|
    } else {
 | 
						|
      $found = false;
 | 
						|
      if ($haveChannels) {
 | 
						|
        $rows = $db->all([
 | 
						|
          "select from _channels",
 | 
						|
        ]);
 | 
						|
        foreach ($rows as $row) {
 | 
						|
          msg::print($row["name"]);
 | 
						|
          $found = true;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      if (!$found) self::die("Vous devez spécifier le canal de données");
 | 
						|
    }
 | 
						|
    $capacitor = new Capacitor($storage, $channel);
 | 
						|
 | 
						|
    switch ($this->action) {
 | 
						|
    case self::ACTION_QUERY:
 | 
						|
      $args = $this->args;
 | 
						|
      var_export($args); #XXX
 | 
						|
      if (!$args) {
 | 
						|
        # lister les id
 | 
						|
        $out = new Stream(STDOUT);
 | 
						|
        $primaryKeys = $storage->getPrimaryKeys($channel);
 | 
						|
        var_export($primaryKeys); #XXX
 | 
						|
        $rows = $db->all([
 | 
						|
          "select",
 | 
						|
          "cols" => $primaryKeys,
 | 
						|
          "from" => $channel->getTableName(),
 | 
						|
        ]);
 | 
						|
        $out->fputcsv($primaryKeys);
 | 
						|
        foreach ($rows as $row) {
 | 
						|
          $rowIds = $storage->getRowIds($channel, $row);
 | 
						|
          $out->fputcsv($rowIds);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        # afficher les lignes correspondantes
 | 
						|
        if (count($args) == 1 && !self::isa_cond($args[0])) {
 | 
						|
          $filter = $args[0];
 | 
						|
        } else {
 | 
						|
          $filter = [];
 | 
						|
          $ms = null;
 | 
						|
          foreach ($args as $arg) {
 | 
						|
            if (self::isa_cond($arg, $ms)) {
 | 
						|
              $filter[$ms[1]] = [$ms[2], $ms[3]];
 | 
						|
            } else {
 | 
						|
              $filter[$arg] = ["not null"];
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
        $first = true;
 | 
						|
        $capacitor->each($filter, function ($item, $row) use (&$first) {
 | 
						|
          if ($first) $first = false;
 | 
						|
          else echo "---\n";
 | 
						|
          yaml::dump($row);
 | 
						|
        });
 | 
						|
      }
 | 
						|
      break;
 | 
						|
    case self::ACTION_SQL:
 | 
						|
      echo $capacitor->getCreateSql()."\n";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
});
 |