IllicoDB3 - Database Creation

IllicoDB3 - Database Creation

Here is part 2 of this article. As promised, we will start with some code, code that will be as close as possible to an ideal formulation tailored to the use I envision for the classes, methods, and functions to be designed: it’s as if I am putting myself in the shoes of those who will have to USE the IllicoDB3 class, for whom ease of use will be paramount. Therefore, I FIRST focus on creating my examples BEFORE creating my classes. This corresponds to a TDD approach - Test Driven Development.

The examples are gathered in a single file, here test.illicodb3.php, and are developed sequentially: I start with the basics of the basics, and then I gradually expand the range of examples to cover what I intend to develop. At this point, there is no IllicoDB3 class yet.

When I run the first test, boom... it crashes! That's normal: no class has been developed; PHP tells me that the IllicoDB3 class was not found.

Fatal error: Uncaught Error: Class "IllicoDB3" not found in test.illicodb3.php:71 Stack trace: #0 {main} thrown in test.illicodb3.php on line 71        

Okido. So ... the next move seems to start developing the IllicoDB3 class. I'll create an empty one. Once created, I run test.illicodb3.php again, and it crashes again. This time it’s not because the class was not found, but rather because the create() method was not found (this is my first example: before being able to use a DB, it must be created)."

Fatal error: Uncaught Error: Call to undefined method trql\db\IllicoDB3\IllicoDB3::create() in test.illicodb3.php:71 Stack trace: #0 {main} thrown in test.illicodb3.php on line 71        

What is this line 71 that causes these crashes?

It is similar to ...

if ( $success = IllicoDB3::create( $DBName,$folder,$tables ) )
    echo "<p>The '{$DBName}' DB was successfully created</p>\n";
else
    echo "<p>The '{$DBName}' DB COULD NOT BE CREATED</p>\n";        

A this point, it does not matter to see the details of $DBName or $folder or $tables: simply, the create method does not exist! Lets create one:

class IllicoDB3
/*-----------*/
{
    static public function create()
    {
        return ( true );
    }
}        

Very well, the fake method for creating a DB is created : it returns always true.

I give my example another try and, oh miracle, here's what I obtain.

The 'firstDB' DB was successfully created
LINE: 76 - Perf: 0,000346 sec to create a new DB        

My development is indeed driven by my tests, which thus determine the code more than the code determines the tests. This is the method I propose to you here. It's called TDD which stands for Test Driven Development. Not all your tests must be written before the code of the class, but I strongly advise to specify your tests before you write any further code in your class.

As we progress in the creation of the code of the class, we will first extend our tests, even to a point at which they can be be considered acceptance tests.

So, in this TDD development perspective, the first operation we will address is the creation of a very simple DB that will contain only one table. We will name this DB "firstDB" and the table it will contain "firstTable." This table will correspond to the schema proposed in the first article, namely..."

Byte after byte, this corresponds to what firstTable looks like when you open it in binary mode. Any record is preceded by a "pre" structure of 4 bytes, then all the fields of the table, then starts the next record.

Let's anticipate a little and see what the structure of the DB should look like...

<?xml version="1.0" encoding="UTF-8"?>
<database>
    <tables>
        <table name="firstTable">
            <field name="field1" length="6" type="string" />
            <field name="field2" length="4" type="string" />
            <field name="field3" length="7" type="string" />
            <field name="memo1" length="4" type="memo" />
            <field name="memo2" length="4" type="memo" />
        </table>
        </tables>
</database>        

The XML structure presented here corresponds to the structure of firstDB. However, no code has yet been created to create this structure, which is only to be expected as this is precisely what the static create() method should be doing, as it is currently empty and simply returns a logical “true” value in all cases. Normal, stupid!

OK. Let's be more ambitious and create the necessary code BUT first, let's see how we specify the tables to be inserted into the DB structure. Let's have a look at $DBName, $folder and $tables.

    $tables     = [];
    $tables[]   = array( 'name'     => 'firstTable'                                 ,
                         'fields'   => array(   array( 'name'       =>  'field1'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  6           ,
                                                     )                              ,
                                                array( 'name'       =>  'field2'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  4           ,
                                                     )                              ,
                                                array( 'name'       =>  'field3'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  7           ,
                                                     )                              ,
                                                 array( 'name'      =>  'memo1'     ,
                                                        'type'      =>  'memo'      ,
                                                       'length'     =>  4           ,
                                                     )                              ,
                                                 array( 'name'      =>  'memo2'     ,
                                                        'type'      =>  'memo'      ,
                                                       'length'     =>  4           ,
                                                      )                             ,
                                            )                                       ,
                       );

    $DBName = 'firstDB';
    $folder = '/home/vaesoli/central-catalog';        

Note: the folder will depend on your needs. It must be a folder you have access to, otherwise the attempt to create the DB will miserably fail. Let's get back of the example:

echo "<h1>Tests of IllicoDB3</h1>";

if ( true ) /* Create a new DB : firstDB */
{
    echo "<h2>Create a DB</h2>";

    $tables     = [];

    $tables[]   = array( 'name'     => 'firstTable'                                 ,
                         'fields'   => array(   array( 'name'       =>  'field1'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  6           ,
                                                     )                              ,
                                                array( 'name'       =>  'field2'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  4           ,
                                                     )                              ,
                                                array( 'name'       =>  'field3'    ,
                                                       'type'       =>  'string'    ,
                                                       'length'     =>  7           ,
                                                     )                              ,
                                                 array( 'name'      =>  'memo1'     ,
                                                        'type'      =>  'memo'      ,
                                                       'length'     =>  4           ,
                                                     )                              ,
                                                 array( 'name'      =>  'memo2'     ,
                                                        'type'      =>  'memo'      ,
                                                       'length'     =>  4           ,
                                                      )                             ,
                                            )                                       ,
                       );

    $DBName = 'firstDB';
    $folder = '/home/vaesoli/central-catalog';

    $t1 = microtime( true );                    /* Start measuring perf. */
    if ( $success = IllicoDB3::create( $DBName,$folder,$tables ) )
        echo "<p>The '{$DBName}' DB was successfully created</p>\n";
    else
        echo "<p>The '{$DBName}' DB COULD NOT BE CREATED</p>\n";
    $t2 = microtime( true );                    /* Start measuring perf. */
    echo "<p>LINE: <b>" . __LINE__ . "</b> - Perf: ",number_format( $t2-$t1,6,',', '.' )," sec to create a new DB</p>\n";
    echo "<hr />";
}        

This is what happens to the code of the static create() method.

static public function create( string $DBName,string $folder,array $tables )
{
    $DBFile = "{$folder}/{$DBName}" . ILLICODB3_EXTENSION;

     $szXML  = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";

    $szXML .= "<database>\n";
    $szXML .= SP_4 . "<tables>\n";

    foreach ( $tables as $key => $tableData )
    {
        $szXML .= SP_8 . "<table name=\"{$tableData['name']}\">\n";

        foreach( $tableData['fields'] as $field )
        {
            if ( ( $iLength = self::fieldLength( $field['type'] ) ) === -1 )
                $iLength = $field['length'];

            $szXML .= SP_12 . "<field name=\"{$field['name']}\" length=\"{$iLength}\" type=\"{$field['type']}\" />\n";
        }   /* foreach( $aData['fields'] as $field ) */

        $szXML .= "        </table>\n";
    }   /* foreach ( $aTables as $name => $aData ) */

    $szXML .= SP_4 . "    </tables>\n";
    $szXML .= "</database>\n";

    return ( self::strToFile( $szXML,$DBFile ) );        

At this stage, there are a number of comments to be made about this code:

  • it uses definitions that have not been documented (e.g. ILLICODB3_EXTENSION, SP_4, ...)
  • it uses two static functions that have not been defined

Here are the definitions in question and the static methods:

defined( 'ILLICODB3_CLASS_VERSION'      )   or define( 'ILLICODB3_CLASS_VERSION','0.1' );

/* Useful definitions */
defined( 'SP_4'  ) or define( 'SP_4','    ' );
defined( 'SP_8'  ) or define( 'SP_8',SP_4 . SP_4 );
defined( 'SP_12' ) or define( 'SP_12',SP_4 . SP_8 );

defined( 'ILLICODB3_EXTENSION' ) or define( 'ILLICODB3_EXTENSION','.illicoDB3' );

/* Define range of exceptions */
defined( 'EXCEPTION_BASIS' ) or define( 'EXCEPTION_BASIS'        ,1000000 );
defined( 'EXCEPTION_INVALID_FIELD' ) or define( 'EXCEPTION_INVALID_FIELD',EXCEPTION_BASIS + 1005 );        

We shall extend these definitions later on when it will be time to define more exceptions than the only one we have at this very moment.

static public function strToFile( string $str,string $file )
{
    $iRetval = -1;

    $str = mb_convert_encoding( $str,'UTF-8' );

    if ( $handle = fopen( $file,'w+' ) )
    {
        $iRetval = fwrite( $handle,$str );
        fclose( $handle );
    }

    return ( $iRetval === mb_strlen( $str ) );
}        
static public function fieldLength( $type )
{
    static $aTypes = null;

    if ( is_null( $aTypes ) )
    {
        $aTypes['bool'    ] =
        $aTypes['date'    ] = 8;
        $aTypes['datetime'] = 14;
        $aTypes['float'   ] = 16;
        $aTypes['int'     ] = 8;
        /* Indicates that length is manual */
        $aTypes['string'  ] = -1;
        /* Variable length fields */
        $aTypes['memo'    ] = 4;
    }   /* if ( is_null( $aTypes ) ) */

    return ( $aTypes[$type] ?? -EXCEPTION_INVALID_FIELD /* Indicate an error */ );
}        

These two static methods are added to the IllicoDB3 class.

If we now try our test, not only will it not crash, but it will create the DB structure this time. Let's have a look...

Tests of IllicoDB3
Create a DB
The 'firstDB' DB was successfully created

LINE: 76 - Perf: 0,000180 sec to create a new DB        

Conclusions

Despite the modest result achieved, we have nevertheless introduced key elements, not the least of which is TDD. We created our first example and we created the first version of our class. We can even consider making what has been developed available to beta users, which I encourage you to do if there is a tangible value to deploy it now.

With the example and the accompanying IllicoDB3 class, we have successfully created a very first DB.

The next article (#3) will aim to determine the tables contained in a DB and physically create the tables in question. We will also be able to determine the fields belonging to a table. For this, we will need two new classes: IllicoDBTable and IllicoDB3Field. We will implement them at a basic level.

At the end of article #3, we will have a DB (firstDB) and a table (firstTable).

We will continue to develop according to TDD principles. We will therefore add examples.

Then, in article #4, we will focus on adding records to the firstTable table and see how to determine the number of records in the table.

See you soon and ... no complications!

Code included in the article (link to https://www.trql.fm/test.illicodb3.code-of-article2.zip) : test.illicodb3.code-of-article2.zip

PS: most of this code is PHP code that was transformed from C code I created in 2002-2004, code that greatly simplified thanks to PHP

Previous article - Next article

要查看或添加评论,请登录

Patrick Boens的更多文章

  • Forging a ChatBot in the Digital Wilderness

    Forging a ChatBot in the Digital Wilderness

    In the relentless landscape of technological evolution, silence is not the absence of action—it is the crucible of…

  • AI Scanning an Invoice

    AI Scanning an Invoice

    This new issue, dedicated to ChatGPT and Sermo (my programming gateway to ChatGPT, Perplexity, and Claude 3.5 Sonnet)…

  • Software Engineers and AI

    Software Engineers and AI

    Through numerous articles written on the subject of artificial intelligence in the context of digital transformations…

  • Using templates to mimic sophisticated object

    Using templates to mimic sophisticated object

    The Power of Templates in IllicoDB3: Revolutionizing Database Structure In the realm of traditional databases, the…

  • More, Faster, Easier...

    More, Faster, Easier...

    In my previous article, I showed you how to create a small todo management app in record time. Now, based on this first…

  • AI at the Developers' Bedside

    AI at the Developers' Bedside

    Let's dive into the world of AI-powered app creation, showcasing just how effortless it can be to bring your ideas to…

    1 条评论
  • AI and IT

    AI and IT

    Here's the question I asked to "Sonar Huge", the AI model of Perplexity.ai: With the advent of AI taking by storm the…

  • The Imperative of AI in Digital Transformation Projects: A Wake-Up Call for Businesses

    The Imperative of AI in Digital Transformation Projects: A Wake-Up Call for Businesses

    In today's rapidly evolving digital landscape, companies that continue to approach their digital transformation and…

  • Data Migration Projects

    Data Migration Projects

    "Mise en bouche" My first interesting encounter with a data migration project dates back to 1999. The tech world was…

  • IllicoDB3 and AI

    IllicoDB3 and AI

    I have mentioned in the past that IllicoDB3 allows the use of artificial intelligence to generate code related to…

社区洞察

其他会员也浏览了