generator for primary keys (HiLo, UUID, etc.)

19 views
Skip to first unread message

Beau Simensen

unread,
Sep 2, 2010, 1:56:19 PM9/2/10
to repos...@googlegroups.com
> here is my own version of Hilo identifier generator for php and
> repose. like in Hibernate it need to use a new connection for the
> querys, so it needs to be configure it to connect with database via
> PDO. It makes sense to config the table name and the next_hi field but
> its the first version. To work properly or more efficiently is better
> to have an previusly initiated session using session_start()
>
> interface repose_IdentifierGenerator {
>        public function generate($className);
> }
> ...

I did a lot of work on this last night and will try to incorporate
some of your ideas into Repose sometime in the next week. It may not
be exactly what you have proposed here but it could turn out to be
pretty close. As of right now, I have built in support for:

* auto - will use auto increment "last insert ID" (default behavior)
* uuid - will generate a v4 UUID prior to inserting the first time
* assigned - will assume that you have assigned the value for the key already

This is handled by way of the property named as a primary key.

'projectId' => array(
'primaryKey' => true,
'generator' => 'uuid',
),

This will be a part of Repose 0.0.9 and the manual will be updated at
that point.

--

Beau D. Simensen


Dragonfly Development Inc
http://dflydev.com/

s3a - Fresh. Urban. Seattle.
http://s3attle.com/


[blog] http://not-invented-here.com/
[flickr] http://flickr.com/photos/kirkryyn
[facebook] http://facebook.com/simensen

Beau D. Simensen

unread,
Sep 9, 2010, 3:13:40 AM9/9/10
to Repose PHP ORM General Discussion
Hi aek,

I believe I have finished building out the generator code to be
included in Repose 0.0.9. I do not think I am going to include the
HiLoIdentifierGenerator in this release as I do not understand it
completely and do not really like the use of $_SESSION. However, I
think that what I have added will make it easy for you to drop your hi/
lo generator into the stock Repose 0.0.9 pretty easily. I created a
somewhat more complex interface for the property generation and put
the hooks in a few places. Right now I have support for:

* auto - will use auto increment "last insert ID" (default behavior)
* uuid - will generate a v4 UUID when the object is first added to a
session
* assigned - will assume that you have assigned the value for the key
already

Custom generators can be used in the following ways:

'projectId' => array(
'primaryKey' => true,
'generator' => 'mypackage_CustomHiLoGenerator',
),

'projectId' => array(
'primaryKey' => true,
'generator' => $myCustomGenerator, // is instance of
repose_IPropertyGenerator
),

I haven't checked it in yet, but this is what
repose_IPropertyGenerator currently looks like:

<?php
/**
* Property Generator Interface
* @package repose
*/

/**
* Property Generator Interface
* @package repose
*/
interface repose_IPropertyGenerator {

/**
* Generates an ID
* @param $session Session
* @param $clazz Mapped Class
* @param $property Mapped Class Property
* @param $object Instance of class
* @param $newId New ID if available from engine (auto increment)
*/
public function generate(repose_Session $session,
repose_MappedClass $clazz, repose_MappedClassProperty $property,
$object, $newId = null);

/**
* Should generate ID when object is added to session
* @return bool
*/
public function shouldGenerateOnAdd();

/**
* Should generate ID just before object will be persisted
* @return bool
*/
public function shouldGenerateBeforePersist();

/**
* Should generate ID right after object has been persisted (i.e.,
"last insert ID")
* @return bool
*/
public function shouldGenerateAfterPersist();

}
?>

... and an abstract base class:

<?php
/**
* Abstract Property Generator
* @package repose
*/

require_once('repose_IPropertyGenerator.php');

/**
* UUID Property Generator
* @package repose
*/
abstract class repose_AbstractPropertyGenerator implements
repose_IPropertyGenerator {
public function shouldGenerateOnAdd() { return false; }
public function shouldGenerateBeforePersist() { return false; }
public function shouldGenerateAfterPersist() { return false; }
}
?>

I've included your entire code snippet at the bottom of this email for
future reference. You would be able to extend
repose_AbstractPropertyGenerator and change the method signature of
your generate() method. Since you will have access to the repose
session, you would be able to access the engine:

$rows = $session->engine()->query(
$session,
'SELECT next_hi FROM repose_unique_key FOR UPDATE'
);

$session->engine()->update(
$session,
'UPDATE ...',
array('next_hi' => $hi, 'old_hi' => $hi+1,)
);

(it wasn't clear to me if you needed to have a separate PDO connection
for this or not... or if you could use the one that was already open?)



interface repose_IdentifierGenerator {
public function generate($className);
}

class repose_HiLoIdentifierGenerator implements
repose_IdentifierGenerator{
private $dsn;
private $username;
private $password;

public function generate($className){

if(isset($_SESSION["HiValues"])){
$domainClassesHiValues = $_SESSION["HiValues"];
if(isset($domainClassesHiValues[$className])){
$hival =
$domainClassesHiValues[$className][0];
$hi = $domainClassesHiValues[$className]
[1];
$lo = $domainClassesHiValues[$className]
[2];
} else {
//$hival = $this->getNext();
$lo = 32768;
}
} else {
$lo = 32768;
$domainClassesHiValues = array();
}

if ($lo > 32767) {
$hival = $this->getNext();
$lo = ($hival == 0) ? 1 : 0;
$hi = $hival * 32768; //$hiVal *
(Short.MAX_VALUE + 1);
}

$next = $hi + $lo++;

$values = array();
$values[] = $hival;
$values[] = $hi;
$values[] = $lo;
$domainClassesHiValues[$className] = $values;

$_SESSION["HiValues"] = $domainClassesHiValues;
return $next;
}

public function getNext(){
$conn = new PDO($this->dsn, $this->username, $this-
>password);

$select = 'select next_hi from repose_unique_key for
update';
$update = 'update repose_unique_key set next_hi
= :next_hi where
next_hi = :old_hi';
$query = $conn->prepare($select);
$query->execute(array());

$rows = array();
foreach ( $query->fetchAll(PDO::FETCH_ASSOC) as $row )
{
$rows[] = $row;
}

$hi = $rows[0]['next_hi'];

$query = $conn->prepare($update);
$params = array();
$params['next_hi'] = $hi+1;
$params['old_hi'] = $hi;
$query->execute($params);

return $hi+1;
}

public function setDsn($dsn){
$this->dsn = $dsn;
}
public function setUsername($username){
$this->username = $username;
}
public function setPassword($password){
$this->password = $password;
}
public function getDsn(){
return $this->dsn;
}
public function getUsername(){
return $this->username;
}
public function getPassword(){
return $this->password;
> Dragonfly Development Inchttp://dflydev.com/
>
> s3a - Fresh. Urban. Seattle.http://s3attle.com/
Reply all
Reply to author
Forward
0 new messages