From 016aff1b2929da5de846768ad2a65a7343071fc3 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Fri, 14 May 2010 18:37:06 +0200 Subject: [PATCH] Basic Oracle support --- adminer/drivers/oracle.inc.php | 334 ++++++++++++++++++++++++++++++ adminer/drivers/pgsql.inc.php | 1 - adminer/include/bootstrap.inc.php | 1 + changes.txt | 2 +- 4 files changed, 336 insertions(+), 2 deletions(-) create mode 100644 adminer/drivers/oracle.inc.php diff --git a/adminer/drivers/oracle.inc.php b/adminer/drivers/oracle.inc.php new file mode 100644 index 00000000..823dce41 --- /dev/null +++ b/adminer/drivers/oracle.inc.php @@ -0,0 +1,334 @@ +error = $error; + } + + function connect($server, $username, $password) { + $this->_link = @oci_new_connect($username, $password, $server); //! AL32UTF8 + if ($this->_link) { + $this->server_info = oci_server_version($this->_link); + return true; + } + $error = oci_error(); + $this->error = $error["message"]; + return false; + } + + function quote($string) { + return "'" . str_replace("'", "''", $string) . "'"; + } + + function select_db($database) { + return true; + } + + function query($query, $unbuffered = false) { + $result = oci_parse($this->_link, $query); + if (!$result) { + $error = oci_error($this->_link); + $this->error = $error["message"]; + return false; + } + set_error_handler(array($this, '_error')); + $return = @oci_execute($result); + restore_error_handler(); + if ($return) { + if (oci_num_fields($result)) { + return new Min_Result($result); + } + $this->affected_rows = oci_num_rows($result); + } + return $return; + } + + function multi_query($query) { + return $this->_result = $this->query($query); + } + + function store_result() { + return $this->_result; + } + + function next_result() { + return false; + } + + function result($query, $field = 1) { + $result = $this->query($query); + if (!is_object($result) || !oci_fetch($result->_result)) { + return false; + } + return oci_result($result->_result, $field); + } + } + + class Min_Result { + var $_result, $_offset = 1, $num_rows; + + function Min_Result($result) { + $this->_result = $result; + $this->num_rows = -1; // all results unbuffered + } + + function fetch_assoc() { + return oci_fetch_assoc($this->_result); + } + + function fetch_row() { + return oci_fetch_row($this->_result); + } + + function fetch_field() { + $column = $this->_offset++; + $return = new stdClass; + $return->name = oci_field_name($this->_result, $column); + $return->orgname = $return->name; + $return->type = oci_field_type($this->_result, $column); + $return->charsetnr = (ereg("raw|blob|bfile", $return->type) ? 63 : 0); // 63 - binary + return $return; + } + + function __destruct() { + oci_free_statement($this->_result); + } + } + + } elseif (extension_loaded("pdo_oci")) { + class Min_DB extends Min_PDO { + var $extension = "PDO_OCI"; + + function connect($server, $username, $password) { + } + + function select_db($database) { + } + } + + } + + function idf_escape($idf) { + return '"' . str_replace('"', '""', $idf) . '"'; + } + + function table($idf) { + return idf_escape($idf); + } + + function connect() { + global $adminer; + $connection = new Min_DB; + $credentials = $adminer->credentials(); + if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) { + return $connection; + } + return $connection->error; + } + + function get_databases() { + return get_vals("SELECT tablespace_name FROM user_tablespaces"); + } + + function limit($query, $where, $limit, $offset = 0, $separator = " ") { + return " $query$where" . (isset($limit) ? ($where ? " AND" : $separator . "WHERE") . ($offset ? " rownum > $offset AND" : "") . " rownum <= " . ($limit + $offset) : ""); + } + + function limit1($query, $where) { + return " $query$where"; + } + + function db_collation($db, $collations) { + //! + } + + function engines() { + return array(); + } + + function logged_user() { + global $connection; + return $connection->result("SELECT USER FROM DUAL"); + } + + function tables_list() { + global $connection; + return get_key_vals("SELECT table_name FROM all_tables WHERE tablespace_name = " . $connection->quote(DB)); //! views + } + + function count_tables($databases) { + return array(); + } + + function table_status($name = "") { + global $connection; + $return = array(); + $result = $connection->query('SELECT table_name "Name" FROM all_tables' . ($name != "" ? ' WHERE table_name = ' . $connection->quote($name) : '')); + while ($row = $result->fetch_assoc()) { + if ($name != "") { + return $row; + } + $return[$row["Name"]] = $row; + } + return $return; + } + + function fk_support($table_status) { + return true; + } + + function fields($table) { + global $connection; + $return = array(); + $result = $connection->query("SELECT * FROM all_tab_columns WHERE table_name = " . $connection->quote($table) . " ORDER BY column_id"); + if ($result) { + while ($row = $result->fetch_assoc()) { + $type = $row["DATA_TYPE"]; + $length = "$row[DATA_PRECISION],$row[DATA_SCALE]"; + if ($length == ",") { + $length = $row["DATA_LENGTH"]; + } //! int + $return[$row["COLUMN_NAME"]] = array( + "field" => $row["COLUMN_NAME"], + "full_type" => $type . ($length ? "($length)" : ""), + "type" => $type, + "length" => $length, + "default" => $row["DATA_DEFAULT"], + "null" => ($row["NULLABLE"] == "Y"), + //! "auto_increment" => false, + "collation" => $row["CHARACTER_SET_NAME"], + "privileges" => array("insert" => 1, "select" => 1, "update" => 1), + //! "comment" => $row["Comment"], + //! "primary" => ($row["Key"] == "PRI"), + ); + } + } + return $return; + } + + function indexes($table, $connection2 = null) { + return array(); //! + } + + function collations() { + return array(); //! + } + + function information_schema($db) { + return false; + } + + function error() { + global $connection; + return h($connection->error); //! highlight sqltext from offset + } + + function exact_value($val) { + global $connection; + return $connection->quote($val); + } + + function explain($connection, $query) { + //! + } + + function foreign_keys($table) { + return array(); //! + } + + function truncate_tables($tables) { + foreach ($tables as $table) { + if (!queries("TRUNCATE TABLE " . table($table))) { + return false; + } + } + return true; + } + + function drop_views($views) { + foreach ($views as $table) { + if (!queries("DROP VIEW " . table($table))) { + return false; + } + } + return true; + } + + function drop_tables($tables) { + foreach ($tables as $table) { + if (!queries("DROP TABLE " . table($table))) { + return false; + } + } + return true; + } + + function begin() { + return true; // automatic start + } + + function insert_into($table, $set) { + return queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")"); //! no columns + } + + function last_id() { + return 0; //! + } + + function schemas() { + return array(); + } + + function get_schema() { + return ""; + } + + function set_schema($scheme) { + return true; + } + + function support($feature) { + return false; //! + } + + $jush = "oracle"; + $types = array(); + $structured_types = array(); + foreach (array( + lang('Numbers') => array("number" => 38, "binary_float" => 12, "binary_double" => 21), + lang('Date and time') => array("date" => 10, "timestamp" => 29, "interval year to month" => 12, "interval day to second" => 28), //! year(), day() to second() + lang('Strings') => array("char" => 2000, "varchar2" => 4000, "nchar" => 2000, "nvarchar2" => 4000, "clob" => 4294967295, "nclob" => 4294967295), + lang('Binary') => array("raw" => 2000, "long raw" => 2147483648, "blob" => 4294967295, "bfile" => 4294967296), + ) as $key => $val) { + $types += $val; + $structured_types[$key] = array_keys($val); + } + $unsigned = array(); + $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL"); + $functions = array("length", "lower", "round", "upper"); + $grouping = array("avg", "count", "count distinct", "max", "min", "sum"); + $edit_functions = array( + array( //! no parentheses + "date" => "current_date", + "timestamp" => "current_timestamp", + ), array( + "number|float|double" => "+/-", + "date|timestamp" => "+ interval/- interval", + "char|clob" => "||", + ) + ); +} diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index 48fcca3c..25d7f859 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -233,7 +233,6 @@ AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema( "default" => $row["column_default"], "null" => ($row["is_nullable"] == "YES"), "auto_increment" => eregi("^nextval\\(", $row["column_default"]), - "on_update" => "", //! "collation" => $row["collation_name"], "privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable "primary" => false, //! diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index 608e1b5f..f43fbee9 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -62,6 +62,7 @@ include "../adminer/lang/$LANG.inc.php"; include "../adminer/include/pdo.inc.php"; include "../adminer/drivers/sqlite.inc.php"; include "../adminer/drivers/pgsql.inc.php"; +include "../adminer/drivers/oracle.inc.php"; include "../adminer/drivers/mssql.inc.php"; include "../adminer/drivers/mysql.inc.php"; // must be included as last driver diff --git a/changes.txt b/changes.txt index c7d02cdb..af3676ac 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,5 @@ Adminer 3.0.0-dev: -Drivers for MS SQL, SQLite, PostgreSQL +Drivers for MS SQL, SQLite, PostgreSQL, Oracle Allow concurrent logins on the same server Allow permanent login without customization In-place editation in select