.gitignore000064400000000052144761607260006546 0ustar00/vendor/ /tests/ composer.lock .vscode/ composer.json000064400000000746144761607260007312 0ustar00{ "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.txt000064400000000311144761607260011706 0ustar00{ "require": { "boru/dhout": "dev-master" }, "repositories": [ { "type": "composer", "url": "https://satis.boruapps.com" } ] }src/Error.php000064400000004777144761607260007171 0ustar00setMessage($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.php000064400000013240144761607260007166 0ustar00rawQueryString = $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.php000064400000000742144761607260007342 0ustar00setTableName($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.php000064400000001440144761607260011573 0ustar00run($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.php000064400000022264144761607260011316 0ustar00threads = 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.php000064400000014604144761607260012514 0ustar00sql($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.php000064400000026024144761607260006666 0ustar00setDriver( 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.php000064400000021157144761607260010652 0ustar00"", "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.php000064400000041225144761607260012144 0ustar00setQuery($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.php000064400000003714144761607260011460 0ustar00setGetSetMainArray("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.php000064400000004155144761607260012655 0ustar00stmt = $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.php000064400000001604144761607260013261 0ustar00get($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.php000064400000000637144761607260013777 0ustar00wrapper = 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.php000064400000011657144761607260012544 0ustar00parser = 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.php000064400000001045144761607260013766 0ustar00$this->expressionName(), "subTree"=>$this->subTree($options), ]; } public function toSql($options=[],&$params=null) { $subTreeSql = $this->subTreeSql($options,$params); return "(" . implode(" ",$subTreeSql) . ")"; } }src/parser/expr/ColumnExpression.php000064400000003615144761607260013655 0ustar00get("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.php000064400000001762144761607260014212 0ustar00get("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.php000064400000010260144761607260012471 0ustar00$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.php000064400000003043144761607260013264 0ustar00setFromArray($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.php000064400000001446144761607260014205 0ustar00get("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.php000064400000001005144761607260013611 0ustar00$this->expressionName(), "subTree"=>$this->subTree($options), ]; } public function toSql($options=[],&$params=null) { $subTreeSql = $this->subTreeSql($options,$params); return "(" . implode(",",$subTreeSql) . ")"; } }src/parser/expr/OperatorExpression.php000064400000001213144761607260014203 0ustar00get("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.php000064400000000470144761607260011557 0ustar00data = []; } public function addParam($param) { $this->data[] = $param; } public function get($options=[]) { return $this->data; } }src/parser/expr/ReservedExpression.php000064400000001015144761607260014167 0ustar00get("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.php000064400000007163144761607260013451 0ustar00get("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); } }