Source for file oracle.php

Documentation is available at oracle.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Database
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. /**
  13.  * Oracle database driver
  14.  *
  15.  * @package     Joomla.Platform
  16.  * @subpackage  Database
  17.  * @see         http://php.net/pdo
  18.  * @since       12.1
  19.  */
  20. {
  21.     /**
  22.      * The name of the database driver.
  23.      *
  24.      * @var    string 
  25.      * @since  12.1
  26.      */
  27.     public $name = 'oracle';
  28.  
  29.     /**
  30.      * The character(s) used to quote SQL statement names such as table names or field names,
  31.      * etc.  The child classes should define this as necessary.  If a single character string the
  32.      * same character is used for both sides of the quoted name, else the first character will be
  33.      * used for the opening quote and the second for the closing quote.
  34.      *
  35.      * @var    string 
  36.      * @since  12.1
  37.      */
  38.     protected $nameQuote = '"';
  39.  
  40.     /**
  41.      * Returns the current dateformat
  42.      *
  43.      * @var   string 
  44.      * @since 12.1
  45.      */
  46.     protected $dateformat;
  47.  
  48.     /**
  49.      * Returns the current character set
  50.      *
  51.      * @var   string 
  52.      * @since 12.1
  53.      */
  54.     protected $charset;
  55.  
  56.     /**
  57.      * Constructor.
  58.      *
  59.      * @param   array  $options  List of options used to configure the connection
  60.      *
  61.      * @since   12.1
  62.      */
  63.     public function __construct($options)
  64.     {
  65.         $options['driver''oci';
  66.         $options['charset']    (isset($options['charset'])) $options['charset']   'AL32UTF8';
  67.         $options['dateformat'(isset($options['dateformat'])) $options['dateformat''RRRR-MM-DD HH24:MI:SS';
  68.  
  69.         $this->charset = $options['charset'];
  70.         $this->dateformat = $options['dateformat'];
  71.  
  72.         // Finalize initialisation
  73.         parent::__construct($options);
  74.     }
  75.  
  76.     /**
  77.      * Destructor.
  78.      *
  79.      * @since   12.1
  80.      */
  81.     public function __destruct()
  82.     {
  83.         $this->freeResult();
  84.         unset($this->connection);
  85.     }
  86.  
  87.     /**
  88.      * Connects to the database if needed.
  89.      *
  90.      * @return  void  Returns void if the database connected successfully.
  91.      *
  92.      * @since   12.1
  93.      * @throws  RuntimeException
  94.      */
  95.     public function connect()
  96.     {
  97.         if ($this->connection)
  98.         {
  99.             return;
  100.         }
  101.  
  102.         parent::connect();
  103.  
  104.         if (isset($this->options['schema']))
  105.         {
  106.             $this->setQuery('ALTER SESSION SET CURRENT_SCHEMA = ' $this->quoteName($this->options['schema']))->execute();
  107.         }
  108.  
  109.         $this->setDateFormat($this->dateformat);
  110.     }
  111.  
  112.     /**
  113.      * Disconnects the database.
  114.      *
  115.      * @return  void 
  116.      *
  117.      * @since   12.1
  118.      */
  119.     public function disconnect()
  120.     {
  121.         // Close the connection.
  122.         $this->freeResult();
  123.         unset($this->connection);
  124.     }
  125.  
  126.     /**
  127.      * Drops a table from the database.
  128.      *
  129.      * Note: The IF EXISTS flag is unused in the Oracle driver.
  130.      *
  131.      * @param   string   $tableName  The name of the database table to drop.
  132.      * @param   boolean  $ifExists   Optionally specify that the table must exist before it is dropped.
  133.      *
  134.      * @return  JDatabaseDriverOracle  Returns this object to support chaining.
  135.      *
  136.      * @since   12.1
  137.      */
  138.     public function dropTable($tableName$ifExists true)
  139.     {
  140.         $this->connect();
  141.  
  142.         $query $this->getQuery(true)
  143.             ->setQuery('DROP TABLE :tableName');
  144.         $query->bind(':tableName'$tableName);
  145.  
  146.         $this->setQuery($query);
  147.  
  148.         $this->execute();
  149.  
  150.         return $this;
  151.     }
  152.  
  153.     /**
  154.      * Method to get the database collation in use by sampling a text field of a table in the database.
  155.      *
  156.      * @return  mixed  The collation in use by the database or boolean false if not supported.
  157.      *
  158.      * @since   12.1
  159.      */
  160.     public function getCollation()
  161.     {
  162.         return $this->charset;
  163.     }
  164.  
  165.     /**
  166.      * Get a query to run and verify the database is operational.
  167.      *
  168.      * @return  string  The query to check the health of the DB.
  169.      *
  170.      * @since   12.2
  171.      */
  172.     public function getConnectedQuery()
  173.     {
  174.         return 'SELECT 1 FROM dual';
  175.     }
  176.  
  177.     /**
  178.      * Returns the current date format
  179.      * This method should be useful in the case that
  180.      * somebody actually wants to use a different
  181.      * date format and needs to check what the current
  182.      * one is to see if it needs to be changed.
  183.      *
  184.      * @return string The current date format
  185.      *
  186.      * @since 12.1
  187.      */
  188.     public function getDateFormat()
  189.     {
  190.         return $this->dateformat;
  191.     }
  192.  
  193.     /**
  194.      * Shows the table CREATE statement that creates the given tables.
  195.      *
  196.      * Note: You must have the correct privileges before this method
  197.      * will return usable results!
  198.      *
  199.      * @param   mixed  $tables  A table name or a list of table names.
  200.      *
  201.      * @return  array  A list of the create SQL for the tables.
  202.      *
  203.      * @since   12.1
  204.      * @throws  RuntimeException
  205.      */
  206.     public function getTableCreate($tables)
  207.     {
  208.         $this->connect();
  209.  
  210.         $result array();
  211.         $query $this->getQuery(true)
  212.             ->select('dbms_metadata.get_ddl(:type, :tableName)')
  213.             ->from('dual')
  214.             ->bind(':type''TABLE');
  215.  
  216.         // Sanitize input to an array and iterate over the list.
  217.         settype($tables'array');
  218.         foreach ($tables as $table)
  219.         {
  220.             $query->bind(':tableName'$table);
  221.             $this->setQuery($query);
  222.             $statement = (string) $this->loadResult();
  223.             $result[$table$statement;
  224.         }
  225.  
  226.         return $result;
  227.     }
  228.  
  229.     /**
  230.      * Retrieves field information about a given table.
  231.      *
  232.      * @param   string   $table     The name of the database table.
  233.      * @param   boolean  $typeOnly  True to only return field types.
  234.      *
  235.      * @return  array  An array of fields for the database table.
  236.      *
  237.      * @since   12.1
  238.      * @throws  RuntimeException
  239.      */
  240.     public function getTableColumns($table$typeOnly true)
  241.     {
  242.         $this->connect();
  243.  
  244.         $columns array();
  245.         $query $this->getQuery(true);
  246.  
  247.         $fieldCasing $this->getOption(PDO::ATTR_CASE);
  248.  
  249.         $this->setOption(PDO::ATTR_CASEPDO::CASE_UPPER);
  250.  
  251.         $table strtoupper($table);
  252.  
  253.         $query->select('*');
  254.         $query->from('ALL_TAB_COLUMNS');
  255.         $query->where('table_name = :tableName');
  256.  
  257.         $prefixedTable str_replace('#__'strtoupper($this->tablePrefix)$table);
  258.         $query->bind(':tableName'$prefixedTable);
  259.         $this->setQuery($query);
  260.         $fields $this->loadObjectList();
  261.  
  262.         if ($typeOnly)
  263.         {
  264.             foreach ($fields as $field)
  265.             {
  266.                 $columns[$field->COLUMN_NAME$field->DATA_TYPE;
  267.             }
  268.         }
  269.         else
  270.         {
  271.             foreach ($fields as $field)
  272.             {
  273.                 $columns[$field->COLUMN_NAME$field;
  274.                 $columns[$field->COLUMN_NAME]->Default null;
  275.             }
  276.         }
  277.  
  278.         $this->setOption(PDO::ATTR_CASE$fieldCasing);
  279.  
  280.         return $columns;
  281.     }
  282.  
  283.     /**
  284.      * Get the details list of keys for a table.
  285.      *
  286.      * @param   string  $table  The name of the table.
  287.      *
  288.      * @return  array  An array of the column specification for the table.
  289.      *
  290.      * @since   12.1
  291.      * @throws  RuntimeException
  292.      */
  293.     public function getTableKeys($table)
  294.     {
  295.         $this->connect();
  296.  
  297.         $query $this->getQuery(true);
  298.  
  299.         $fieldCasing $this->getOption(PDO::ATTR_CASE);
  300.  
  301.         $this->setOption(PDO::ATTR_CASEPDO::CASE_UPPER);
  302.  
  303.         $table strtoupper($table);
  304.         $query->select('*')
  305.             ->from('ALL_CONSTRAINTS')
  306.             ->where('table_name = :tableName')
  307.             ->bind(':tableName'$table);
  308.  
  309.         $this->setQuery($query);
  310.         $keys $this->loadObjectList();
  311.  
  312.         $this->setOption(PDO::ATTR_CASE$fieldCasing);
  313.  
  314.         return $keys;
  315.     }
  316.  
  317.     /**
  318.      * Method to get an array of all tables in the database (schema).
  319.      *
  320.      * @param   string   $databaseName         The database (schema) name
  321.      * @param   boolean  $includeDatabaseName  Whether to include the schema name in the results
  322.      *
  323.      * @return  array    An array of all the tables in the database.
  324.      *
  325.      * @since   12.1
  326.      * @throws  RuntimeException
  327.      */
  328.     public function getTableList($databaseName null$includeDatabaseName false)
  329.     {
  330.         $this->connect();
  331.  
  332.         $query $this->getQuery(true);
  333.  
  334.         if ($includeDatabaseName)
  335.         {
  336.             $query->select('owner, table_name');
  337.         }
  338.         else
  339.         {
  340.             $query->select('table_name');
  341.         }
  342.  
  343.         $query->from('all_tables');
  344.         if ($databaseName)
  345.         {
  346.             $query->where('owner = :database')
  347.                 ->bind(':database'$databaseName);
  348.         }
  349.  
  350.         $query->order('table_name');
  351.  
  352.         $this->setQuery($query);
  353.  
  354.         if ($includeDatabaseName)
  355.         {
  356.             $tables $this->loadAssocList();
  357.         }
  358.         else
  359.         {
  360.             $tables $this->loadColumn();
  361.         }
  362.  
  363.         return $tables;
  364.     }
  365.  
  366.     /**
  367.      * Get the version of the database connector.
  368.      *
  369.      * @return  string  The database connector version.
  370.      *
  371.      * @since   12.1
  372.      */
  373.     public function getVersion()
  374.     {
  375.         $this->connect();
  376.  
  377.         $this->setQuery("select value from nls_database_parameters where parameter = 'NLS_RDBMS_VERSION'");
  378.  
  379.         return $this->loadResult();
  380.     }
  381.  
  382.     /**
  383.      * Select a database for use.
  384.      *
  385.      * @param   string  $database  The name of the database to select for use.
  386.      *
  387.      * @return  boolean  True if the database was successfully selected.
  388.      *
  389.      * @since   12.1
  390.      * @throws  RuntimeException
  391.      */
  392.     public function select($database)
  393.     {
  394.         $this->connect();
  395.  
  396.         return true;
  397.     }
  398.  
  399.     /**
  400.      * Sets the Oracle Date Format for the session
  401.      * Default date format for Oracle is = DD-MON-RR
  402.      * The default date format for this driver is:
  403.      * 'RRRR-MM-DD HH24:MI:SS' since it is the format
  404.      * that matches the MySQL one used within most Joomla
  405.      * tables.
  406.      *
  407.      * @param   string  $dateFormat  Oracle Date Format String
  408.      *
  409.      * @return boolean 
  410.      *
  411.      * @since  12.1
  412.      */
  413.     public function setDateFormat($dateFormat 'DD-MON-RR')
  414.     {
  415.         $this->connect();
  416.  
  417.         $this->setQuery("ALTER SESSION SET NLS_DATE_FORMAT = '$dateFormat'");
  418.  
  419.         if (!$this->execute())
  420.         {
  421.             return false;
  422.         }
  423.  
  424.         $this->setQuery("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = '$dateFormat'");
  425.         if (!$this->execute())
  426.         {
  427.             return false;
  428.         }
  429.  
  430.         $this->dateformat = $dateFormat;
  431.  
  432.         return true;
  433.     }
  434.  
  435.     /**
  436.      * Set the connection to use UTF-8 character encoding.
  437.      *
  438.      * Returns false automatically for the Oracle driver since
  439.      * you can only set the character set when the connection
  440.      * is created.
  441.      *
  442.      * @return  boolean  True on success.
  443.      *
  444.      * @since   12.1
  445.      */
  446.     public function setUTF()
  447.     {
  448.         return false;
  449.     }
  450.  
  451.     /**
  452.      * Locks a table in the database.
  453.      *
  454.      * @param   string  $table  The name of the table to unlock.
  455.      *
  456.      * @return  JDatabaseDriverOracle  Returns this object to support chaining.
  457.      *
  458.      * @since   12.1
  459.      * @throws  RuntimeException
  460.      */
  461.     public function lockTable($table)
  462.     {
  463.         $this->setQuery('LOCK TABLE ' $this->quoteName($table' IN EXCLUSIVE MODE')->execute();
  464.  
  465.         return $this;
  466.     }
  467.  
  468.     /**
  469.      * Renames a table in the database.
  470.      *
  471.      * @param   string  $oldTable  The name of the table to be renamed
  472.      * @param   string  $newTable  The new name for the table.
  473.      * @param   string  $backup    Not used by Oracle.
  474.      * @param   string  $prefix    Not used by Oracle.
  475.      *
  476.      * @return  JDatabaseDriverOracle  Returns this object to support chaining.
  477.      *
  478.      * @since   12.1
  479.      * @throws  RuntimeException
  480.      */
  481.     public function renameTable($oldTable$newTable$backup null$prefix null)
  482.     {
  483.         $this->setQuery('RENAME ' $oldTable ' TO ' $newTable)->execute();
  484.  
  485.         return $this;
  486.     }
  487.  
  488.     /**
  489.      * Unlocks tables in the database.
  490.      *
  491.      * @return  JDatabaseDriverOracle  Returns this object to support chaining.
  492.      *
  493.      * @since   12.1
  494.      * @throws  RuntimeException
  495.      */
  496.     public function unlockTables()
  497.     {
  498.         $this->setQuery('COMMIT')->execute();
  499.  
  500.         return $this;
  501.     }
  502.  
  503.     /**
  504.      * Test to see if the PDO ODBC connector is available.
  505.      *
  506.      * @return  boolean  True on success, false otherwise.
  507.      *
  508.      * @since   12.1
  509.      */
  510.     public static function isSupported()
  511.     {
  512.         return class_exists('PDO'&& in_array('oci'PDO::getAvailableDrivers());
  513.     }
  514.  
  515.     /**
  516.      * This function replaces a string identifier <var>$prefix</var> with the string held is the
  517.      * <var>tablePrefix</var> class variable.
  518.      *
  519.      * @param   string  $query   The SQL statement to prepare.
  520.      * @param   string  $prefix  The common table prefix.
  521.      *
  522.      * @return  string  The processed SQL statement.
  523.      *
  524.      * @since   11.1
  525.      */
  526.     public function replacePrefix($query$prefix '#__')
  527.     {
  528.         $startPos 0;
  529.         $quoteChar "'";
  530.         $literal '';
  531.  
  532.         $query trim($query);
  533.         $n strlen($query);
  534.  
  535.         while ($startPos $n)
  536.         {
  537.             $ip strpos($query$prefix$startPos);
  538.             if ($ip === false)
  539.             {
  540.                 break;
  541.             }
  542.  
  543.             $j strpos($query"'"$startPos);
  544.  
  545.             if ($j === false)
  546.             {
  547.                 $j $n;
  548.             }
  549.  
  550.             $literal .= str_replace($prefix$this->tablePrefixsubstr($query$startPos$j $startPos));
  551.             $startPos $j;
  552.  
  553.             $j $startPos 1;
  554.  
  555.             if ($j >= $n)
  556.             {
  557.                 break;
  558.             }
  559.  
  560.             // Quote comes first, find end of quote
  561.             while (true)
  562.             {
  563.                 $k strpos($query$quoteChar$j);
  564.                 $escaped false;
  565.                 if ($k === false)
  566.                 {
  567.                     break;
  568.                 }
  569.                 $l $k 1;
  570.                 while ($l >= && $query{$l== '\\')
  571.                 {
  572.                     $l--;
  573.                     $escaped !$escaped;
  574.                 }
  575.                 if ($escaped)
  576.                 {
  577.                     $j $k 1;
  578.                     continue;
  579.                 }
  580.                 break;
  581.             }
  582.             if ($k === false)
  583.             {
  584.                 // Error in the query - no end quote; ignore it
  585.                 break;
  586.             }
  587.             $literal .= substr($query$startPos$k $startPos 1);
  588.             $startPos $k 1;
  589.         }
  590.         if ($startPos $n)
  591.         {
  592.             $literal .= substr($query$startPos$n $startPos);
  593.         }
  594.  
  595.         return $literal;
  596.     }
  597.  
  598.     /**
  599.      * Method to commit a transaction.
  600.      *
  601.      * @param   boolean  $toSavepoint  If true, commit to the last savepoint.
  602.      *
  603.      * @return  void 
  604.      *
  605.      * @since   12.3
  606.      * @throws  RuntimeException
  607.      */
  608.     public function transactionCommit($toSavepoint false)
  609.     {
  610.         $this->connect();
  611.  
  612.         if (!$toSavepoint || $this->transactionDepth <= 1)
  613.         {
  614.             parent::transactionCommit($toSavepoint);
  615.         }
  616.         else
  617.         {
  618.             $this->transactionDepth--;
  619.         }
  620.     }
  621.  
  622.     /**
  623.      * Method to roll back a transaction.
  624.      *
  625.      * @param   boolean  $toSavepoint  If true, rollback to the last savepoint.
  626.      *
  627.      * @return  void 
  628.      *
  629.      * @since   12.3
  630.      * @throws  RuntimeException
  631.      */
  632.     public function transactionRollback($toSavepoint false)
  633.     {
  634.         $this->connect();
  635.  
  636.         if (!$toSavepoint || $this->transactionDepth <= 1)
  637.         {
  638.             parent::transactionRollback($toSavepoint);
  639.         }
  640.         else
  641.         {
  642.             $savepoint 'SP_' ($this->transactionDepth - 1);
  643.             $this->setQuery('ROLLBACK TO SAVEPOINT ' $this->quoteName($savepoint));
  644.  
  645.             if ($this->execute())
  646.             {
  647.                 $this->transactionDepth--;
  648.             }
  649.         }
  650.     }
  651.  
  652.     /**
  653.      * Method to initialize a transaction.
  654.      *
  655.      * @param   boolean  $asSavepoint  If true and a transaction is already active, a savepoint will be created.
  656.      *
  657.      * @return  void 
  658.      *
  659.      * @since   12.3
  660.      * @throws  RuntimeException
  661.      */
  662.     public function transactionStart($asSavepoint false)
  663.     {
  664.         $this->connect();
  665.  
  666.         if (!$asSavepoint || !$this->transactionDepth)
  667.         {
  668.             return parent::transactionStart($asSavepoint);
  669.         }
  670.  
  671.         $savepoint 'SP_' $this->transactionDepth;
  672.         $this->setQuery('SAVEPOINT ' $this->quoteName($savepoint));
  673.  
  674.         if ($this->execute())
  675.         {
  676.             $this->transactionDepth++;
  677.         }
  678.     }
  679. }

Documentation generated on Tue, 19 Nov 2013 15:09:51 +0100 by phpDocumentor 1.4.3