.gitignore 0000644 00000000052 14476160726 0006546 0 ustar 00 /vendor/
/tests/
composer.lock
.vscode/
composer.json 0000644 00000000746 14476160726 0007312 0 ustar 00 {
"name": "boru/dhdb",
"type": "library",
"autoload": {
"psr-4": {
"boru\\dhdb\\": "src/"
}
},
"authors": [
{
"name": "Daniel Hayes",
"email": "dhayes@boruapps.com"
}
],
"require": {
"boru/dhutils": "*",
"greenlion/php-sql-parser": "^4.6"
},
"repositories": [
{
"type": "composer",
"url": "https://satis.boruapps.com"
}
]
}
instructions-composer.txt 0000644 00000000311 14476160726 0011706 0 ustar 00 {
"require": {
"boru/dhout": "dev-master"
},
"repositories": [
{
"type": "composer",
"url": "https://satis.boruapps.com"
}
]
} src/Error.php 0000644 00000004777 14476160726 0007171 0 ustar 00 setMessage($message);
$this->setQuery($query);
$this->setParams($params);
$this->setInterpolated($interpolated);
$this->setTrace($trace);
}
public function log() {
dhGlobal::error("Query Error with query:".PHP_EOL.$this->query.PHP_EOL." ");
dhGlobal::error("Interpolated:".PHP_EOL.$this->interpolated.PHP_EOL." ");
dhGlobal::error("Message:".PHP_EOL.$this->message.PHP_EOL." ");
dhGlobal::error("Stack Trace:".PHP_EOL.$this->trace.PHP_EOL." ");
}
/**
* Get the value of message
*/
public function getMessage()
{
return $this->message;
}
/**
* Set the value of message
*
* @return self
*/
public function setMessage($message)
{
$this->message = $message;
return $this;
}
/**
* Get the value of query
*/
public function getQuery()
{
return $this->query;
}
/**
* Set the value of query
*
* @return self
*/
public function setQuery($query)
{
$this->query = $query;
return $this;
}
/**
* Get the value of params
*/
public function getParams()
{
return $this->params;
}
/**
* Set the value of params
*
* @return self
*/
public function setParams($params)
{
$this->params = $params;
return $this;
}
/**
* Get the value of trace
*/
public function getTrace()
{
return $this->trace;
}
/**
* Set the value of trace
*
* @return self
*/
public function setTrace($trace)
{
$this->trace = $trace;
return $this;
}
/**
* Get the value of interpolated
*
* @return mixed
*/
public function getInterpolated() {
return $this->interpolated;
}
/**
* Set the value of interpolated
*
* @param mixed $interpolated
* @return self
*/
public function setInterpolated($interpolated) {
$this->interpolated = $interpolated;
return $this;
}
} src/Query.php 0000644 00000013240 14476160726 0007166 0 ustar 00 rawQueryString = $queryString;
}
public function getQuery($interpolate=false) {
$sql = $this->driver->fromQuery($this);
if($interpolate) {
return $this->driver->interpolateQuery($sql,$this->value);
}
return $sql;
}
public function insert($i,$v=null) {
$this->type = "insert";
return $this->column($i,$v);
}
public function select($s) {
$this->type = "select";
return $this->column($s);
}
public function update($i,$v) {
$this->type = "update";
return $this->updateValue($i,$v);
}
public function create($t,$ifNotExists=false) {
$this->type = "create";
$this->ifNotExists = $ifNotExists;
return $this->table($t);
}
public function alter($t) {
$this->type = "alter";
return $this->table($t);
}
public function into(...$args) {
return $this->table(...$args);
}
public function from(...$args) {
return $this->table(...$args);
}
public function join(...$args) {
return $this->table(...$args);
}
public function where($c,$v=null) {
return $this->condition($c,$v);
}
public function order($o) {
$this->orderBy[] = $o;
return $this;
}
public function orderBy($o) {
$this->orderBy[] = $o;
return $this;
}
public function group($o) {
$this->groupBy[] = $o;
return $this;
}
public function groupBy($o) {
$this->groupBy[] = $o;
return $this;
}
public function limit($num,$start=0) {
$this->limit = [];
$this->limit[] = $start;
$this->limit[] = $num;
return $this;
}
public function add($col,$type=null,$extra=null) {
return $this->schemaColumn("add",$col,$type,$extra);
}
public function remove($col) {
return $this->schemaColumn("drop",$col);
}
public function change($col,$newcol,$type=null,$extra=null) {
return $this->schemaColumn("change",[$col,$newcol],$type,$extra);
}
public function addIndex($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function key($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function index($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function dropIndex($name) {
return $this->schemaColumn("dropIndex",$name);
}
public function meta($key,$value=null) {
if($this->type == "create" || $this->type == "alter") {
$this->tableMeta[] = ["key"=>$key,"value"=>$value];
}
return $this;
}
public function schemaColumn($action="add",$col,$type=null,$extra=null) {
$this->schemaColumns[] = ["action"=>$action,"column"=>$col,"type"=>$type, "extra"=>$extra];
return $this;
}
public function column($c,$v=null,$extraIfAlterOrAdd=null) {
if($this->type == "create" || $this->type == "alter") {
return $this->add($c,$v,$extraIfAlterOrAdd);
} else {
if(is_array($c)) {
foreach($c as $col) {
$this->columns[] = $col;
}
} else {
$this->columns[] = $c;
}
if(!is_null($v)) {
if(is_array($v)) {
foreach($v as $val) {
$this->value($v);
}
} else {
$this->value($v);
}
}
return $this;
}
}
public function updateValue($c,$v=null) {
if(!is_array($c) && !is_null($v)) {
$this->columns[] = $c."=?";
$this->values[] = $v;
} else {
return $this->column($c,$v);
}
return $this;
}
public function condition($c,$v=null) {
if(is_array($c)) {
foreach($c as $col) {
$this->conditions[] = $c;
}
} else {
$this->conditions[] = $c;
}
if(!is_null($v)) {
if(is_array($v)) {
foreach($v as $val) {
$this->value($val);
}
} else {
$this->value($v);
}
}
return $this;
}
public function table($t,$type=null,$on=null) {
$this->tables[] = ["name"=>$t,"type"=>$type,"on"=>$on];
return $this;
}
public function values($arr) {
foreach($arr as $v) {
$this->value($v);
}
return $this;
}
public function value($v,$vv=null) {
if(!is_null($vv)) {
$this->values[$v] = $vv;
} else {
if(is_array($v)) {
return $this->values($v);
} else {
$this->values[] = $v;
}
}
return $this;
}
} src/Result.php 0000644 00000000742 14476160726 0007342 0 ustar 00 setTableName($tableName);
}
if(!is_null($file)) {
$this->setFile($file);
if(!is_null($this->file)) {
$this->load();
}
}
}
public function get($version=null) {
$array["name"] = $this->getTableName();
$array["meta"] = $this->getMeta($version);
$array["columns"] = $this->getColumns($version);
$array["keys"] = $this->getKeys($version);
return $array;
}
public function getAll() {
$array["tableName"] = $this->tableName;
$array["meta"] = $this->meta;
$array["columns"] = $this->columns;
$array["keys"] = $this->keys;
$array["history"] = $this->history;
$array["versions"] = $this->versions;
$array["changes"] = $this->changes;
return $array;
}
public function save($makeVersion=true) {
if(!empty($this->changes) && $makeVersion) {
$this->version++;
$versionString = $this->getVersionString();
$this->meta("comment","dhDB::".$versionString);
$this->history[$versionString] = $this->changes;
$this->versions[$versionString]["columns"] = $this->columns;
$this->versions[$versionString]["keys"] = $this->keys;
$this->versions[$versionString]["meta"] = $this->meta;
$this->changes = [];
}
if(!is_null($this->file)) {
$this->file->write(json_encode($this->getAll(),JSON_PRETTY_PRINT));
}
return $this;
}
public function load($clean=true) {
if(!is_null($this->file)) {
$data = $this->file->content(["json"=>true]);
if(is_array($data)) {
if(!$clean) {
$this->meta = dhGlobal::getVal($data,"meta",null);
$this->columns = dhGlobal::getVal($data,"columns",null);
$this->keys = dhGlobal::getVal($data,"keys",null);
}
$this->history = dhGlobal::getVal($data,"history",null);
$this->versions = dhGlobal::getVal($data,"versions",null);
$this->version = 0;
if(is_array($this->versions)) {
foreach($this->versions as $version=>$d) {
$version = intval(dhGlobal::trimString("v_",$version,dhGlobal::TRIM_START));
if($version>$this->version) {
$this->version = $version;
}
}
}
}
}
return $this;
}
public function getColumnHistory($column) {
$columnHistory = [];
if(!empty($this->history)) {
foreach($this->history as $version=>$changes) {
foreach($changes as $change) {
if($change["column"] == $column && strpos($change["action"],"Index") === false) {
$columnHistory[$version][] = $change;
}
}
}
}
return $columnHistory;
}
public function replayHistory($version=null) {
if(!is_null($version)) {
$version = $this->getVersionString($version);
if(isset($this->history[$version])) {
$this->replayHistoryVersion($version);
return true;
}
return false;
} else {
if(!empty($this->history)) {
$versions = array_keys($this->history);
foreach($versions as $version) {
$this->replayHistoryVersion($version);
}
return true;
}
return false;
}
return false;
}
protected function replayHistoryVersion($version) {
foreach($this->history[$version] as $entry) {
$this->schemaColumnEntry($entry);
}
}
public function version($version=null) {
if(is_null($version)) {
return $this->version;
}
if($version === true) {
$this->version++;
} else {
$this->version = $version;
}
return $this;
}
public function add($col,$type=null,$extra=null) {
return $this->schemaColumn("add",$col,$type,$extra);
}
public function remove($col) {
return $this->schemaColumn("drop",$col);
}
public function change($col,$newcol,$type=null,$extra=null) {
return $this->schemaColumn("change",[$col,$newcol],$type,$extra);
}
public function addIndex($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function key($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function index($name,$cols=[],$type="key") {
return $this->schemaColumn("addIndex",$name,strtolower($type),$cols);
}
public function dropIndex($name) {
return $this->schemaColumn("dropIndex",$name);
}
public function meta($key,$value=null,$version=null) {
if($version == null) {
$this->meta[$key] = ["key"=>$key,"value"=>$value];
} else {
$version = $this->getVersionString($version);
$this->versions[$version]["meta"][$key] = ["key"=>$key,"value"=>$value];
}
return $this;
}
protected function parseColExtra($extra,$glue=" ") {
$null = dhGlobal::getVal($extra,"null",false);
$collate = dhGlobal::getVal($extra,"collate",false);
$charset = dhGlobal::getVal($extra,"charset",false);
$default = dhGlobal::getVal($extra,"default",false);
$auto_incr = dhGlobal::getVal($extra,"auto_increment",false);
if(!$charset && $collate !== false) {
list($charset,$unused) = explode("_",$charset,2);
}
$parts = [];
if($charset !== false) {
$parts[] ="CHARACTER SET ".$charset;
}
if($collate !== false) {
$parts[] ="COLLATE ".$collate;
}
if($null) {
if($default === false) {
$parts[] = "DEFAULT NULL";
} else {
$parts[] = 'DEFAULT "'.$default.'"';
}
} else {
$parts[] = "NULL NULL";
if($default !== false) {
$parts[] = 'DEFAULT "'.$default.'"';
}
}
if($auto_incr !== false) {
$parts[] = "AUTO_INCREMENT";
}
return implode($glue,$parts);
}
public function schemaColumn($action="add",$col,$type=null,$extra=null) {
$entry = ["action"=>$action,"column"=>$col,"type"=>$type, "extra"=>$extra];
return $this->schemaColumnEntry($entry);
}
protected function schemaColumnEntry(array $entry) {
if(!is_array($this->changes)) {
$this->changes = [];
}
$changed = $this->processEntry($entry);
if($changed) {
$this->changes[] = $entry;
}
return $this;
}
protected function processEntry(array $entry) {
$action = $entry["action"];
$column = $entry["column"];
$type = $entry["type"];
$extra = $entry["extra"];
if($action == "add") {
if(!isset($this->columns[$column])) {
$this->columns[$column] = ["type"=>$type,"extra"=>$extra];
return true;
}
return false;
} elseif($action == "drop") {
if(isset($this->columns[$column])) {
unset($this->columns[$column]);
return true;
}
return false;
} elseif($action == "change") {
$old = $column[0];
$new = $column[1];
if(isset($this->columns[$old])) {
unset($this->columns[$old]);
$this->columns[$new] = ["type"=>$type,"extra"=>$extra];
return true;
}
if(!isset($this->columns[$new])) {
$entry["action"] == "add";
return $this->processEntry($entry);
}
return false;
} elseif($action == "dropIndex") {
if(isset($this->keys[$column])) {
unset($this->keys[$column]);
return true;
}
return false;
} elseif($action == "addIndex") {
if(!isset($this->keys[$column])) {
$this->keys[$column] = ["type"=>$type,"columns"=>$extra];
return true;
}
return false;
}
}
public function toQuery($patch=false) {
$query = new Query();
$table = $this->getTableName();
if($patch && $this->version>=1) {
return $this->toPatchQuery();
}
$query->create($table);
$after = null;
foreach($this->getColumns($this->version) as $col=>$entry) {
//if(!is_null($after)) {
//$entry["extra"]["after"] = $after;
//}
if(isset($entry["extra"]["after"])) {
unset($entry["extra"]["after"]);
}
$query->add($col,$entry["type"],$entry["extra"]);
$after = $col;
}
foreach($this->getKeys($this->version) as $name=>$entry) {
$query->addIndex($name,$entry["columns"],$entry["type"]);
}
foreach($this->getMeta($this->version) as $key=>$entry) {
$noBlank = ["auto_increment","comment"];
if(in_array($entry["key"],$noBlank) && (is_null($entry["value"]) || empty($entry["value"]))) {
} else {
$query->meta($entry["key"],$entry["value"]);
}
}
return $query;
}
public function toPatchQuery($reorder=false) {
if($this->version<=0) {
return $this->toQuery(false);
}
$changes = 0;
$savedCols = $this->getColumns($this->version);
$curCols = $this->getColumns();
$savedOrder = array_keys($savedCols);
$curOrder = array_keys($curCols);
$columnAfter = [];
$needAfter = [];
foreach($savedOrder as $colname) {
$columnAfter[$colname] = $this->getColumnAfter($colname,$this->version);
}
unset($savedOrder);
foreach($curOrder as $colname) {
if($columnAfter[$colname] != $this->getColumnAfter($colname)) {
$needAfter[$colname] = $columnAfter[$colname];
}
}
unset($curOrder);
$query = new Query();
$table = $this->getTableName();
$query->alter($table);
foreach($curCols as $col=>$entry) {
if(!isset($savedCols[$col])) {
$origCol = $col;
//currentColumn isn't part of the savedCols.. now we see if it changed
$changed = $dropped = false;
$colHist = $this->getColumnHistory($col);
foreach($colHist as $ver=>$changes) {
foreach($changes as $change) {
if($change["action"] == "change" && $change["column"][0] == $col) {
$col = $change["column"][1];
$entry = ["type"=>$change["type"],"extra"=>$change["extra"]];
$changed=true;
}
if($changed && $change["action"] == "drop" && $change["column"] == $col) {
$changed = false;
}
}
}
if($changed) {
if(isset($savedCols[$col])) {
$extra = $savedCols[$col]["extra"];
if(isset($columnAfter[$col])) {
$extra["after"] = $columnAfter[$col];
if(isset($needAfter[$col])) {
unset($needAfter[$col]);
}
}
$query->change($origCol,$col,$savedCols[$col]["type"],$extra);
$changes++;
} else {
throw new \Exception("Couldn't process change for $origCol to $col.. $col not part of current columns. History fail?");
}
} else {
$query->remove($origCol);
$changes++;
}
}
}
$addedCols = [];
foreach($savedCols as $sCol=>$entry) {
if(!isset($curCols[$sCol])) {
$entry["extra"]["after"] = $this->getColumnAfter($sCol,$this->version);
$query->add($sCol,$entry["type"],$entry["extra"]);
$addedCols[] = $sCol;
$changes++;
} else {
$changed = false;
$versionTypeDiff = false;
if(strpos($entry["type"],"(") === false) {
if(substr($curCols[$sCol]["type"],0,strlen($entry["type"])+1) == $entry["type"]."(") {
$versionTypeDiff = true;
}
}
if($entry["type"] != $curCols[$sCol]["type"] && !$versionTypeDiff) {
$changed = true;
} else {
if(!is_array($entry["extra"]) && is_array($curCols[$sCol]["extra"])) {
$changed = true;
} elseif(is_array($entry["extra"]) && !is_array($curCols[$sCol]["extra"])) {
$changed = true;
} elseif(count($entry["extra"]) !== count($curCols[$sCol]["extra"])) {
$changed = true;
} else {
foreach($entry["extra"] as $e=>$ev) {
if(!isset($curCols[$sCol]["extra"][$e]) || $curCols[$sCol]["extra"][$e] != $ev) {
$changed = true;
}
}
}
}
if($changed) {
$entry["extra"]["after"] = $this->getColumnAfter($sCol,$this->version);
if(isset($needAfter[$sCol])) {
unset($needAfter[$sCol]);
}
$query->change($sCol,$sCol,$entry["type"],$entry["extra"]);
$changes++;
}
}
}
if(!empty($needAfter)) {
foreach($needAfter as $col=>$after) {
if(in_array($after,$addedCols)) {
} else {
$extra = $savedCols[$col]["extra"];
$extra["after"] = $after;
$query->change($col,$col,$savedCols[$col]["type"],$extra);
$changes++;
}
}
}
//TODO: order check //$entry["extra"]["after"] = $this->getColumnAfter($sCol,$this->version);
if($changes>0) {
foreach($this->getMeta($this->version) as $key=>$entry) {
if($entry["key"] == "auto_increment")
$query->meta($entry["key"],$entry["value"]);
}
return $query;
}
return false;
}
protected function getColumnAfter($colName,$version=null) {
$columns = $this->getColumns($version);
$colKeys = array_keys($columns);
$after = false;
foreach($colKeys as $sCol) {
if($sCol == $colName) {
return $after;
}
$after = $sCol;
}
return $after;
}
public function jsonSerialize($array=null) {
if(is_null($array)) {
}
return $array;
}
public function __toString() {
return json_encode($this);
}
/**
* Get the value of tableName
*/
public function getTableName() {
return $this->tableName;
}
/**
* Get the value of columns
*/
public function getColumns($version=null) {
if($version == null) {
return $this->columns;
} else {
$version = $this->getVersionString($version);
return dhGlobal::getVal($this->versions[$version],"columns",null);
}
}
/**
* Get the value of keys
*/
public function getKeys($version=null) {
if($version == null) {
return $this->keys;
} else {
$version = $this->getVersionString($version);
return dhGlobal::getVal($this->versions[$version],"keys",null);
}
}
/**
* Get the value of meta
*/
public function getMeta($version=null) {
if($version == null) {
return $this->meta;
} else {
$version = $this->getVersionString($version);
return dhGlobal::getVal($this->versions[$version],"meta",null);
}
}
/**
* Get the value of versions
*/
public function getVersions() {
return $this->versions;
}
/**
* Get the value of history
*/
public function getHistory($version=null) {
if($version == null) {
return $this->history;
} else {
$version = $this->getVersionString($version);
return dhGlobal::getVal($this->history,$version,null);
}
}
/**
* Get the value of changes
*
* @return mixed
*/
public function getChanges() {
return $this->changes;
}
/**
* Set the value of columns
*
* @return self
*/
public function setColumns($columns) {
$this->columns = $columns;
return $this;
}
/**
* Set the value of tableName
*
* @return self
*/
public function setTableName($tableName) {
$this->tableName = $tableName;
return $this;
}
/**
* Set the value of keys
*
* @return self
*/
public function setKeys($keys) {
$this->keys = $keys;
return $this;
}
/**
* Set the value of meta
*
* @return self
*/
public function setMeta($meta) {
$this->meta = $meta;
return $this;
}
/**
* Get the value of file
*
* @return mixed
*/
public function getFile() {
return $this->file;
}
/**
* Set the value of file
*
* @param File|String $file
* @return self
*/
public function setFile($file) {
if(!is_object($file)) {
if(is_string($file)) {
$this->file = new File(["path"=>$file]);
} elseif(is_array($file)) {
$this->file = new File($file);
}
} else {
$this->file = $file;
}
return $this;
}
protected function getVersionString($version=null) {
if(is_null($version)) {
$version = $this->version;
}
if(!is_numeric($version)) {
return $version;
}
return "v_".$version;
}
} src/async/AsyncActions.php 0000644 00000001440 14476160726 0011573 0 ustar 00 run($query,$params);
if($res === false) {
return !($returnResult) ? false : ["success"=>false,"error"=>$db->getError()];
} else {
return !($returnResult) ? true : ["success"=>true,"results"=>$res->all()];
}
}
} src/async/QueryQueue.php 0000644 00000022264 14476160726 0011316 0 ustar 00 threads = dhGlobal::getVal($options,"threads" ,$this->threads);
$this->visualize = dhGlobal::getVal($options,"visualize" ,$this->visualize);
$this->extended = dhGlobal::getVal($options,"extended" ,$this->extended);
$this->bootstrap = dhGlobal::getVal($options,"bootstrap" ,$this->bootstrap);
$this->expected = dhGlobal::getVal($options,"expected" ,$this->expected);
}
private function initQueue() {
if(is_null($this->bootstrap)) {
$this->bootstrap = $this->getAsyncBoostrapCallable();
}
$this->queue = new Queue($this->threads,$this->bootstrap,null,$this->visualize);
if(is_array($this->bootstrap)) {
$this->queue->setBootstrapAsCallable(true);
}
$this->queue->setMaxQueued($this->threads*3);
if($this->extended) {
$this->queue->enableExtendedBar(true);
}
if(!is_null($this->expected)) {
$this->queue->setExpected($this->expected);
}
$this->queueDeferred = new Deferred();
}
/**
* @return QueryQueueResult[]
*/
public function wait() {
$this->queue->wait();
return $this->results;
}
/**
* @return QueryQueueResult[]
*/
public function collect() {
return $this->wait();
}
/**
* Queue a query -- split this out into it's own class so that multiple queues can be running at once, if needed.
* @param mixed $query
* @param array $params
* @param bool $returnResult
* @param mixed $display
* @return AsyncWork
* @throws Exception
* @throws UnexpectedValueException
* @throws RuntimeException
*/
public function queue($query,$params=[],$returnResult=true,$display=null) {
if(is_null($this->queue)) {
$this->initQueue();
}
$callable = ["\\boru\\dhdb\\async\\AsyncActions","asyncQuery"];
if(is_object($query)) {
$info = $this->getDb()->getQueryFromObject($query,$params);
$sql = $info["query"];
$params = $info["params"];
} else {
$sql = $query;
}
$args = [$sql,$params,$returnResult];
$work = new AsyncWork($callable,["args"=>$args,"asJson"=>false]);
if($this->visualize && is_null($display)) {
$display = json_encode($params);
if(strlen($display) >= 24) {
$display=substr($display,0,20)." ...";
}
}
$work->then(function(AsyncResult $result) use ($display)
{
$this->handleQueueWorkResult($result->getWorkId(),$display,$result);
},
function(AsyncResult $result) use ($display)
{
$this->handleQueueWorkResult($result->getWorkId(),$display,$result,true);
});
$work->onStart(function($work) use ($display)
{
$this->results[$work->getId()]->started(microtime(true));
$this->visualizeQueue("start",$work->getId(),$display);
});
$this->results[$work->getId()] = new QueryQueueResult($sql,$params);
$this->queue->queue($work);
return $work;
}
private function handleQueueWorkResult($workId,$display,$result) {
$this->results[$workId]->completed(microtime(true));
if(!is_null($result)) {
if($result->result("success")) {
$this->results[$workId]->isError(false);
$this->results[$workId]->result($result->result("results"));
$this->visualizeQueue("complete",$result->getWorkId(),$display,$result->result("results"));
} else {
$this->results[$workId]->isError(true);
$this->results[$workId]->error($result->result("error"));
$this->visualizeQueue("error",$result->getWorkId(),$display,$result->result("error"));
}
}
}
private function visualizeQueue($action,$workId,$display,$result=null) {
if(is_null($this->displayLen)) {
$this->displayLen = stdOut::getCols(90);
}
if($this->displayLen<20) {
$this->displayLen=20;
}
$prefix = $suffix = "";
if($action == "start") {
$prefix = "> --- started :";
} elseif($action == "error") {
$prefix = "> !!! failure :";
} elseif($action == "complete") {
$prefix = "> *** complete :";
if(!is_null($result)) {
$suffix = json_encode($result);
if(strlen($suffix) >= $this->displayLen) {
$suffix=substr($suffix,0,$this->displayLen-4)." ...";
}
}
}
if($this->visualize) {
dhGlobal::outLine($prefix,$workId,$display,$suffix);
}
}
private function getAsyncBoostrapCallable() {
return [
"callable"=>["\\boru\\dhdb\\async\\AsyncActions","init"],
"args"=>[$this->getDb()->getConfig()]
];
}
public function db($db=null) {
return is_null($db) ? $this->getDb() : $this->setDb($db);
}
public function threads($threads=null) {
return is_null($threads) ? $this->getThreads() : $this->setThreads($threads);
}
public function visualize($visualize=null) {
return is_null($visualize) ? $this->getVisualize() : $this->setVisualize($visualize);
}
public function bootstrap($bootstrap=null) {
return is_null($bootstrap) ? $this->getBootstrap() : $this->setBootstrap($bootstrap);
}
public function extended($extended=null) {
return is_null($extended) ? $this->getExtended() : $this->setExtended($extended);
}
public function expected($expected=null) {
return is_null($expected) ? $this->getExpected() : $this->setExpected($expected);
}
public function results($results=null) {
return $this->results;
}
public function promise() {
return $this->queueDeferred->promise();
}
/**
* Get the value of db
* @return null|\boru\dhdb\dhDB
*/
public function getDb() {
if(is_null($this->db)) {
$this->db = dhGlobal::db();
}
return $this->db;
}
/**
* Set the value of db
* @param \boru\dhdb\dhDB $db
* @return self
*/
public function setDb($db) {
$this->db = $db;
return $this;
}
/**
* Get the value of threads
* @return mixed
*/
public function getThreads() {
return $this->threads;
}
/**
* Set the value of threads
* @param mixed $threads
* @return self
*/
public function setThreads($threads) {
$this->threads = $threads;
return $this;
}
/**
* Get the value of visualize
* @return mixed
*/
public function getVisualize() {
return $this->visualize;
}
/**
* Set the value of visualize
* @param mixed $visualize
* @return self
*/
public function setVisualize($visualize) {
$this->visualize = $visualize;
return $this;
}
/**
* Get the value of extended
* @return mixed
*/
public function getExtended() {
return $this->extended;
}
/**
* Set the value of extended
* @param mixed $extended
* @return self
*/
public function setExtended($extended) {
$this->extended = $extended;
if(!is_null($this->queue)) {
$this->queue->enableExtendedBar($this->extended);
}
return $this;
}
/**
* Get the value of bootstrap
* @return mixed
*/
public function getBootstrap() {
return $this->bootstrap;
}
/**
* Set the value of bootstrap
* @param mixed $bootstrap
* @return self
*/
public function setBootstrap($bootstrap) {
$this->bootstrap = $bootstrap;
return $this;
}
/**
* Get the value of expected
* @return mixed
*/
public function getExpected() {
return $this->expected;
}
/**
* Set the value of expected
* @param mixed $expected
* @return self
*/
public function setExpected($expected) {
$this->expected = $expected;
return $this;
}
} src/async/QueryQueueResult.php 0000644 00000014604 14476160726 0012514 0 ustar 00 sql($sql);
}
if(!is_null($params)) {
$this->params($params);
}
if(!is_null($workId)) {
$this->workId($workId);
}
}
public function started($started=null) {
return is_null($started) ? $this->getStarted() : $this->setStarted($started);
}
public function completed($completed=null) {
return is_null($completed) ? $this->getCompleted() : $this->setCompleted($completed);
}
public function execTime($execTime=null) {
return is_null($execTime) ? $this->getExecTime() : $this->setExecTime($execTime);
}
public function sql($sql=null) {
return is_null($sql) ? $this->getSql() : $this->setSql($sql);
}
public function params($params=null) {
return is_null($params) ? $this->getParams() : $this->setParams($params);
}
public function result($result=null) {
return is_null($result) ? $this->getResult() : $this->setResult($result);
}
public function workId($workId=null) {
return is_null($workId) ? $this->getWorkId() : $this->setWorkId($workId);
}
public function isError($isError=null) {
return is_null($isError) ? $this->getIsError() : $this->setIsError($isError);
}
public function error($error=null) {
return is_null($error) ? $this->getError() : $this->setError($error);
}
/**
* Get the value of started
* @return mixed
*/
public function getStarted() {
return $this->started;
}
/**
* Set the value of started
* @param mixed $started
* @return self
*/
public function setStarted($started) {
$this->started = $started;
return $this;
}
/**
* Get the value of completed
* @return mixed
*/
public function getCompleted() {
return $this->completed;
}
/**
* Set the value of completed
* @param mixed $completed
* @return self
*/
public function setCompleted($completed) {
$this->completed = $completed;
if(!is_null($this->started)) {
$this->execTime($this->completed - $this->started);
}
return $this;
}
/**
* Get the value of sql
* @return mixed
*/
public function getSql() {
return $this->sql;
}
/**
* Set the value of sql
* @param mixed $sql
* @return self
*/
public function setSql($sql) {
$this->sql = $sql;
return $this;
}
/**
* Get the value of params
* @return mixed
*/
public function getParams() {
return $this->params;
}
/**
* Set the value of params
* @param mixed $params
* @return self
*/
public function setParams($params) {
$this->params = $params;
return $this;
}
/**
* Get the value of result
* @return mixed
*/
public function getResult() {
return $this->result;
}
/**
* Set the value of result
* @param mixed $result
* @return self
*/
public function setResult($result) {
$this->result = $result;
return $this;
}
/**
* Get the value of workId
* @return mixed
*/
public function getWorkId() {
return $this->workId;
}
/**
* Set the value of workId
* @param mixed $workId
* @return self
*/
public function setWorkId($workId) {
$this->workId = $workId;
return $this;
}
/**
* Get the value of isError
* @return bool
*/
public function getIsError() {
return $this->isError;
}
/**
* Set the value of isError
* @param bool $isError
* @return self
*/
public function setIsError($isError) {
$this->isError = $isError;
return $this;
}
/**
* Get the value of error
* @return mixed
*/
public function getError() {
return $this->error;
}
/**
* Set the value of error
* @param mixed $error
* @return self
*/
public function setError($error) {
$this->error = $error;
return $this;
}
/**
* Get the value of execTime
* @return mixed
*/
public function getExecTime() {
return $this->execTime;
}
/**
* Set the value of execTime
* @param mixed $execTime
* @return self
*/
public function setExecTime($execTime) {
$this->execTime = $execTime;
return $this;
}
public function asArray() {
return [
"started"=>$this->started(),
"completed"=>$this->completed(),
"execTime"=>$this->execTime(),
"workId"=>$this->workId(),
"isError"=>$this->isError(),
"sql"=>$this->sql(),
"params"=>$this->params(),
"result"=>$this->result(),
"error"=>$this->error(),
];
}
public function __toString() {
return json_encode($this);
}
public function jsonSerialize($array=null) {
return $this->asArray();
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetExists($offset) {
return property_exists($this,$offset);
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetGet($offset) {
return property_exists($this,$offset) ? $this->$offset : false;
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetSet($offset , $value) {
if(property_exists($this,$offset)) {
$this->$offset($value);
}
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetUnset($offset) {
$this->offsetSet($offset,null);
}
} src/dhDB.php 0000644 00000026024 14476160726 0006666 0 ustar 00 setDriver( dhGlobal::getVal($options,"driver", "Mysql"));
$this->setConfig( dhGlobal::getVal($options,"config", false));
$this->initDriver(true);
}
public function __destruct() {
//echo "destruct\n";
}
public function connected() {
return $this->init;
}
protected function initDriver($force=false) {
$finishedDrivers = ["mysql"];
if($force || is_null($this->driver)) {
$this->init = false;
if(!is_null($this->driverClass) && in_array(strtolower($this->driverClass),$finishedDrivers)
&& !is_null($this->config) && $this->config !== false)
{
if(strtolower($this->driverClass) == "mysql") {
$this->driver = new \boru\dhdb\drivers\Mysql($this->config);
$this->init = $this->driver->init();
}
}
}
}
public function driver($driver=null) {
if(!is_null($driver)) {
return $this->setDriver($driver);
}
return $this->getDriver();
}
public function getDumpCommand($db=null,$table=null) {
$cmd = "mysqldump";
$cmd.=" --host=".$this->config["dbhost"];
$cmd.=" --user=".$this->config["dbuser"];
$cmd.=" --password=".$this->config["dbpass"];
$cmd.=" ";
if(!is_null($db)) {
$cmd.=$db." ";
if(!is_null($table)) {
$cmd.="'".$table."' ";
}
}
return $cmd;
}
public function getStats() {
return $this->driver()->getResults();
}
/**
* (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
*
* Returns the ID of the last inserted row or sequence value
* @return string|false
*/
public function lastInsertId($name=null) {
return $this->driver()->lastInsertId($name=null);
}
public function getError() {
return $this->driver()->getError();
}
/**
* Returns a new Query object for ORM style operations
*
* @return Query
*/
public function makeQuery() {
return new Query();
}
/**
* Returns the SQL for a query object. If Interpolate is true, returns the interpolated query (default, true)
*
* @param Query $query the query object to parse
* @param boolean $interpolate wether or not to interpolate the returned sql
* @return string
*/
public function fromQuery(Query $query,$interpolate=true) {
$sql = $this->driver->fromQuery($query);
if($interpolate) {
return $this->driver->interpolateQuery($sql,$query->values);
}
return $sql;
}
/**
* Generate a Schema for a table. Optionally provide an existing Schema for comparison
*
* @param string $table The tablename to parse
* @param null|Schema $schema optional schema to compare
* @return \boru\dhdb\Schema
*/
public function getTable($table,$schema=null) {
return $this->driver->table($table,$schema);
}
/**
* Wrapper for ResultInterface->next() so no need to check if result is proper or not before calling next()
*
* @param StatementInterface|null $handler
* @return bool|ResultInterface
*/
public function next($handler=null,$mode=\PDO::FETCH_ASSOC,$cursorOrientation = \PDO::FETCH_ORI_NEXT,$cursorOffset = 0) {
if(is_object($handler)) {
return $handler->next($mode,$cursorOrientation,$cursorOffset);
}
return false;
}
/**
* Wrapper for ResultInterface->next() so no need to check if result is proper or not before calling next()
*
* @param StatementInterface|null $handler
* @return bool|ResultInterface
*/
public function nextRow($handler=null,$assoc=true,$object=true) {
if(is_object($handler)) {
return $handler->nextRow($assoc,$object);
}
return false;
}
/**
* Run a SQL query (or Query Object)
*
* @param string|Query $query sql query to run
* @param null|array $params params to bind to sql query
* @param null|array $options additional optns (debug,exec,etc)
* @return \boru\dhdb\interfaces\StatementInterface
*/
public function query($query,$params=[],$options=[]) {
return $this->run($query,$params,$options);
}
/**
* Run a SQL query (or Query Object)
*
* @param string|Query $query sql query to run
* @param null|array $params params to bind to sql query
* @param null|array $options additional optns (debug,exec,logErrors,etc)
* @return \boru\dhdb\interfaces\StatementInterface
*/
public function run($query,$params=[],$options=[]) {
$debug = dhGlobal::getVal($options,"debug",false);
$exec = dhGlobal::getVal($options,"exec",true);
$logErrors = dhGlobal::getVal($options,"logErrors",true);
$this->driver->setLogErrors($logErrors);
if(is_null($this->driver) || !$this->init) {
return new Result();
}
if(is_object($query)) {
$info = $this->getQueryFromObject($query,$params);
$sql = $info["query"];
$params = $info["params"];
} else {
$sql = $query;
}
if(!$exec) {
if($debug || self::$globalDebug) {
//dhGlobal::debug("query debug".PHP_EOL."Query: ".$sql.PHP_EOL." ");
static::debugQueryPrint($sql);
}
return $sql;
} else {
$return = $this->driver->run($sql,$params);
if($debug || self::$globalDebug) {
$stats = $this->driver->getResults();
//dhGlobal::debug("query debug".PHP_EOL."Query: ".$stats["interpolated"].PHP_EOL."Exec: ".$stats["execTime"]);
static::debugQueryPrint($stats["interpolated"],$stats["execTime"]);
}
return $return;
}
}
public function runCallback($query,$params=[],$options=[],callable $callback) {
$res = $this->run($query,$params,$options);
while($row = $this->nextRow($res)) {
$callback($row);
unset($row);
}
}
public function getQueryFromObject($queryObject,$params=[]) {
$sql = $this->fromQuery($queryObject);
$params = null;
if(empty($params)) {
$params = $queryObject->values;
} else {
if(!empty($queryObject->values)) {
$params = array_merge($queryObject->values,$params);
}
}
return ["query"=>$sql,"params"=>$params];
}
/**
* Get the value of driver
*
* @return \boru\dhdb\interfaces\DriverInterface
*/
public function getDriver()
{
$this->initDriver();
return $this->driver;
}
/**
* Set the value of driver
*
* @param string $driver the driver class name
* @return self
*/
public function setDriver($driver)
{
if(is_object($driver)) {
$this->driver = $driver;
} elseif(is_string($driver)) {
$this->driverClass = $driver;
$this->initDriver(true);
}
return $this;
}
/**
* Get the value of config
*
* @return array
*/
public function getConfig()
{
return $this->config;
}
/**
* Set the value of config
*
* @param array $config the config array
* @return self
*/
public function setConfig($config)
{
$this->config = $config;
return $this;
}
/**
* Generate an array of [?,?,?,...]
*
* @param array $array the array to count/replace with '?'
* @param string $glue optional glue to use on the returned string (default ',');
* @return string
*/
public function generateQs($array,$glue=",") {
$qarr = array_fill(0,count($array),"?");
return implode($glue,$qarr);
}
public static function fromVtigerConfig($configIncPhpFile,$options=[]) {
$configFile = new File(["path"=>$configIncPhpFile]);
$lineFilter = function($line) {
if(preg_match('/^\$dbconfig/', $line)) {
return $line;
}
};
$dbconfig = [];
$data = $configFile->content(["lineFilter"=>$lineFilter]);
try {
eval($data);
} catch (\Exception $e) {
return false;
}
$options['config'] = [
'dbtype'=>'mysql',
"dbhost"=>$dbconfig['db_server'],
"dbport"=>dhGlobal::trimString(":",$dbconfig['db_port'],dhGlobal::TRIM_START),
"dbuser"=>$dbconfig['db_username'],
"dbpass"=>$dbconfig['db_password'],
"dbname"=>$dbconfig['db_name'],
];
return new self($options);
}
public static function parse($queryString,$opts=[]) {
$parser = new Parser($queryString);
$options = [];
if(isset($opts["params"])) {
$options["constantAsQuestionMark"]=true;
}
if(isset($opts["part"])) {
$options["part"] = $opts["part"];
}
if(isset($opts["array"])) {
return $parser->toArray($options);
}
return $parser->toSql($options);
}
public static function setDebug($debug) {
self::$globalDebug = $debug;
}
public static function setDebugFormat($format,$useEcho=false) {
self::$globalDebugFormat = $format;
self::$globalDebugEcho = $useEcho;
}
public static function debugQueryPrint($queryString,$execTime=null) {
//if web, use
, else use phpeol
if(php_sapi_name() == "cli") {
$nl = PHP_EOL;
} else {
$nl = "
".PHP_EOL;
}
$msg = str_replace(["%query%","%time%","%nl%"],[$queryString,$execTime,$nl],self::$globalDebugFormat);
if(self::$globalDebugEcho) {
echo $msg;
} else {
dhGlobal::debug($msg);
}
}
} src/drivers/Mysql.php 0000644 00000021157 14476160726 0010652 0 ustar 00 "",
"interpolated"=>"",
"execTime"=>0,
"error"=>false
];
protected $qStart=0;
protected $qEnd=0;
protected $execTime=0;
protected $interpolated;
protected $sql;
protected $params;
protected $failed = false;
/**
* @var \PDO
*/
private $PDO;
public function __construct($config) {
$this->setConfig($config);
}
public function init() {
if(!$this->init && !is_null($this->config) && $this->config !== false) {
try {
if(!isset($this->config["dbtype"])) {
$this->config["dbtype"] = "mysql";
}
$dsn=$this->config["dbtype"].':host='.$this->config["dbhost"].";port=".$this->config["dbport"].";dbname=".$this->config["dbname"];
$user=$this->config["dbuser"];
$passwd=$this->config["dbpass"];
$options = array(
\PDO::ATTR_PERSISTENT => true,
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION
);
$this->PDO = new \PDO($dsn, $user, $passwd, $options);
$this->init = true;
return true;
} catch (\PDOException $e) {
return false;
}
}
return $this->init;
}
public function newQuery() {
return new Query();
}
public function newParser() {
return new Parser();
}
public function fromQuery($query) {
$parser = new Parser($query);
$parser->parse();
$sql = $parser->getQueryString();
return $sql;
}
/**
*
* @param mixed $sql
* @param mixed $arr
* @param mixed $arr2
* @param mixed $unused1
* @param mixed $unused2
* @return false|Statement
*/
public function run($sql,$arr=null,$arr2=null,$unused1=null,$unused2=null) {
$this->init();
$this->failed = false;
if($this->is_assoc($arr)) {
$keys = "";
$values = array();
foreach($arr as $k=>$v) {
$keys.=",`$k`=?";
$values[]=$v;
}
$keys = trim($keys,",");
$sql = str_replace("::replace::",$keys,$sql);
$sth = new Statement($this->PDO->prepare($sql));
foreach($values as $k=>$v) {
$this->bind($sth,$k+1,$v);
$last = $k+1;
}
if(is_array($arr2)) {
foreach($arr2 as $k=>$v) {
$last++;
$this->bind($sth,$last,$v);
}
}
} else {
$sth = new Statement($this->PDO->prepare($sql));
if(is_array($arr)) {
foreach($arr as $k=>$v) {
$this->bind($sth,$k+1,$v);
}
} elseif($arr!=null && $arr!="") {
$this->bind($sth,1,$arr);
}
}
try {
$this->set("queryStart",microtime(true));
$this->set("query",$sql);
$this->set("interpolated",$this->interpolateQuery($sql,$arr));
$sth->execute();
$this->set("queryEnd",microtime(true));
$this->set("execTime",$this->get("queryEnd",0) - $this->get("queryStart",0));
$this->set("error",false);
$this->set("complete",true);
} catch (\PDOException $e) {
$this->setError($sql,$arr,$this->interpolateQuery($sql,$arr),$e);
return false;
} catch (\Exception $e) {
$this->setError($sql,$arr,$this->interpolateQuery($sql,$arr),$e);
return false;
}
return $sth;
}
public function table($tableName,$schema=null) {
$meta = [];
if(is_null($schema)) {
$schema = new Schema($tableName);
}
$sth = $this->run("SHOW TABLE STATUS LIKE ?",[$tableName]);
while($row = $sth->next()) {
$meta["engine"] = $row->get("Engine");
$meta["collate"] = $row->get("Collation");
if(!empty($row->get("Auto_increment"))) {
$meta["auto_increment"] = $row->get("Auto_increment");
}
if(!empty($row->get("Comment"))) {
$meta["comment"]= $row->get("Comment");
}
}
foreach($meta as $k=>$v) {
$schema->meta($k,$v);
}
$sth = $this->run("SHOW FULL FIELDS FROM `".$tableName."`");
while($row = $sth->next()) {
$extra = ["null"=>true];
if(strtolower($row->get("Null")) == "no") {
$extra["null"] = false;
}
if(!empty($row->get("Collation"))) {
$extra["collate"] = $row->get("Collation");
}
if(!empty($row->get("Default"))) {
$extra["default"] = $row->get("Default");
}
if(!empty($row->get("Extra")) && $row->get("Extra") == "auto_increment") {
$extra["auto_increment"] = true;
}
$schema->add($row->get("Field"),$row->get("Type"),$extra);
}
$sth = $this->run("SHOW INDEX FROM `".$tableName."`");
$indexArr = [];
while($row = $sth->next()) {
if(!isset($indexArr[$row->get("Key_name")])) {
if($row->get("Key_name") == "PRIMARY" && $row->get("Non_unique")<=0) {
$type = "primary";
} elseif($row->get("Index_type") == "FULLTEXT") {
$type="fulltext";
} elseif($row->get("Non_unique") <= 0) {
$type = "unique";
} else {
$type = "key";
}
$indexArr[$row->get("Key_name")] = [
"name"=>$row->get("Key_name"),
"type"=>$type,
"extra"=>[]
];
}
$indexArr[$row->get("Key_name")]["extra"][] = $row->get("Column_name").($row->get("Cardinality") == "D" ? " DESC" : "");
}
foreach($indexArr as $name=>$index) {
$schema->addIndex($name,$index["extra"],$index["type"]);
}
return $schema;
}
public function setError($query,$params,$interpolated,$exception) {
$this->lastError = new Error($exception->getMessage(),$query,$params,$interpolated,$exception->getTraceAsString());
if($this->logErrors) {
$this->lastError->log();
}
}
public function getError() {
return $this->lastError;
}
private function is_assoc($array) {
if(!is_array($array)) return false;
return (bool)count(array_filter(array_keys($array), 'is_string'));
}
private function bind(&$sth,$pos,$value,$type=null) {
if( is_null($type) ) {
switch( true ) {
case is_int($value):
$type = \PDO::PARAM_INT;
break;
case is_bool($value):
$type = \PDO::PARAM_BOOL;
break;
case is_null($value):
$type = \PDO::PARAM_NULL;
break;
default:
$type = \PDO::PARAM_STR;
}
}
$sth->bindValue($pos,$value,$type);
}
public function interpolateQuery($query="", $params=[]) {
if(empty($params)) {
return $query;
}
$keys = array();
$values = $params;
# build a regular expression for each parameter
foreach ($params as $key => $value) {
if (is_string($key)) {
$keys[] = '/:'.$key.'/';
} else {
$keys[] = '/[?]/';
}
if (is_array($value))
$values[$key] = implode(',', $value);
if (is_null($value))
$values[$key] = 'NULL';
}
// Walk the array to see if we can add single-quotes to strings
array_walk($values, function (&$v) {
if (!is_numeric($v) && $v!="NULL") {
$v = "\"".$v."\"";
}
});
$query = preg_replace($keys, $values, $query, 1, $count);
return $query;
}
public function getResults($item=null) {
if(is_null($item)) {
return $this->get();
}
return $this->get($item,null);
}
public function generateQuestions($array) {
$string = "";
foreach($array as $v) {
$string.=",?";
}
return trim($string,",");
}
/**
* Get the value of config
*/
public function getConfig()
{
return $this->config;
}
/**
* Set the value of config
*
* @return self
*/
public function setConfig($config)
{
$this->config = $config;
$this->init();
return $this;
}
/**
* Get the value of logErrors
*
* @return mixed
*/
public function getLogErrors() {
return $this->logErrors;
}
/**
* Set the value of logErrors
*
* @param mixed $logErrors
* @return self
*/
public function setLogErrors($logErrors) {
$this->logErrors = $logErrors;
return $this;
}
/**
* (PHP 5 >= 5.1.0, PHP 7, PECL pdo >= 0.1.0)
*
* Returns the ID of the last inserted row or sequence value
* @return string|false
*/
public function lastInsertId($name=null) {
return $this->PDO->lastInsertId($name=null);
}
public function __call($method,$args) {
return call_user_func_array( [$this->PDO,$method], $args);
}
} src/drivers/mysql/Parser.php 0000644 00000041225 14476160726 0012144 0 ustar 00 setQuery($query);
}
}
public function parse($query=null) {
if(is_null($query)) {
$query = $this->getQuery();
}
//raw query string
if(!is_null($query->rawQueryString)) {
return $this->setQueryString($query->rawQueryString);
}
if(isset($query->type) && !is_null($query->type)) {
//select query
if($query->type == "select") {
return $this->parseSelect($query);
}
//update query
if($query->type == "update") {
return $this->parseUpdate($query);
}
//insert query
if($query->type == "insert") {
return $this->parseInsert($query);
}
//delete query
//union query
//create table
if($query->type == "create") {
return $this->parseCreateTable($query);
}
//alter table
if($query->type == "alter") {
return $this->parseAlterTable($query);
}
}
}
protected function parseSelect($query) {
$sql = "";
$sql.= $this->parseColumnString($query," ");
$sql.= $this->parseTableString($query," FROM ");
$sql.= $this->parseConditionString($query," WHERE ");
$sql.= $this->parseGroupByString($query);
$sql.= $this->parseOrderByString($query);
$sql.= $this->parseLimitString($query);
if(!empty($sql)) {
return $this->setQueryString("SELECT".$sql);
}
return false;
}
protected function parseUpdate($query) {
$sql = "";
$sql.= $this->parseTableString($query,"UPDATE ");
$sql.= $this->parseColumnString($query," SET ",false);
$sql.= $this->parseConditionString($query," WHERE ");
$sql.= $this->parseGroupByString($query);
$sql.= $this->parseOrderByString($query);
$sql.= $this->parseLimitString($query);
if(!empty($sql)) {
return $this->setQueryString($sql);
}
return false;
}
protected function parseInsert($query) {
$sql = "";
$sql.= $this->parseTableString($query,"INSERT INTO ");
$sql.= " (";
$sql.= $this->parseColumnString($query);
$sql.= " ) ";
$sql.= $this->parseInsertValues($query,"VALUES ");
if(!empty($sql)) {
return $this->setQueryString($sql);
}
return false;
}
protected function parseCreateTable($query) {
$sql = "";
if($query->ifNotExists) {
$sql.= $this->parseTableString($query,"CREATE TABLE IF NOT EXISTS ");
} else {
$sql.= $this->parseTableString($query,"CREATE TABLE ");
}
$sql.= " (";
$sql.= $this->parseSchemaColumnsCreate($query);
$sql.= ") ";
$sql.= $this->parseTableMeta($query," ");
if(!empty($sql)) {
return $this->setQueryString($sql);
}
return false;
}
protected function parseAlterTable($query) {
$tableAlter = $this->parseTableString($query,"ALTER TABLE ");
$columnAlter = $this->parseSchemaColumnsAlter($query);
$metaAlter = $this->parseTableMeta($query,",");
$sql = $tableAlter." ";
$sqlInner = [];
if(!empty($columnAlter)) {
$sqlInner[]=$columnAlter;
}
if(!empty($metaAlter)) {
$sqlInner[]=$metaAlter;
}
if(!empty($sqlInner)) {
return $this->setQueryString($sql.implode(", ",$sqlInner));
}
return false;
}
protected function parseGroupByString($query) {
if(!is_null($query->groupBy)) {
if(is_array($query->groupBy)) {
return " GROUP BY ".implode(",",$query->groupBy);
} else {
return " GROUP BY ".$query->groupBy;
}
}
return "";
}
protected function parseOrderByString($query) {
if(!is_null($query->orderBy)) {
if(is_array($query->orderBy)) {
return " ORDER BY ".implode(",",$query->orderBy);
} else {
return " ORDER BY ".$query->orderBy;
}
}
return "";
}
protected function parseLimitString($query) {
if(!is_null($query->limit)) {
if(is_array($query->limit)) {
return " LIMIT ".implode(",",$query->limit);
} else {
return " LIMIT ".$query->limit;
}
}
return "";
}
protected function parseColumnString($query,$prefix="",$sanitize=true) {
if(empty($query->columns)) {
return "";
}
if($sanitize) {
$columns = array_map([$this,'sanitizeColumnName'],$query->columns);
} else {
$columns = $query->columns;
}
return $prefix.implode(",",$columns);
}
protected function parseConditionString($query,$prefix="") {
if(empty($query->conditions)) {
return "";
}
$conds = [];
foreach($query->conditions as $cond) {
$conds[] = "($cond)";
}
return $prefix.implode(" AND ",$conds);
}
protected function parseTableString($query,$prefix="") {
if(empty($query->tables)) {
return "";
}
$tables = $query->tables;
$string = $this->sanitizeColumnName($tables[0]["name"]);
array_shift($tables);
if(!empty($tables)) {
$tableStrings = [];
foreach($tables as $table) {
$tstring = "";
if(!is_null($table["type"])) {
$tstring.=" ".$table["type"]." ";
} else {
$tstring.=",";
}
$tstring .= $this->sanitizeColumnName($table["name"]);
if(!is_null($table["on"])) {
$tstring.=" ON ".$table["on"];
}
$tableStrings[] = $tstring;
}
$string.=implode(" ",$tableStrings);
}
return $prefix.$string;
}
public function parseInsertValues($query,$prefix = "") {
$valueGroups = [];
if(!empty($query->values)) {
if(is_array($query->values[0])) {
//TODO
} else {
$valueGroups[] = "(".$this->generateQs($query->values).")";
}
}
return $prefix.implode(",",$valueGroups);
}
public function parseSchemaColumnsCreate($query,$prefix = "") {
if(empty($query->schemaColumns)) {
return "";
}
$coldefs = [];
foreach($query->schemaColumns as $def) {
$action = $def["action"];
$col = $def["column"];
$type = $def["type"];
$extra = $def["extra"];
if($action == "add") {
$coldefs[] = $this->sanitizeColumnName($col)." $type".(!empty($extra) ? " ".$this->parseColExtra($extra,$type) : "");
} elseif($action == "addIndex") {
$indexCols = [];
if(is_array($extra)) {
foreach($extra as $v) {
$indexCols[] = $this->sanitizeColumnName($v);
}
} else {
$indexCols[] = $this->sanitizeColumnName($extra);
}
if(empty($type) || $type == "key") {
$coldefs[] = "KEY ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
} elseif($type == "primary") {
$coldefs[] = "PRIMARY KEY (".implode(",",$indexCols).")";
} elseif($type == "fulltext") {
$coldefs[] = "FULLTEXT KEY ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
} elseif($type == "unique") {
$coldefs[] = "UNIQUE KEY ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
}
}
}
return implode(",",$coldefs);
}
public function parseSchemaColumnsAlter($query,$prefix = "") {
if(empty($query->schemaColumns)) {
return "";
}
$out = [];
foreach($query->schemaColumns as $def) {
//$this->schemaColumns[] = ["action"=>$action,"column"=>$col,"type"=>$type, "extra"=>$extra];
$action = $def["action"];
$col = $def["column"];
$type = $def["type"];
$extra = $def["extra"];
if($action == "add") {
$out[] = "ADD COLUMN ".$this->sanitizeColumnName($col)." $type".(!empty($extra) ? " ".$this->parseColExtra($extra,$type) : "");
} elseif($action == "drop") {
$out[] = "DROP COLUMN ".$this->sanitizeColumnName($col);
} elseif($action == "change") {
$out[] = "CHANGE COLUMN ".$this->sanitizeColumnName($col[0])." ".$this->sanitizeColumnName($col[1])." $type".(!empty($extra) ? " ".$this->parseColExtra($extra,$type) : "");
} elseif($action == "dropIndex") {
$out[] = "DROP INDEX ".$this->sanitizeColumnName($col);
} elseif($action == "addIndex") {
$indexCols = [];
if(is_array($extra)) {
foreach($extra as $v) {
$indexCols[] = $this->sanitizeColumnName($v);
}
} else {
$indexCols[] = $this->sanitizeColumnName($extra);
}
if(empty($type) || $type == "key") {
$out[] = "ADD KEY ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
} elseif($type == "primary") {
$out[] = "ADD PRIMARY KEY (".implode(",",$indexCols).")";
} elseif($type == "fulltext") {
$out[] = "ADD FULLTEXT INDEX ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
} elseif($type == "unique") {
$out[] = "ADD UNIQUE INDEX ".$this->sanitizeColumnName($col)." (".implode(",",$indexCols).")";
}
}
}
return $prefix.implode(",",$out);
}
public function parseTableMeta($query,$implode=",") {
//tableMeta
if(empty($query->tableMeta)) {
return "";
}
$out = [];
foreach($query->tableMeta as $def) {
$key = $def["key"];
$value = $def["value"];
if($key != "auto_increment") {
if(is_null($value) || empty($value)) {
$out[] = $key;
} else {
$noEmpty = ["comment","auto_increment"];
if($key == "comment" && !empty($value)) {
$out[] = $key.'="'.$value.'"';
} else {
$out[] = $key."=".$value;
}
}
}
}
return implode($implode,$out);
}
protected function parseColExtra($extra,$type,$glue=" ") {
if(!is_array($extra)) {
if(empty($extra)) {
return "";
} else {
return $extra;
}
}
$null = dhGlobal::getVal($extra,"null",false);
$collate = dhGlobal::getVal($extra,"collate",false);
$charset = dhGlobal::getVal($extra,"charset",false);
$default = dhGlobal::getVal($extra,"default",false);
$auto_incr = dhGlobal::getVal($extra,"auto_increment",false);
$after = dhGlobal::getVal($extra,"after",false);
if(!$charset && $collate !== false) {
list($charset,$unused) = explode("_",$collate,2);
}
$parts = [];
if($charset !== false) {
$parts[] ="CHARACTER SET ".$charset;
}
if($collate !== false) {
$parts[] ="COLLATE ".$collate;
}
if($null) {
if($default === false) {
$parts[] = "DEFAULT NULL";
} else {
if($type == "timestamp" && $default == "CURRENT_TIMESTAMP") {
$parts[] = 'DEFAULT CURRENT_TIMESTAMP';
} else {
$parts[] = 'DEFAULT "'.$default.'"';
}
}
} else {
$parts[] = "NOT NULL";
if($default !== false) {
if($type == "timestamp" && $default == "CURRENT_TIMESTAMP") {
$parts[] = 'DEFAULT CURRENT_TIMESTAMP';
} else {
$parts[] = 'DEFAULT "'.$default.'"';
}
}
}
if($auto_incr !== false) {
$parts[] = "AUTO_INCREMENT";
}
if($after !== false) {
$parts[] = "AFTER ".$this->sanitizeColumnName($after);
}
return implode($glue,$parts);
}
public function sanitizeColumnName($colString) {
if(!is_array($colString) && $colString == "*") {
return $colString;
}
if(!is_array($colString)) {
//$columns = explode(",",$colString);
$columns = [$colString];
} else {
$columns = $colString;
}
return $this->sanitize_arrayOfColumns($columns);
}
public function sanitize_arrayOfColumns($columns) {
foreach($columns as $k=>$colString) {
if(strpos($colString,"(") !== false && strpos($colString,")") !== false) {
//do nothing.. it's a function or subquery, and i'm not about to go down that rabbit hole.
echo "skipping $colString\n";
} elseif(strpos($colString," ") !== false) {
$columns[$k] = $this->sanitize_colWithAlias($colString);
} elseif(strpos($colString,".") !== false) {
$columns[$k] = $this->sanitize_colWithSub($colString);
} else {
$columns[$k] = $this->sanitize_colName($colString);
}
}
return implode(",",$columns);
}
public function sanitize_colWithAlias($colString) {
$parts = preg_split('/\sas\s|\s/', strtolower($colString));
foreach($parts as $k=>$part) {
if(strpos($parts[$k],".") !== false) {
$parts[$k] = $this->sanitize_colWithSub($part);
} else {
$parts[$k] = $this->sanitize_colName($part);
}
}
return implode(" ",$parts);
}
public function sanitize_colWithSub($colString) {
$parts = explode(".",strtolower($colString));
foreach($parts as $k=>$part) {
$parts[$k] = $this->sanitize_colName($part);
}
return implode(".",$parts);
}
public function sanitize_colName($col) {
if($col == "*") {
return $col;
}
return "`".preg_replace("/[^A-Za-z0-9\-_\.\(\)\*]/", '', $col)."`";
}
public function sanitize_quoteCol($field) {
if($field == "*") {
return $field;
}
return preg_replace("/[^\`A-Za-z0-9\-_\.\(\)\*\ ]/", '', $field);
}
/**
* Get the value of query
*/
public function getQuery()
{
return $this->query;
}
/**
* Set the value of query
*
* @return self
*/
public function setQuery($query)
{
$this->query = $query;
return $this;
}
/**
* Get the value of queryString
*/
public function getQueryString()
{
return $this->queryString;
}
/**
* Set the value of queryString
*
* @return self
*/
public function setQueryString($queryString)
{
$this->queryString = $queryString;
return $this;
}
/**
* Generate an array of [?,?,?,...]
*
* @param array $array the array to count/replace with '?'
* @param string $glue optional glue to use on the returned string (default ',');
* @return string
*/
public function generateQs($array,$glue=",") {
$qarr = array_fill(0,count($array),"?");
return implode($glue,$qarr);
}
} src/drivers/mysql/Row.php 0000644 00000003714 14476160726 0011460 0 ustar 00 setGetSetMainArray("fields");
if(is_array($fields) && !empty($fields)) {
$this->fields = $fields;
}
}
public function __set($field,$val) {
$this->set($field,$val);
}
public static function fromStatement($row) {
if(is_array($row)) {
return new self($row);
}
return false;
}
public function toArray() {
return $this->fields;
}
public function asArray() {
return $this->fields;
}
public function asString() {
return json_encode($this->fields);
}
public function asObject() {
return (object)$this->fields;
}
/**
* Inherits trait functions from GetSetArray
* ->get($key,$default=null)
* ->set($key,$val='',$append=false)
* ->exists($key=null)
*/
public function jsonSerialize($array=null) {
if(is_null($array)) {
$array = $this->fields;
}
return $array;
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetExists($offset) {
return $this->exists($offset);
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetGet($offset) {
return $this->get($offset);
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetSet($offset , $value) {
$this->set($offset,$value);
}
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetUnset($offset) {
$this->remove($this->$offset);
}
public function __toString() {
return json_encode($this->fields);
}
} src/drivers/mysql/Statement.php 0000644 00000004155 14476160726 0012655 0 ustar 00 stmt = $stmt;
if(!is_null($this->stmt) && $this->stmt !== false) {
$this->stmt->setFetchMode(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE,"\\boru\\dhdb\\drivers\\mysql\\Row");
} else {
$this->isFalse = true;
}
}
public function __destruct() {
$this->stmt = null;
}
public function nextRow($assoc=true,$object=true) {
if($this->isFalse) {
return false;
}
if(!is_null($this->stmt) && $this->stmt !== false) {
if($object) {
return $this->stmt->fetch($assoc ? \PDO::FETCH_ASSOC : \PDO::FETCH_NUM);
} else {
return $this->stmt->fetch($assoc ? \PDO::FETCH_ASSOC : \PDO::FETCH_NUM);
}
}
$this->stmt = null;
unset($this->stmt);
return false;
}
public function next($mode=\PDO::FETCH_ASSOC,$cursorOrientation = \PDO::FETCH_ORI_NEXT,$cursorOffset = 0) {
if($this->isFalse) {
return false;
}
if(!is_null($this->stmt) && $row = Row::fromStatement($this->stmt->fetch($mode,$cursorOrientation,$cursorOffset))) {
return $row;
}
$this->stmt = null;
unset($this->stmt);
return false;
}
public function all($object=true) {
if($this->isFalse) {
return false;
}
if($object) {
return $this->stmt->fetchAll(\PDO::FETCH_CLASS | \PDO::FETCH_PROPS_LATE,"\\boru\\dhdb\\drivers\\mysql\\Row");
} else {
return $this->stmt->fetchAll(\PDO::FETCH_ASSOC);
}
}
public function __call($method,$args) {
if($this->isFalse) {
return false;
}
return call_user_func_array( [$this->stmt,$method], $args);
}
} src/interfaces/DriverInterface.php 0000644 00000001604 14476160726 0013261 0 ustar 00 get($key,$default=null)
* ->set($key,$val='',$append=false)
* ->exists($key=null)
*/
public function jsonSerialize($array=null);
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetExists($offset);
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetGet($offset);
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetSet($offset , $value);
/**
* Ignore intelephense error, php 5.6 :(
*/
public function offsetUnset($offset);
public function __toString();
} src/interfaces/StatementInterface.php 0000644 00000000637 14476160726 0013777 0 ustar 00 wrapper = new SQLParserWrapper();
if(!empty($options)) {
$this->setOptions($options);
}
if(!is_null($query)) {
$this->setQuery($query);
$this->parse();
}
}
public function setQuery($query) {
$this->query = $query;
$this->parse();
return $this;
}
public function setOptions($options=[],$merge=true) {
if($merge) {
$this->options = array_merge($this->options,$options);
} else {
$this->options = $options;
}
return $this;
}
public function getExpressions($type=null) {
if(!is_null($type)) {
$type = strtoupper($type);
if(isset($this->expressions[$type])) {
return $this->expressions[$type];
}
}
return $this->expressions;
}
public function parse($sql=null,$options=[]) {
if(!is_null($sql)) {
$this->setQuery($sql);
}
if(!empty($options)) {
$this->setOptions($options);
}
$this->wrapper->parse($this->query, $this->options);
$parsed = $this->wrapper->get();
foreach($parsed as $key=>$value) {
$key = strtoupper($key);
$this->expressions[$key] = [];
foreach($value as $expr) {
$this->expressions[$key][] = Expression::fromArray($expr);
}
}
}
public function get($whatPart,$asSql=false) {
$whatPart = strtoupper($whatPart);
if(isset($this->expressions[$whatPart])) {
if($asSql) {
$sql = [];
foreach($this->expressions[$whatPart] as $expr) {
$sql[] = $expr->toSql();
}
return implode(" ",$sql);
} else {
return $this->expressions[$whatPart];
}
}
return false;
}
public function toArray($options=[]) {
$sqlArray = [];
$part = isset($options["part"]) ? $options["part"] : null;
if(is_null($part)) {
foreach($this->expressions as $key=>$value) {
$sqlArray[$key] = [];
foreach($value as $expr) {
$sqlArray[$key][] = $expr->toArray($options);
}
}
} else {
$part = strtoupper($part);
if(isset($this->expressions[$part])) {
foreach($this->expressions[$part] as $expr) {
$sqlArray[] = $expr->toArray($options);
}
}
}
return $sqlArray;
}
public function jsonSerialize() {
return $this->toArray();
}
public function __toString() {
return json_encode($this->toArray(),JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function toString($options=[]) {
$sqlArray = $this->toArray($options);
return json_encode($sqlArray,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function toSql($options=[]) {
$params = new Params();
$sqlArray = [];
$part = isset($options["part"]) ? $options["part"] : null;
if(is_null($part)) {
foreach($this->expressions as $key=>$value) {
$sqlArray[$key] = [];
foreach($value as $expr) {
if($expr instanceof Expression) {
$sqlArray[$key][] = $expr->toSql($options,$params);
} else {
$sqlArray[$key][] = $expr;
}
}
}
foreach($sqlArray as $key=>$value) {
$sqlArray[$key] = $this->keyToSql($key)." ".implode(" ",$value);
}
} else {
$part = strtoupper($part);
if(isset($this->expressions[$part])) {
foreach($this->expressions[$part] as $expr) {
if($expr instanceof Expression) {
$sqlArray[] = $expr->toSql($options,$params);
} else {
$sqlArray[] = $expr;
}
}
}
}
return ["sql"=>implode(" ",$sqlArray),"params"=>$params->get()];
}
private function keyToSql($key) {
$key = strtoupper($key);
if($key == "ORDER") {
return "ORDER BY";
}
return $key;
}
} src/parser/SQLParserWrapper.php 0000644 00000011657 14476160726 0012544 0 ustar 00 parser = new \PHPSQLParser\PHPSQLParser();
$this->creator = new \PHPSQLParser\PHPSQLCreator();
if(!empty($options)) {
$this->setOptions($options);
}
if(!is_null($query)) {
$this->setQuery($query);
$this->parse();
}
}
public function setQuery($query) {
$this->query = $query;
$this->parse();
return $this;
}
public function setOptions($options=[],$merge=true) {
if($merge) {
$this->options = array_merge($this->options,$options);
} else {
$this->options = $options;
}
return $this;
}
public function parse($sql=null,$options=[]) {
if(!is_null($sql)) {
$this->setQuery($sql);
}
if(!empty($options)) {
$this->setOptions($options);
}
$this->parser->parse($this->query, true);
$this->parsed = $this->parser->parsed;
return $this;
}
public function jsonSerialize() {
return $this->parsed;
}
public function __toString() {
return json_encode($this->parsed,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
}
public function get($key=null,$default=null) {
if(is_null($key)) {
return $this->parsed;
}
if(isset($this->parsed[$key])) {
return $this->parsed[$key];
}
return dhGlobal::getDot($this->parsed,$key,$default);
}
public function set($key,$value) {
dhGlobal::dotAssign($this->parsed,$key,$value);
return $this;
}
public function getQuery() {
return $this->query;
}
public function getSelect($asSql=false) {
$part = $this->get('SELECT',false);
if($asSql) {
return $this->toQuery(["SELECT"=>$part]);
}
return $part;
}
public function getFrom($asSql=false) {
$part = $this->get('FROM',false);
if($asSql) {
return $this->toQuery(["FROM"=>$part]);
}
return $part;
}
public function getWhere($asSql=false) {
$part = $this->get('WHERE',false);
if($asSql) {
return $this->toQuery(["WHERE"=>$part]);
}
return $part;
}
public function getGroupBy($asSql=false) {
$part = $this->get('GROUP',false);
if($asSql) {
return $this->toQuery(["GROUP"=>$part]);
}
return $part;
}
public function getOrderBy($asSql=false) {
$part = $this->get('ORDER',false);
if($asSql) {
return $this->toQuery(["ORDER"=>$part]);
}
return $part;
}
public function toQuery($partArray=null) {
if(is_null($partArray)) {
$partArray = $this->parsed;
}
$sql = "";
try {
$sql = $this->creator->create($partArray);
} catch (UnsupportedFeatureException $e) {
$partType = key($partArray);
try {
$sql = $this->partQuery($partType,$partArray);
} catch (\Exception $e) {
throw new \Exception("Unsupported: ".$e->getMessage());
}
}
return $sql;
}
public function partQuery($partType,$partArray) {
$partValue = $partArray[$partType];
$partType = strtolower($partType);
if($partType == "select") {
$builder = new \PHPSQLParser\builders\SelectStatementBuilder();
} elseif($partType == "from") {
$builder = new \PHPSQLParser\builders\FromBuilder();
} elseif($partType == "where") {
$builder = new \PHPSQLParser\builders\WhereBuilder();
} elseif($partType == "group") {
$builder = new \PHPSQLParser\builders\GroupByBuilder();
} elseif($partType == "order") {
$builder = new \PHPSQLParser\builders\OrderByBuilder();
} elseif($partType == "limit") {
$builder = new \PHPSQLParser\builders\LimitBuilder();
} elseif($partType == "having") {
$builder = new \PHPSQLParser\builders\HavingBuilder();
} elseif($partType == "union") {
$builder = new \PHPSQLParser\builders\UnionStatementBuilder();
} elseif($partType == "union all") {
$builder = new \PHPSQLParser\builders\UnionAllStatementBuilder();
} else {
throw new \Exception("Unknown part type: ".$partType);
}
return $builder->build($partValue);
}
} src/parser/expr/BracketExpression.php 0000644 00000001045 14476160726 0013766 0 ustar 00 $this->expressionName(),
"subTree"=>$this->subTree($options),
];
}
public function toSql($options=[],&$params=null) {
$subTreeSql = $this->subTreeSql($options,$params);
return "(" . implode(" ",$subTreeSql) . ")";
}
} src/parser/expr/ColumnExpression.php 0000644 00000003615 14476160726 0013655 0 ustar 00 get("no_quotes")) !== false && count($noQuotes["parts"]) > 1) {
return $noQuotes["parts"][0];
}
return false;
}
public function column() {
if(($noQuotes = $this->get("no_quotes")) !== false) {
if(count($noQuotes["parts"]) > 1) {
return $noQuotes["parts"][1];
} else {
return $noQuotes["parts"][0];
}
}
return $this->get("base_expr");
return false;
}
public function alias() {
$alias = $this->get("alias");
if(is_array($alias) && isset($alias["no_quotes"])) {
return $alias["no_quotes"]["parts"][0];
}
return $this->get("alias");
}
public function getArray($options=[]) {
$return["type"] = $this->expressionName();
if($this->table() !== false) {
$return["table"] = $this->table();
}
$return["column"] = $this->column();
if($this->alias() !== false) {
$return["alias"] = $this->alias();
}
if($this->subTree($options) !== false) {
$return["subTree"] = $this->subTree($options);
}
return $return;
}
public function toSql($options=[],&$params=null) {
$return = "";
if($this->table() !== false) {
$return .= "`".$this->table() . "`.";
}
if($this->column() == "*") {
$return .= "*";
return $return;
}
$return .= "`".$this->column()."`";
if($this->alias() !== false) {
$return .= " AS " . $this->alias();
}
return $return;
}
} src/parser/expr/ConstantExpression.php 0000644 00000001762 14476160726 0014212 0 ustar 00 get("base_expr");
}
public function getArray($options=[]) {
$return["type"] = $this->expressionName();
if(isset($options["constantAsQuestionMark"]) && $options["constantAsQuestionMark"] === true) {
$return["constant"] = "?";
} else {
$return["constant"] = $this->constant();
}
if($this->subTree($options) !== false) {
$return["subTree"] = $this->subTree($options);
}
return $return;
}
public function toSql($options=[],&$params=null) {
$params->addParam($this->constant());
if(isset($options["constantAsQuestionMark"]) && $options["constantAsQuestionMark"] === true) {
return "?";
}
return $this->constant();
}
} src/parser/expr/Expression.php 0000644 00000010260 14476160726 0012471 0 ustar 00 $val) {
if(is_array($val) && isset($val["expr_type"])) {
$data[$key] = Expression::fromArray($val);
} elseif(is_array($val) && dhGlobal::isList($val)) {
$data[$key] = [];
foreach($val as $v) {
if(is_array($v) && isset($v["expr_type"])) {
$data[$key][] = Expression::fromArray($v);
} else {
$data[$key][] = $v;
}
}
}
}
$this->data = new ExpressionData($data);
}
public function get($key=null,$defaultValue=false) {
return $this->data->get($key,$defaultValue);
}
public function set($key,$value=null) {
$this->data->set($key,$value);
return $this;
}
public function expressionName() {
return "Expression";
}
public function exprType() {
return $this->get("expr_type");
}
public function type() {
return $this->get("expr_type");
}
public function baseExpr() {
return $this->get("base_expr");
}
public function base() {
return $this->get("base_expr");
}
public function subTree($options=[]) {
return $this->get("sub_tree");
}
public function position() {
return $this->get("position");
}
public function parts() {
return $this->get("no_quotes");
}
public function subTreeSql($options=[],&$params=null) {
$subTree = $this->subTree($options);
$subTreeSql = [];
if(is_array($subTree) && dhGlobal::isList($subTree)) {
foreach($subTree as $expr) {
$subTreeSql[] = $expr->toSql($options,$params);
}
} else {
$subTreeSql[] = $subTree->toSql($options,$params);
}
return $subTreeSql;
}
public static function fromArray($array) {
if(isset($array["expr_type"])) {
$exprType = $array["expr_type"];
if($exprType == "table") {
return new TableExpression($array);
}
if($exprType == "colref") {
return new ColumnExpression($array);
}
if($exprType == "const") {
return new ConstantExpression($array);
}
if($exprType == "operator") {
return new OperatorExpression($array);
}
if($exprType == "bracket_expression") {
return new BracketExpression($array);
}
if($exprType == "in-list") {
return new InListExpression($array);
}
if($exprType == "function") {
return new FunctionExpression($array);
}
if($exprType == "aggregate_function") {
return new FunctionExpression($array);
}
if($exprType == "reserved") {
return new ReservedExpression($array);
}
return new Expression($array);
} else {
return $array;
}
}
public function getArray($options=[]) {
return $this->data->toArray();
}
public function __toString() {
return json_encode($this->toArray(),JSON_PRETTY_PRINT);
}
public function jsonSerialize() {
return $this->toArray();
}
public function toArray($options=[]) {
$arr = $this->getArray($options);
foreach($arr as $k=>$v) {
if($v instanceof Expression) {
$arr[$k] = $v->toArray($options);
}
}
return $arr;
}
public function toSql($options=[],&$params=null) {
$arr = $this->getArray();
foreach($arr as $k=>$v) {
if($v instanceof Expression) {
$arr[$k] = $v->toSql($options,$params);
}
}
return $arr;
}
} src/parser/expr/ExpressionData.php 0000644 00000003043 14476160726 0013264 0 ustar 00 setFromArray($data);
}
}
public function has($dotKey) {
$val = $this->get($dotKey,"_|xzx|_NOT_SET_|xzx|_");
return $val !== "_|xzx|_NOT_SET_|xzx|_";
}
public function get($key=null,$defaultValue=null) {
if(is_null($key)) {
return $this->toArray(false);
}
if(isset($this->data[$key])) {
return $this->data[$key];
}
return $defaultValue;
}
public function set($key,$value=null) {
if(is_array($key)) {
$this->data=$key;
//dhGlobal::parseDots($this->data);
return $this;
}
dhGlobal::dotAssign($this->data,$key,$value);
return $this;
}
public function toArray() {
return $this->data;
}
public function __toString() {
return json_encode($this->toArray(),JSON_PRETTY_PRINT);
}
public function jsonSerialize() {
return $this->toArray();
}
public function setFromArray($array) {
if(is_object($array) && method_exists($array,"toArray")) {
$array = $array->toArray();
}
if(empty($array)) { return false; }
$this->data = $array;
//dhGlobal::parseDots($this->data);
return $this;
}
} src/parser/expr/FunctionExpression.php 0000644 00000001446 14476160726 0014205 0 ustar 00 get("base_expr");
}
public function getArray($options=[]) {
$return = [
"type"=>$this->expressionName(),
"func"=>$this->func(),
];
if($this->subTree($options) !== false) {
$return["subTree"] = $this->subTree($options);
}
return $return;
}
public function toSql($options=[],&$params=null) {
$subTreeSql = $this->subTreeSql($options,$params);
$return = $this->func() . "(". implode(",",$subTreeSql) .")";
return $return;
}
} src/parser/expr/InListExpression.php 0000644 00000001005 14476160726 0013611 0 ustar 00 $this->expressionName(),
"subTree"=>$this->subTree($options),
];
}
public function toSql($options=[],&$params=null) {
$subTreeSql = $this->subTreeSql($options,$params);
return "(" . implode(",",$subTreeSql) . ")";
}
} src/parser/expr/OperatorExpression.php 0000644 00000001213 14476160726 0014203 0 ustar 00 get("base_expr");
}
public function getArray($options=[]) {
$return = [
"type"=>$this->expressionName(),
"operator"=>$this->operator(),
];
if($this->subTree() !== false) {
$return["subTree"] = $this->subTree();
}
return $return;
}
public function toSql($options=[],&$params=null) {
return $this->operator();
}
} src/parser/expr/Params.php 0000644 00000000470 14476160726 0011557 0 ustar 00 data = [];
}
public function addParam($param) {
$this->data[] = $param;
}
public function get($options=[]) {
return $this->data;
}
} src/parser/expr/ReservedExpression.php 0000644 00000001015 14476160726 0014167 0 ustar 00 get("base_expr");
}
public function getArray($options=[]) {
$return["type"] = $this->expressionName();
$return["constant"] = $this->reserved();
return $return;
}
public function toSql($options=[],&$params=null) {
return $this->reserved();
}
} src/parser/expr/TableExpression.php 0000644 00000007163 14476160726 0013451 0 ustar 00 get("no_quotes")) !== false) {
return $noQuotes["parts"][0];
}
return $this->get("table");
}
public function alias() {
$alias = $this->get("alias");
if(is_array($alias) && isset($alias["no_quotes"])) {
return $alias["no_quotes"]["parts"][0];
}
return $this->get("alias");
}
public function hints() {
return $this->get("hints");
}
public function joinType() {
return $this->get("join_type");
}
public function refType() {
return $this->get("ref_type");
}
/**
* @return Expression|Expression[]|false
*/
public function refClause() {
return $this->get("ref_clause");
}
public function refClauseSql($options=[],&$params=null) {
$refClause = $this->refClause();
$refClauseSql = [];
if(is_array($refClause) && dhGlobal::isList($refClause)) {
foreach($refClause as $expr) {
$refClauseSql[] = $expr->toSql($options,$params);
}
} else {
$refClauseSql[] = $refClause->toSql($options,$params);
}
return $refClauseSql;
}
private function joinTypeSql() {
if($this->refType() === false) {
return;
}
switch($this->joinType()) {
case "LEFT":
return "LEFT JOIN";
case "RIGHT":
return "RIGHT JOIN";
case "INNER":
case "JOIN":
return "INNER JOIN";
case "CROSS":
return "CROSS JOIN";
case "STRAIGHT":
return "STRAIGHT_JOIN";
case "NATURAL":
return "NATURAL JOIN";
default:
return "JOIN";
}
}
public function getArray($options=[]) {
$return = [
"type"=>$this->expressionName(),
"table"=>$this->table(),
];
if($this->alias() !== false) {
$return["alias"] = $this->alias();
}
if($this->hints() !== false) {
$return["hints"] = $this->hints();
}
if($this->joinType() !== false) {
$return["joinType"] = $this->joinType();
}
if($this->refType() !== false) {
$return["refType"] = $this->refType();
}
if($this->refClause() !== false) {
$return["refClause"] = $this->refClause();
}
if($this->subTree() !== false) {
$return["subTree"] = $this->subTree();
}
return $return;
}
public function toSql($options=[],&$params=null) {
$parts = [];
if($this->joinType() !== false && $this->refType() !== false) {
$parts[] = $this->joinTypeSql();
}
$parts[] = "`".$this->table()."`";
if($this->alias() !== false) {
$parts[] = "AS " . $this->alias();
}
if($this->hints() !== false) {
$parts[] = $this->hints();
}
if($this->refType() !== false) {
$parts[] = $this->refType();
}
if($this->refClause() !== false) {
$refClauseSql = $this->refClauseSql($options,$params);
$parts[] = implode(" ",$refClauseSql);
}
return implode(" ",$parts);
}
}