TransWikia.com

Trying to connect to an external ODBC data source

Joomla Asked by Irata on September 5, 2021

I have a need to connect to a data source on an old unix box via ODBC, but I don’t seem to be getting far and I can’t find any examples to help me.

I have started with https://docs.joomla.org/Connecting_to_an_external_database and set up the following details:

$option['driver'] = 'pdo';            // Database driver name
$option['host'] = 'nnn.nnn.nnn.nnn:nnnn';    // Database host name
$options['dsn'] = 'Fred';
$option['user'] = 'Barney';       // User for database authentication
$option['password'] = 'Wilma';   // Password for database authentication
$option['database'] = 'dbname';      // Database name
$option['prefix'] = '';             // Database prefix (may be empty)

$dbx = JDatabaseDriver::getInstance($option);

With that configuration, I get an error message of:

Cannot instantiate abstract class JDatabaseDriverPdo
E:wwwbedrocklibrariesjoomladatabasedriver.php:313

This happens because driver.php takes the value ‘pdo’ from $option['driver'] = 'pdo'; and appends it to a class of JDatabaseDriver to be found in librariesdatabasedriverpdo.php which is an abstract class the extends JDatabaseDriver hence the message. It is the only abstract class in /driver. If I replace ‘pdo’ with ‘odbc’, I get a message to say it can’t load the database driver which will be because the class JDatabaseDriverOdbc is not found.

When I look at librariesdatabasedriverpdo.php, I can see that ‘odbc’ is the default if no other driver is specified and further down I can see the connection string set up for ‘odbc’ so it looks like it is supported.

public function __construct($options)
{
    // Get some basic values from the options.
    $options['driver'] = (isset($options['driver'])) ? $options['driver'] : 'odbc';
    $options['dsn'] = (isset($options['dsn'])) ? $options['dsn'] : '';
    $options['host'] = (isset($options['host'])) ? $options['host'] : 'localhost';
    ...
    // Find the correct PDO DSN Format to use:
    switch ($this->options['driver'])
    {
    ..
    case 'odbc':
    $format = 'odbc:DSN=#DSN#;UID:#USER#;PWD=#PASSWORD#';
    $replace = array('#DSN#', '#USER#', '#PASSWORD#');
    $with = array($this->options['dsn'], $this->options['user'], $this->options['password']);

It seems to me that $option['driver'] = has two different uses depending on where it is used, as either a suffix to build a class name or as a switch to set the connection string.

I have also tried to use the class directly with

`$option['driver'] = 'odbc';
...
$dbx = JDatabaseDriverPdo::getInstance($option);

however that still tries to find a class of JDatabaseDriverOdbc from driver.php

I really could use some pointers in the right direction or an example of ODBC in use.

Some hours later…

Looking at the code in driver.php and some of the data base formats in librariesdatabasedriver it would appear I need to create a new class that extends JDatabaseDriverPdo, eg. class JDatabaseDriverOdbc extends JDatabaseDriverPdo and make that available to my code. So I think the Joomla answer is yes you can do it if you write your own connector.

One Answer

Although I have had to put this work aside for the time being I wanted to provide some closure to this question.

The last part of my original post is approximately what was required, I had to create a /joomla/database/odbc.php which I created from copying from one of the existing drivers and change the relevant references to 'odbc', and that extended the JDatabaseDriverPdo class.

That got me past the error message in the original Question but then I hit a problem with the next line, $query = $dbx->getQuery(true);due to either an error in the core code or my lack of understanding but it is worth mentioning here if anyone else finds this post.

The getQuery command calls this piece of code in /joomla/database/driver.php

public function getQuery($new = false)
    {
        if ($new)
        {
            // Derive the class name from the driver.
            $class = 'JDatabaseQuery' . ucfirst($this->name);

            // Make sure we have a query class for this driver.
            if (!class_exists($class))
            {
                // If it doesn't exist we are at an impasse so throw an exception.
                throw new JDatabaseExceptionUnsupported('Database Query Class not found.');
            }

            return new $class($this);
        }
        else
        {
            return $this->sql;
        }
    }

However $this->name which creates the $class is not picking up the value set in the JDatabaseDriverXxxx for $this-name therefore it always falls out the bottom returning a value of mysqli.

My resolution was to copy this function into my joomla/database/odbc.php so that it would receive the correct value of $this->name, odbc.

The lack of being able to find a suitable linux ODBC driver to work with the target has put this stage of the project on hold for the time being.

Correct answer by Irata on September 5, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP