Skip to content

Instantly share code, notes, and snippets.

@anoopmd

anoopmd/database.php

Last active Jan 1, 2019
Embed
What would you like to do?
InMemoryDB php class psuedo code
<?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;
}
}
<?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());
}
@anoopmd

This comment has been minimized.

Copy link
Owner Author

@anoopmd anoopmd commented Jan 1, 2019

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment