Roll Your Own (Highly Experimental) MultiValue Database — Part 2

In this series of articles, we are going to build a brand new flavor of MultiValue database engine. I call it Lumpy, because data isn't flat. Also, because programmers shouldn't be allowed to name things. While Part 1 laid the groundwork, a database isn't a database if you can't CRUD (Create, Read, Update, Delete) it up.

Remember, while Lumpy is implemented in PHP, it could be implemented in any language. The goal is to build a roadmap of features and create a reference set of working commands in one language. Where you take it is up to you.

"Oh, Pen," Says Me

Since Lumpy is MultiValue, we need to start any discussion of file transactions with the OPEN statement. OPEN establishes a handle — which can be used by READ, WRITE, and DELETE — to specify which file is responding to the actions.

Since the language isn't BASIC, we have some hoops to jump through. Our variables won't be their variables, but this is only useful if you can easily exchange values between the host language and the Lumpy commands. To accomplish this, before we can dig into the CRUD, we need a way move things back and forth. Here's an example of our get and set commands:


phpVariable = Lumpy->command('get attendee.rec');

We will treat the file variable, the record id, and the record itself, as Lumpy variables. OPEN will look like this:

Lumpy->command('open attendee to attendee.handle');

The OPEN statement should allow for THEN and/or ELSE actions:

If(Lumpy->command('open attendee to attendee.handle')['error'] = false)

All of this will be extended into PHP using the verbs.php module we started developing in the last issue. Lumpy programs will start with this PHP command:


The code for verbs.php can be found at

Reed and Rite

Now that we've laid the groundwork, we can get to the core commands for this article. Here's an example of the syntax for the Lumpy version of READ with a THEN clause:


If(Lumpy->command('read attendee.rec from attendee.handle,')['error'] = false)

phpVariable = Lumpy->command('get attendee.rec');

The code for verbs.php can be found at

Of course, we don't have just one READ command in MultiValue. Spoiler: not all of them will make an appearance in our new system . Lumpy will support READ and READV. It won't support READT (tape), READU (locking), and READVU (also locking). Tape processing and locking are both out-of-scope. Since all the code will be available, you are welcome to provide those extensions.

Lumpy will also skip READSEQ (foreign files) and MATREAD (dimensioned arrays). Don't feel the need to add these two on your own time. MATREAD and all its related commands are omitted because fixed arrays don't have the same performance differential in PHP that they would have in other MultiValue implementations. MAT is useless in Lumpy. SEQ-style commands... we'll get to that next issue. While we are leaving them out, we aren't really leaving them out. It's complicated because it will be easier. You'll see.

Part of the fun of roll-your-own is customization. While that will mean cutting some commands, as we've already discussed, we can also jazz up Lumpy by adding new commands. READX tests if the record exists. It will not return the content, just a true/false. You could do this with a READ or READV, but READX will be more efficient.

Some examples of our three READs:


Lumpy->command('read attendee.rec from attendee.handle,');

Lumpy->command('readv attendee.rec from attendee.handle,, -1');

Lumpy->command('readx from attendee.handle,');

The code for verbs.php can be found at

Reading only works if there's content. The WRITE command is our mechanism for adding data to our database. As with READ, WRITE will lose some variants. It will also gain two new ones. Say goodbye to WRITET (tape), WRITEU (locking), and MATWRITE (dimensioned arrays). Say hello to WRITEC and WRITER. WRITEC is a specialized version of WRITE which will create new records but not replace existing records. WRITER is the reverse. It will (update) replace existing records only, but never create new ones.

DELETE comes through as-is.

Lumpy->command('write attendee.rec on attendee.handle,');

Lumpy->command('writev attendee.rec on attendee.handle,, -1');

Lumpy->command('writec attendee.rec on attendee.handle,');

Lumpy->command('writer attendee.rec on attendee.handle,');

Lumpy->command('delete attendee.handle,');

The code for verbs.php can be found at

Delete, Not to be Confused with Delete

MultiValue has a second form of DELETE, but it does not deal with file I/O so it was omitted from this article. READNEXT does deal with file I/O but not in the same way as other READ commands. READNEXT has a featured role in Part 3.

Verde Ick

Part 1 established the commands for creating databases, accounts, and tables. This part was all about CRUD, Let's see how we did.

CRUD scorecard for Lumpy:

Create: WRITEC


Update: WRITER

Delete: DELETE

Plus, we still have the traditional WRITE, WRITEV, and the new READX.

Hide and SEQ

While we've met our goals, the Lumpy odyssey is not over. Next up, we will discuss foreign data structures, dictionaries, and LQL (Lumpy Query Language).


Charles Barouch is the CTO of HDWP, Inc. He is also a regular contributor to International Spectrum Magazine, a former Associate Editor for both Database Trends and for Gateways Magazine, a former distance learning Instructor for CALC. He is presently the Past President of the U2UG. Mr. Barouch has presented technology and business topics in front of hundreds of companies, in a wide range of product and service categories. He is available for on-site speaking and consulting engagements in and out of the United States.

View more articles


Jul/Aug 2015