Thursday, March 20, 2014

CodeIgniter Database Driver for SAP Sybase SQL Anywhere

CodeIgniter provides drivers for all the famous databases like MySQL, Oracle and MS SQL, but if somebody wants to use SAP Sybase SQL Anywhere with CI then it's difficult to write a new driver. I have written a CodeIgniter DB driver which supports SQL Anywhere. Please follow the below steps.

1. Create a new folder in sasql in "system/database/drivers".
2. Create below files in sasql folder.
  • sasql_driver.php
  • sasql_result.php
  • sasql_utility.php
  • sasql_forge.php

GitHub URL:
https://github.com/nirmaljingar/CI-DB-Driver-for-SQL-Anywhere

Content for above files:
sasql_driver.php
<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * SAP Sybase SQL Anywhere Database Adapter Class
 *
 * Note: _DB is an extender class that the app controller
 * creates dynamically based on whether the active record
 * class is being used or not.
 *
 * @package        CodeIgniter
 * @subpackage    Drivers
 * @category    Database
 * @author        Nirmal Jingar
 */
class CI_DB_sasql_driver extends CI_DB
{

    var $dbdriver = 'sasql';
    // the character used to excape - not necessary for SQL Anywhere
    var $_escape_char = '';
    // clause and character used for LIKE escape sequences
    var $_like_escape_str = " escape '%s' ";
    var $_like_escape_chr = '!';

    /**
     * The syntax to count rows is slightly different across different
     * database engines, so this string appears in each driver and is
     * used for the count_all() and count_all_results() functions.
     */
    var $_count_string = "SELECT COUNT(*) AS ";
    var $_random_keyword;

    function __construct($params)
    {
        parent::__construct($params);

        $this->_random_keyword = ' RND(' . time() . ')'; // database specific random keyword
    }

    /**
     * Non-persistent database connection
     *
     * @access    private called by the base class
     * @return    resource
     */
    function db_connect()
    {
        return @sasql_connect("Dbn=$this->database;UID=$this->username;PWD=$this->password;ServerName=$this->server_name");
    }

    // --------------------------------------------------------------------

    /**
     * Persistent database connection
     *
     * @access    private called by the base class
     * @return    resource
     */
    function db_pconnect()
    {
        return @sasql_pconnect("Dbn=$this->database;UID=$this->username;PWD=$this->password;ServerName=$this->server_name");
    }

    // --------------------------------------------------------------------

    /**
     * Reconnect
     *
     * Keep / reestablish the db connection if no queries have been
     * sent for a length of time exceeding the server's idle timeout
     *
     * @access    public
     * @return    void
     */
    function reconnect()
    {
        // not implemented in sasql
    }

    // --------------------------------------------------------------------

    /**
     * Select the database
     *
     * @access    private called by the base class
     * @return    resource
     */
    function db_select()
    {
        // Not needed for SQL Anywhere
        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Set client character set
     *
     * @access    public
     * @param    string
     * @param    string
     * @return    resource
     */
    function db_set_charset($charset, $collation)
    {
        // @todo - add support if needed
        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Version number query string
     *
     * @access    public
     * @return    string
     */
    function _version()
    {
        return "SELECT version() AS ver";
    }

    // --------------------------------------------------------------------

    /**
     * Execute the query
     *
     * @access    private called by the base class
     * @param    string    an SQL query
     * @return    resource
     */
    function _execute($sql)
    {
        $sql = $this->_prep_query($sql);
        return @sasql_query($this->conn_id, $sql);
    }

    // --------------------------------------------------------------------

    /**
     * Prep the query
     *
     * If needed, each database adapter can prep the query string
     *
     * @access    private called by execute()
     * @param    string    an SQL query
     * @return    string
     */
    function _prep_query($sql)
    {
        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Begin Transaction
     *
     * @access    public
     * @return    bool
     */
    function trans_begin($test_mode = FALSE)
    {
        if (!$this->trans_enabled)
        {
            return TRUE;
        }

        // When transactions are nested we only begin/commit/rollback the outermost ones
        if ($this->_trans_depth > 0)
        {
            return TRUE;
        }

        // Reset the transaction failure flag.
        // If the $test_mode flag is set to TRUE transactions will be rolled back
        // even if the queries produce a successful result.
        $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;

        sasql_set_option($this->conn_id, 'auto_commit', 'on'); // DON'T KNOW THIS IS REQUIRED OR NOT.
        $this->simple_query('BEGIN TRANSACTION');
        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Commit Transaction
     *
     * @access    public
     * @return    bool
     */
    function trans_commit()
    {
        if (!$this->trans_enabled)
        {
            return TRUE;
        }

        // When transactions are nested we only begin/commit/rollback the outermost ones
        if ($this->_trans_depth > 0)
        {
            return TRUE;
        }

        $ret = sasql_commit($this->conn_id);
        return $ret;
    }

    // --------------------------------------------------------------------

    /**
     * Rollback Transaction
     *
     * @access    public
     * @return    bool
     */
    function trans_rollback()
    {
        if (!$this->trans_enabled)
        {
            return TRUE;
        }

        // When transactions are nested we only begin/commit/rollback the outermost ones
        if ($this->_trans_depth > 0)
        {
            return TRUE;
        }

        $ret = sasql_rollback($this->conn_id);
        return $ret;
    }

    // --------------------------------------------------------------------

    /**
     * Escape String
     *
     * @access    public
     * @param    string
     * @param    bool    whether or not the string will be used in a LIKE condition
     * @return    string
     */
    function escape_str($str, $like = FALSE)
    {
        if (is_array($str))
        {
            foreach ($str as $key => $val)
            {
                $str[$key] = $this->escape_str($val, $like);
            }

            return $str;
        }

        if (function_exists('sasql_real_escape_string') AND is_resource($this->conn_id))
        {
            $str = sasql_real_escape_string($this->conn_id, $str);
        }
        elseif (function_exists('sasql_escape_string'))
        {
            $str = sasql_escape_string($str);
        }
        else
        {
            $str = addslashes($str);
        }

        // escape LIKE condition wildcards
        if ($like === TRUE)
        {
            $str = str_replace(array($this->_like_escape_chr, '%', '_'), array($this->_like_escape_chr . $this->_like_escape_chr, $this->_like_escape_chr . '%', $this->_like_escape_chr . '_'), $str);
        }

        return $str;
    }

    // --------------------------------------------------------------------

    /**
     * Affected Rows
     *
     * @access    public
     * @return    integer
     */
    function affected_rows()
    {
        return @sasql_num_rows($this->conn_id);
    }

    // --------------------------------------------------------------------

    /**
     * Insert ID
     *
     * @access    public
     * @return    integer
     */
    function insert_id()
    {
        return @sasql_insert_id($this->conn_id);
    }

    // --------------------------------------------------------------------

    /**
     * "Count All" query
     *
     * Generates a platform-specific query string that counts all records in
     * the specified database
     *
     * @access    public
     * @param    string
     * @return    string
     */
    function count_all($table = '')
    {
        if ($table == '')
        {
            return 0;
        }

        $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));

        if ($query->num_rows() == 0)
        {
            return 0;
        }

        $row = $query->row();
        $this->_reset_select();
        return (int) $row->numrows;
    }

    // --------------------------------------------------------------------

    /**
     * Show table query
     *
     * Generates a platform-specific query string so that the table names can be fetched
     *
     * @access    private
     * @param    boolean
     * @return    string
     */
    function _list_tables($prefix_limit = FALSE)
    {
        $sql = "SELECT name FROM sysobjects WHERE type='U'";
        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Show column query
     *
     * Generates a platform-specific query string so that the column names can be fetched
     *
     * @access    public
     * @param    string    the table name
     * @return    string
     */
    function _list_columns($table = '')
    {
        return "select syscolumns.name from syscolumns, sysobjects where sysobjects.name='" . $this->_escape_table($table) . "' and sysobjects.id = syscolumns.id";
    }

    // --------------------------------------------------------------------

    /**
     * Field data query
     *
     * Generates a platform-specific query so that the column data can be retrieved
     *
     * @access    public
     * @param    string    the table name
     * @return    object
     */
    function _field_data($table)
    {
        return "DESCRIBE " . $table;
    }

    // --------------------------------------------------------------------

    /**
     * The error message string
     *
     * @access    private
     * @return    string
     */
    function _error_message()
    {
        return sasql_error($this->conn_id);
    }

    // --------------------------------------------------------------------

    /**
     * The error message number
     *
     * @access    private
     * @return    integer
     */
    function _error_number()
    {
        return sasql_errorcode($this->conn_id);
    }

    // --------------------------------------------------------------------

    /**
     * Escape the SQL Identifiers
     *
     * This function escapes column and table names
     *
     * @access    private
     * @param    string
     * @return    string
     */
    function _escape_identifiers($item)
    {
        if ($this->_escape_char == '')
        {
            return $item;
        }

        foreach ($this->_reserved_identifiers as $id)
        {
            if (strpos($item, '.' . $id) !== FALSE)
            {
                $str = $this->_escape_char . str_replace('.', $this->_escape_char . '.', $item);

                // remove duplicates if the user already included the escape
                return preg_replace('/[' . $this->_escape_char . ']+/', $this->_escape_char, $str);
            }
        }

        if (strpos($item, '.') !== FALSE)
        {
            $str = $this->_escape_char . str_replace('.', $this->_escape_char . '.' . $this->_escape_char, $item) . $this->_escape_char;
        }
        else
        {
            $str = $this->_escape_char . $item . $this->_escape_char;
        }

        // remove duplicates if the user already included the escape
        return preg_replace('/[' . $this->_escape_char . ']+/', $this->_escape_char, $str);
    }

    // --------------------------------------------------------------------

    /**
     * From Tables
     *
     * This function implicitly groups FROM tables so there is no confusion
     * about operator precedence in harmony with SQL standards
     *
     * @access    public
     * @param    type
     * @return    type
     */
    function _from_tables($tables)
    {
        if (!is_array($tables))
        {
            $tables = array($tables);
        }

        return '' . implode(', ', $tables) . '';
    }

    // --------------------------------------------------------------------

    /**
     * Insert statement
     *
     * Generates a platform-specific insert string from the supplied data
     *
     * @access    public
     * @param    string    the table name
     * @param    array    the insert keys
     * @param    array    the insert values
     * @return    string
     */
    function _insert($table, $keys, $values)
    {
        return "INSERT INTO " . $table . " (" . implode(', ', $keys) . ") VALUES (" . implode(', ', $values) . ")";
    }

    // --------------------------------------------------------------------

    /**
     * Insert_batch statement
     *
     * Generates a platform-specific insert string from the supplied data
     *
     * @access    public
     * @param    string    the table name
     * @param    array    the insert keys
     * @param    array    the insert values
     * @return    string
     */
    function _insert_batch($table, $keys, $values)
    {
        return "INSERT INTO " . $table . " (" . implode(', ', $keys) . ") VALUES " . implode(', ', $values);
    }

    // --------------------------------------------------------------------

    /**
     * Update statement
     *
     * Generates a platform-specific update string from the supplied data
     *
     * @access    public
     * @param    string    the table name
     * @param    array    the update data
     * @param    array    the where clause
     * @param    array    the orderby clause
     * @param    array    the limit clause
     * @return    string
     */
    function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
    {
        foreach ($values as $key => $val)
        {
            $valstr[] = $key . " = " . $val;
        }

        $limit = (!$limit) ? '' : ' LIMIT ' . $limit;

        $orderby = (count($orderby) >= 1) ? ' ORDER BY ' . implode(", ", $orderby) : '';

        $sql = "UPDATE " . $table . " SET " . implode(', ', $valstr);

        $sql .= ($where != '' AND count($where) >= 1) ? " WHERE " . implode(" ", $where) : '';

        $sql .= $orderby . $limit;

        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Truncate statement
     *
     * Generates a platform-specific truncate string from the supplied data
     * If the database does not support the truncate() command
     * This function maps to "DELETE FROM table"
     *
     * @access    public
     * @param    string    the table name
     * @return    string
     */
    function _truncate($table)
    {
        return $this->_delete($table);
    }

    // --------------------------------------------------------------------

    /**
     * Delete statement
     *
     * Generates a platform-specific delete string from the supplied data
     *
     * @access    public
     * @param    string    the table name
     * @param    array    the where clause
     * @param    string    the limit clause
     * @return    string
     */
    function _delete($table, $where = array(), $like = array(), $limit = FALSE)
    {
        $conditions = '';

        if (count($where) > 0 OR count($like) > 0)
        {
            $conditions = "\nWHERE ";
            $conditions .= implode("\n", $this->ar_where);

            if (count($where) > 0 && count($like) > 0)
            {
                $conditions .= " AND ";
            }
            $conditions .= implode("\n", $like);
        }

        $limit = (!$limit) ? '' : ' LIMIT ' . $limit;

        return "DELETE FROM " . $table . $conditions . $limit;
    }

    // --------------------------------------------------------------------

    /**
     * Limit string
     *
     * Generates a platform-specific LIMIT clause
     *
     * @access    public
     * @param    string    the sql query string
     * @param    integer    the number of rows to limit the query to
     * @param    integer    the offset value
     * @return    string
     */
    function _limit($sql, $limit, $offset)
    {
        return preg_replace('/(^\SELECT (DISTINCT)?)/i', '\\1 TOP ' . $limit . ' START AT ' . $offset . ' ', $sql);
    }

    // --------------------------------------------------------------------

    /**
     * Close DB Connection
     *
     * @access    public
     * @param    resource
     * @return    void
     */
    function _close($conn_id)
    {
        @sasql_close($conn_id);
    }

}

/* End of file sasql_driver.php */
/* Location: ./system/database/drivers/sasql/sasql_driver.php */
sasql_result.php
<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * SQL Anywhere Result Class
 *
 * This class extends the parent result class: CI_DB_result
 *
 * @category    Database
 * @author        Nirmal Kumar Jingar
 */
class CI_DB_sasql_result extends CI_DB_result
{

    /**
     * Number of rows in the result set
     *
     * @access    public
     * @return    integer
     */
    function num_rows()
    {
        return @sasql_num_rows($this->result_id);
    }

    // --------------------------------------------------------------------

    /**
     * Number of fields in the result set
     *
     * @access    public
     * @return    integer
     */
    function num_fields()
    {
        return @sasql_num_fields($this->result_id);
    }

    // --------------------------------------------------------------------

    /**
     * Fetch Field Names
     *
     * Generates an array of column names
     *
     * @access    public
     * @return    array
     */
    function list_fields()
    {
        $field_names = array();
        while ($field = sasql_fetch_field($this->result_id))
        {
            $field_names[] = $field->name;
        }

        return $field_names;
    }

    // --------------------------------------------------------------------

    /**
     * Field data
     *
     * Generates an array of objects containing field meta-data
     *
     * @access    public
     * @return    array
     */
    function field_data()
    {
        $retval = array();
        while ($field = sasql_fetch_object($this->result_id))
        {
            preg_match('/([a-zA-Z]+)(\(\d+\))?/', $field->Type, $matches);

            $type = (array_key_exists(1, $matches)) ? $matches[1] : NULL;
            $length = (array_key_exists(2, $matches)) ? preg_replace('/[^\d]/', '', $matches[2]) : NULL;

            $F = new stdClass();
            $F->name = $field->Field;
            $F->type = $type;
            $F->default = $field->Default;
            $F->max_length = $length;
            $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );

            $retval[] = $F;
        }

        return $retval;
    }

    // --------------------------------------------------------------------

    /**
     * Free the result
     *
     * @return    null
     */
    function free_result()
    {
        if (is_resource($this->result_id))
        {
            sasql_free_result($this->result_id);
            $this->result_id = FALSE;
        }
    }

    // --------------------------------------------------------------------

    /**
     * Data Seek
     *
     * Moves the internal pointer to the desired offset.  We call
     * this internally before fetching results to make sure the
     * result set starts at zero
     *
     * @access    private
     * @return    array
     */
    function _data_seek($n = 0)
    {
        return sasql_data_seek($this->result_id, $n);
    }

    // --------------------------------------------------------------------

    /**
     * Result - associative array
     *
     * Returns the result set as an array
     *
     * @access    private
     * @return    array
     */
    function _fetch_assoc()
    {
        return sasql_fetch_assoc($this->result_id);
    }

    // --------------------------------------------------------------------

    /**
     * Result - object
     *
     * Returns the result set as an object
     *
     * @access    private
     * @return    object
     */
    function _fetch_object()
    {
        return sasql_fetch_object($this->result_id);
    }

}

/* End of file sasql_result.php */
/* Location: ./system/database/drivers/sasql/sasql_result.php */
sasql_utility.php
<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * SQL Anywhere Utility Class
 *
 * @category    Database
 * @author        Nirmal Kumar Jingar
 */
class CI_DB_sasql_utility extends CI_DB_utility
{

    /**
     * List databases
     *
     * @access    private
     * @return    bool
     */
    function _list_databases()
    {
        return "SHOW DATABASES";
    }

    // --------------------------------------------------------------------

    /**
     * Optimize table query
     *
     * Generates a platform-specific query so that a table can be optimized
     *
     * @access    private
     * @param    string    the table name
     * @return    object
     */
    function _optimize_table($table)
    {
        return "OPTIMIZE TABLE " . $this->db->_escape_identifiers($table);
    }

    // --------------------------------------------------------------------

    /**
     * Repair table query
     *
     * Generates a platform-specific query so that a table can be repaired
     *
     * @access    private
     * @param    string    the table name
     * @return    object
     */
    function _repair_table($table)
    {
        return "REPAIR TABLE " . $this->db->_escape_identifiers($table);
    }

    // --------------------------------------------------------------------
    /**
     * SQL Anywhere Export
     *
     * @access    private
     * @param    array    Preferences
     * @return    mixed
     */
    function _backup($params = array())
    {
        if (count($params) == 0)
        {
            return FALSE;
        }

        // Extract the prefs for simplicity
        extract($params);

        // Build the output
        $output = '';
        foreach ((array) $tables as $table)
        {
            // Is the table in the "ignore" list?
            if (in_array($table, (array) $ignore, TRUE))
            {
                continue;
            }

            // Get the table schema
            $query = $this->db->query("SHOW CREATE TABLE `" . $this->db->database . '`.`' . $table . '`');

            // No result means the table name was invalid
            if ($query === FALSE)
            {
                continue;
            }

            // Write out the table schema
            $output .= '#' . $newline . '# TABLE STRUCTURE FOR: ' . $table . $newline . '#' . $newline . $newline;

            if ($add_drop == TRUE)
            {
                $output .= 'DROP TABLE IF EXISTS ' . $table . ';' . $newline . $newline;
            }

            $i = 0;
            $result = $query->result_array();
            foreach ($result[0] as $val)
            {
                if ($i++ % 2)
                {
                    $output .= $val . ';' . $newline . $newline;
                }
            }

            // If inserts are not needed we're done...
            if ($add_insert == FALSE)
            {
                continue;
            }

            // Grab all the data from the current table
            $query = $this->db->query("SELECT * FROM $table");

            if ($query->num_rows() == 0)
            {
                continue;
            }

            // Fetch the field names and determine if the field is an
            // integer type.  We use this info to decide whether to
            // surround the data with quotes or not

            $i = 0;
            $field_str = '';
            $is_int = array();
            while ($field = sasql_fetch_field($query->result_id))
            {
                // Most versions of SQL Anywhere store timestamp as a string
                $is_int[$i] = (in_array(
                                strtolower(sasql_field_type($query->result_id, $i)), array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),
                                TRUE)
                        ) ? TRUE : FALSE;

                // Create a string of field names
                $field_str .= '`' . $field->name . '`, ';
                $i++;
            }

            // Trim off the end comma
            $field_str = preg_replace("/, $/", "", $field_str);


            // Build the insert string
            foreach ($query->result_array() as $row)
            {
                $val_str = '';

                $i = 0;
                foreach ($row as $v)
                {
                    // Is the value NULL?
                    if ($v === NULL)
                    {
                        $val_str .= 'NULL';
                    }
                    else
                    {
                        // Escape the data if it's not an integer
                        if ($is_int[$i] == FALSE)
                        {
                            $val_str .= $this->db->escape($v);
                        }
                        else
                        {
                            $val_str .= $v;
                        }
                    }

                    // Append a comma
                    $val_str .= ', ';
                    $i++;
                }

                // Remove the comma at the end of the string
                $val_str = preg_replace("/, $/", "", $val_str);

                // Build the INSERT string
                $output .= 'INSERT INTO ' . $table . ' (' . $field_str . ') VALUES (' . $val_str . ');' . $newline;
            }

            $output .= $newline . $newline;
        }

        return $output;
    }

}

/* End of file sasql_utility.php */
/* Location: ./system/database/drivers/sasql/sasql_utility.php */
sasql_forge.php
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * SQL Anywhere Forge Class
 *
 * @category    Database
 * @author        ExpressionEngine Dev Team
 */
class CI_DB_sasql_forge extends CI_DB_forge {

    /**
     * Create database
     *
     * @access    private
     * @param    string    the database name
     * @return    bool
     */
    function _create_database($name)
    {
        return "CREATE DATABASE ".$name;
    }

    // --------------------------------------------------------------------

    /**
     * Drop database
     *
     * @access    private
     * @param    string    the database name
     * @return    bool
     */
    function _drop_database($name)
    {
        return "DROP DATABASE ".$name;
    }

    // --------------------------------------------------------------------

    /**
     * Process Fields
     *
     * @access    private
     * @param    mixed    the fields
     * @return    string
     */
    function _process_fields($fields)
    {
        $current_field_count = 0;
        $sql = '';

        foreach ($fields as $field=>$attributes)
        {
            // Numeric field names aren't allowed in databases, so if the key is
            // numeric, we know it was assigned by PHP and the developer manually
            // entered the field information, so we'll simply add it to the list
            if (is_numeric($field))
            {
                $sql .= "\n\t$attributes";
            }
            else
            {
                $attributes = array_change_key_case($attributes, CASE_UPPER);

                $sql .= "\n\t".$this->db->_protect_identifiers($field);

                if (array_key_exists('NAME', $attributes))
                {
                    $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' ';
                }

                if (array_key_exists('TYPE', $attributes))
                {
                    $sql .=  ' '.$attributes['TYPE'];

                    if (array_key_exists('CONSTRAINT', $attributes))
                    {
                        switch ($attributes['TYPE'])
                        {
                            case 'decimal':
                            case 'float':
                            case 'numeric':
                                $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
                            break;

                            case 'enum':
                            case 'set':
                                $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
                            break;

                            default:
                                $sql .= '('.$attributes['CONSTRAINT'].')';
                        }
                    }
                }

                if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
                {
                    $sql .= ' UNSIGNED';
                }

                if (array_key_exists('DEFAULT', $attributes))
                {
                    $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
                }

                if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
                {
                    $sql .= ' NULL';
                }
                else
                {
                    $sql .= ' NOT NULL';
                }

                if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
                {
                    $sql .= ' AUTO_INCREMENT';
                }
            }

            // don't add a comma on the end of the last field
            if (++$current_field_count < count($fields))
            {
                $sql .= ',';
            }
        }

        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Create Table
     *
     * @access    private
     * @param    string    the table name
     * @param    mixed    the fields
     * @param    mixed    primary key(s)
     * @param    mixed    key(s)
     * @param    boolean    should 'IF NOT EXISTS' be added to the SQL
     * @return    bool
     */
    function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
    {
        $sql = 'CREATE TABLE ';

        if ($if_not_exists === TRUE)
        {
            $sql .= 'IF NOT EXISTS ';
        }

        $sql .= $this->db->_escape_identifiers($table)." (";

        $sql .= $this->_process_fields($fields);

        if (count($primary_keys) > 0)
        {
            $key_name = $this->db->_protect_identifiers(implode('_', $primary_keys));
            $primary_keys = $this->db->_protect_identifiers($primary_keys);
            $sql .= ",\n\tPRIMARY KEY ".$key_name." (" . implode(', ', $primary_keys) . ")";
        }

        if (is_array($keys) && count($keys) > 0)
        {
            foreach ($keys as $key)
            {
                if (is_array($key))
                {
                    $key_name = $this->db->_protect_identifiers(implode('_', $key));
                    $key = $this->db->_protect_identifiers($key);
                }
                else
                {
                    $key_name = $this->db->_protect_identifiers($key);
                    $key = array($key_name);
                }

                $sql .= ",\n\tKEY {$key_name} (" . implode(', ', $key) . ")";
            }
        }

        $sql .= "\n) DEFAULT CHARACTER SET {$this->db->char_set} COLLATE {$this->db->dbcollat};";

        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Drop Table
     *
     * @access    private
     * @return    string
     */
    function _drop_table($table)
    {
        return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
    }

    // --------------------------------------------------------------------

    /**
     * Alter table query
     *
     * Generates a platform-specific query so that a table can be altered
     * Called by add_column(), drop_column(), and column_alter(),
     *
     * @access    private
     * @param    string    the ALTER type (ADD, DROP, CHANGE)
     * @param    string    the column name
     * @param    array    fields
     * @param    string    the field after which we should add the new field
     * @return    object
     */
    function _alter_table($alter_type, $table, $fields, $after_field = '')
    {
        $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ";

        // DROP has everything it needs now.
        if ($alter_type == 'DROP')
        {
            return $sql.$this->db->_protect_identifiers($fields);
        }

        $sql .= $this->_process_fields($fields);

        if ($after_field != '')
        {
            $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
        }

        return $sql;
    }

    // --------------------------------------------------------------------

    /**
     * Rename a table
     *
     * Generates a platform-specific query so that a table can be renamed
     *
     * @access    private
     * @param    string    the old table name
     * @param    string    the new table name
     * @return    string
     */
    function _rename_table($table_name, $new_table_name)
    {
        $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table_name)." RENAME TO ".$this->db->_protect_identifiers($new_table_name);
        return $sql;
    }

}

/* End of file sasql_forge.php */
/* Location: ./system/database/drivers/sasql/sasql_forge.php */

No comments:

Post a Comment