Last active
January 1, 2019 18:34
-
-
Save helloanoop/c94e214290a63e0a479b67a1fbbffda6 to your computer and use it in GitHub Desktop.
InMemoryDB php class psuedo code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Database | |
{ | |
/** | |
* Storage | |
* @var array | |
*/ | |
protected $database = array(); | |
/** | |
* Transactions | |
* @var array | |
*/ | |
protected $transactions = array(); | |
/** | |
* Value usage counter | |
* @var array | |
*/ | |
protected $valueUsage = array(); | |
/** | |
* Set value | |
* @param $name | |
* @param bool $value | |
*/ | |
protected function setValue($name,$value=false) | |
{ | |
if(isset($this->database[$name])) { | |
$this->valueUsage[$this->database[$name]] -= 1; | |
unset($this->database[$name]); | |
} | |
if ($value) { | |
$this->database[$name] = $value; | |
// IDEA: if values are mostly large, we can keep their hashes as $valueUsage key | |
$this->valueUsage[$value] = isset($this->valueUsage[$value]) ? $this->valueUsage[$value] + 1 : 1; | |
} | |
} | |
/** | |
* Keep records about value change | |
* @param $name | |
*/ | |
protected function addTransactionChange($name) | |
{ | |
if ($this->transactions) { | |
$lastTransaction = end($this->transactions); | |
if (!isset($lastTransaction[$name])) { | |
$this->transactions[key($this->transactions)][$name] = $this->get($name); | |
} | |
} | |
} | |
/** | |
* Open a transactional block | |
*/ | |
public function begin() | |
{ | |
array_push($this->transactions, array()); | |
} | |
/** | |
* Rollback all of the commands from the most recent transaction block | |
* | |
* @throws Exception | |
*/ | |
public function rollback() | |
{ | |
if ($this->transactions) { | |
$lastTransaction = end($this->transactions); | |
foreach($lastTransaction as $name => $value) { | |
$this->setValue($name,$value); | |
} | |
unset($this->transactions[key($this->transactions)]); | |
} else { | |
throw new Exception("INVALID ROLLBACK"); | |
} | |
} | |
/** | |
* Permanently store all of the operations from any presently open transactional blocks | |
*/ | |
public function commit() | |
{ | |
$this->transactions = array(); | |
} | |
/** | |
* Return the value stored under the variable $name | |
* @param $name | |
* @return string | |
*/ | |
public function get($name) | |
{ | |
return isset($this->database[$name]) ? $this->database[$name] : 'null'; | |
} | |
/** | |
* Set variable | |
* @param $name | |
* @param $value | |
*/ | |
public function set($name,$value) | |
{ | |
$this->addTransactionChange($name); | |
$this->setValue($name,$value); | |
} | |
/** | |
* Unset variable | |
* @param $name | |
*/ | |
public function delete($name) | |
{ | |
$this->addTransactionChange($name); | |
$this->setValue($name); | |
} | |
/** | |
* Returns the number of variables equal to $value | |
* @param $value | |
* @return int | |
*/ | |
public function numEqualTo($value) | |
{ | |
return isset($this->valueUsage[$value]) ? $this->valueUsage[$value] : 0; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require_once('database.php'); | |
$database = new Database(); | |
if(!defined('STDIN')) define('STDIN', fopen('php://stdin', 'r')); | |
if(!defined('STDOUT')) define('STDOUT', fopen('php://stdout', 'w')); | |
if(!defined('STDERR')) define('STDERR', fopen('php://stderr', 'w')); | |
fwrite(STDOUT, "\nHey! Program will terminate on command 'END'\n\n"); | |
$data = array(); | |
do { | |
$command = trim(fgets(STDIN)); | |
$data[] = explode(' ', $command); | |
} while ($command != 'END'); | |
fwrite(STDOUT, "-- OUTPUT --\n"); | |
try { | |
foreach ($data as $cmd) { | |
switch ($cmd[0]) { | |
case 'BEGIN': | |
$database->begin(); | |
break; | |
case 'ROLLBACK': | |
$database->rollback(); | |
break; | |
case 'COMMIT': | |
$database->commit(); | |
break; | |
case 'GET': | |
echo $database->get($cmd[1])."\n"; | |
break; | |
case 'SET': | |
$database->set($cmd[1],@$cmd[2]); | |
break; | |
case 'UNSET': | |
$database->delete($cmd[1]); | |
break; | |
case 'NUMEQUALTO': | |
echo $database->numEqualTo($cmd[1])."\n"; | |
break; | |
case 'END': | |
exit(0); | |
break; | |
default: | |
fwrite(STDOUT, "There is no command $cmd[0]!\n"); | |
exit(0); | |
break; | |
} | |
} | |
} catch(Exception $e) { | |
fwrite(STDOUT, $e->getMessage()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is just a pseudo code. Not intended for production. Please note that this code is checked for its correctness. A lot of improvements may be needed.