From c217eadef413780a8b7cd5dd3cdcc6bf4c0c8985 Mon Sep 17 00:00:00 2001 From: juanmanuelr Date: Thu, 31 Mar 2011 13:46:34 +0000 Subject: [PATCH] 2011-03-31 Juan Manuel Ramon * include/db/oracle.php: Added new functions for Oracle support. include/functions_db.php: Added conditional code for Oracle engine. * pandoradb.oracle.sql: Added new db procedure "insert_id" to retrieve PK when insert is performed. git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@4156 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f --- pandora_console/ChangeLog | 7 + pandora_console/include/db/oracle.php | 1281 ++++++++++++++++++++++ pandora_console/include/functions_db.php | 149 ++- pandora_console/pandoradb.oracle.sql | 16 +- 4 files changed, 1443 insertions(+), 10 deletions(-) create mode 100644 pandora_console/include/db/oracle.php diff --git a/pandora_console/ChangeLog b/pandora_console/ChangeLog index d94c153644..905f1af342 100644 --- a/pandora_console/ChangeLog +++ b/pandora_console/ChangeLog @@ -1,3 +1,10 @@ +2011-03-31 Juan Manuel Ramon + + * include/db/oracle.php: Added new functions for Oracle support. + include/functions_db.php: Added conditional code for Oracle engine. + * pandoradb.oracle.sql: Added new db procedure "insert_id" to + retrieve PK when insert is performed. + 2011-03-31 Sergio Martin * include/graphs/pChart/pDraw.class.php: Added to diff --git a/pandora_console/include/db/oracle.php b/pandora_console/include/db/oracle.php new file mode 100644 index 0000000000..f3cc157e7b --- /dev/null +++ b/pandora_console/include/db/oracle.php @@ -0,0 +1,1281 @@ +%s on line %d', + htmlentities($e['message'], ENT_QUOTES), $sql, $backtrace[0]['file'], $backtrace[0]['line']); + add_database_debug_trace ($sql, htmlentities($e['message'], ENT_QUOTES)); + set_error_handler ('sql_error_handler'); + trigger_error ($error); + restore_error_handler (); + + return false; + } + else { + $status = oci_statement_type($query); + $rows = oci_num_rows($query); + + if ($status !== 'SELECT') { //The query NOT IS a select + if ($rettype == "insert_id") { + $result = $id; + } + elseif ($rettype == "info") { + //TODO: return debug information of the query $result = pg_result_status($result, PGSQL_STATUS_STRING); + $result = ''; + } + else { + $result = $rows; + } + add_database_debug_trace ($sql, $result, $rows, + array ('time' => $time)); + + return $result; + } + else { //The query IS a select. + add_database_debug_trace ($sql, 0, $rows, array ('time' => $time)); + while ($row = oci_fetch_assoc($query)) { + array_push($retval, $row); + } + + if ($cache === true) + $sql_cache[$sql] = $retval; + oci_free_statement ($query); + } + } + } + + if (! empty ($retval)) { + return $retval; + } + + //Return false, check with === or !== + return false; +} + +/** + * Get all the rows in a table of the database. + * + * @param string Database table name. + * @param string Field to order by. + * @param string $order The type of order, by default 'ASC'. + * + * @return mixed A matrix with all the values in the table + */ +function oracle_get_db_all_rows_in_table($table, $order_field = "", $order = 'ASC') { + if ($order_field != "") { + return get_db_all_rows_sql ('SELECT * FROM ' . $table . ' ORDER BY ' . $order_field . ' ' . $order); + } + else { + return get_db_all_rows_sql ('SELECT * FROM ' . $table); + } +} + +/** + * Inserts strings into database + * + * The number of values should be the same or a positive integer multiple as the number of rows + * If you have an associate array (eg. array ("row1" => "value1")) you can use this function with ($table, array_keys ($array), $array) in it's options + * All arrays and values should have been cleaned before passing. It's not neccessary to add quotes. + * + * @param string Table to insert into + * @param mixed A single value or array of values to insert (can be a multiple amount of rows) + * + * @return mixed False in case of error or invalid values passed. Affected rows otherwise + */ +function oracle_process_sql_insert($table, $values) { + //Empty rows or values not processed + if (empty ($values)) + return false; + + $values = (array) $values; + + $query = sprintf ('INSERT INTO %s ', $table); + $fields = array (); + $values_str = ''; + $i = 1; + $max = count ($values); + foreach ($values as $field => $value) { + array_push ($fields, $field); + + if (is_null ($value)) { + $values_str .= "NULL"; + } + elseif (is_int ($value) || is_bool ($value)) { + $values_str .= sprintf("%d", $value); + } + else if (is_float ($value) || is_double ($value)) { + $values_str .= sprintf("%f", $value); + } + else { + $values_str .= sprintf("'%s'", $value); + } + + if ($i < $max) { + $values_str .= ","; + } + $i++; + } + + $query .= '(' . implode(', ', $fields) . ')'; + + $query .= ' VALUES (' . $values_str . ')'; + + return process_sql($query, 'insert_id'); +} + +/** + * Escape string to set it properly to use in sql queries + * + * @param string String to be cleaned. + * + * @return string String cleaned. + */ +function oracle_escape_string_sql($string) { + return str_replace(array('"', "'", '\\'), array('\\"', '\\\'', '\\\\'), $string); +} + +/** + * Get the first value of the first row of a table in the database from an + * array with filter conditions. + * + * Example: + + get_db_value_filter ('name', 'talert_templates', + array ('value' => 2, 'type' => 'equal')); + // Equivalent to: + // SELECT name FROM talert_templates WHERE value = 2 AND type = 'equal' LIMIT 1 + // In oracle sintax: + // SELECT name FROM talert_templates WHERE value = 2 AND type = 'equal' AND rownum < 2 + + get_db_value_filter ('description', 'talert_templates', + array ('name' => 'My alert', 'type' => 'regex'), 'OR'); + // Equivalent to: + // SELECT description FROM talert_templates WHERE name = 'My alert' OR type = 'equal' LIMIT 1 + // In oracle sintax: + // SELECT description FROM talert_templates WHERE name = 'My alert' OR type = 'equal' AND rownum < 2 + + * + * @param string Field name to get + * @param string Table to retrieve the data + * @param array Conditions to filter the element. See format_array_to_where_clause_sql() + * for the format + * @param string Join operator for the elements in the filter. + * + * @return mixed Value of first column of the first row. False if there were no row. + */ +function oracle_get_db_value_filter ($field, $table, $filter, $where_join = 'AND') { + if (! is_array ($filter) || empty ($filter)) + return false; + + /* Avoid limit and offset if given */ + unset ($filter['limit']); + unset ($filter['offset']); + + $sql = sprintf ("SELECT %s FROM %s WHERE %s AND rownum < 2", + $field, $table, + format_array_to_where_clause_sql ($filter, $where_join)); + + $result = get_db_all_rows_sql ($sql); + + if ($result === false) + return false; + + $fieldClean = strtoupper(str_replace('`', '', $field)); + + return $result[0][$fieldClean]; +} + +/** + * Formats an array of values into a SQL where clause string. + * + * This function is useful to generate a WHERE clause for a SQL sentence from + * a list of values. Example code: + + $values = array (); + $values['name'] = "Name"; + $values['description'] = "Long description"; + $values['limit'] = $config['block_size']; // Assume it's 20 + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values); + echo $sql; + + * Will return: + * + * SELECT * FROM table WHERE `name` = "Name" AND `description` = "Long description" LIMIT 20 + * This in Oracle Sql sintaxis is translate to: + * SELECT * FROM table WHERE name = "Name" AND description = "Long description" AND rownum <= 20 + * + * + * @param array Values to be formatted in an array indexed by the field name. + * There are special parameters such as 'order' and 'limit' that will be used + * as ORDER and LIMIT clauses respectively. Since LIMIT is + * numeric, ORDER can receive a field name or a SQL function and a the ASC or + * DESC clause. Examples: + + $values = array (); + $values['value'] = 10; + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values); + // SELECT * FROM table WHERE VALUE = 10 + + $values = array (); + $values['value'] = 10; + $values['order'] = 'name DESC'; + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values); + // SELECT * FROM table WHERE VALUE = 10 ORDER BY name DESC + + + IMPORTANT!!! OFFSET is not allowed in this function because Oracle needs to recode the complete query. + use oracle_recode_query() function instead + * + * @return string Values joined into an SQL string that can fits into the WHERE + * clause of an SQL sentence. + */ +function oracle_format_array_to_where_clause_sql ($values, $join = 'AND', $prefix = false) { + + $fields = array (); + + if (! is_array ($values)) { + return ''; + } + + $query = ''; + $limit = ''; + $order = ''; + $group = ''; + if (isset($values['offset'])) { + return ''; + } + + if (isset ($values['limit'])) { + $limit = sprintf (' AND rownum <= %d', $values['limit']); + unset ($values['limit']); + } + + if (isset ($values['order'])) { + if (is_array($values['order'])) { + if (!isset($values['order']['order'])) { + $orderTexts = array(); + foreach ($values['order'] as $orderItem) { + $orderTexts[] = $orderItem['field'] . ' ' . $orderItem['order']; + } + $order = ' ORDER BY ' . implode(', ', $orderTexts); + } + else { + $order = sprintf (' ORDER BY %s %s', $values['order']['field'], $values['order']['order']); + } + } + else { + $order = sprintf (' ORDER BY %s', $values['order']); + } + unset ($values['order']); + } + + if (isset ($values['group'])) { + $group = sprintf (' GROUP BY %s', $values['group']); + unset ($values['group']); + } + + $i = 1; + $max = count ($values); + foreach ($values as $field => $value) { + if ($i == 1) { + $query .= ' ( '; + } + + if (is_numeric ($field)) { + /* User provide the exact operation to do */ + $query .= $value; + + if ($i < $max) { + $query .= ' '.$join.' '; + } + $i++; + continue; + } + + if (is_null ($value)) { + $query .= sprintf ("%s IS NULL", $field); + } + elseif (is_int ($value) || is_bool ($value)) { + $query .= sprintf ("%s = %d", $field, $value); + } + else if (is_float ($value) || is_double ($value)) { + $query .= sprintf ("%s = %f", $field, $value); + } + elseif (is_array ($value)) { + $query .= sprintf ("%s IN ('%s')", $field, implode ("', '", $value)); + } + else { + if ($value[0] == ">"){ + $value = substr($value,1,strlen($value)-1); + $query .= sprintf ("%s > '%s'", $field, $value); + } + else if ($value[0] == "<"){ + if ($value[1] == ">"){ + $value = substr($value,2,strlen($value)-2); + $query .= sprintf ("%s <> '%s'", $field, $value); + } + else { + $value = substr($value,1,strlen($value)-1); + $query .= sprintf ("%s < '%s'", $field, $value); + } + } + else if ($value[0] == '%') { + $query .= sprintf ("%s LIKE '%s'", $field, $value); + } + else { + $query .= sprintf ("%s = '%s'", $field, $value); + } + } + + if ($i < $max) { + $query .= ' '.$join.' '; + } + if ($i == $max) { + $query .= ' ) '; + } + $i++; + } + + return (! empty ($query) ? $prefix: '').$query.$limit.$group.$order; +} + +/** + * Formats an SQL query to use LIMIT and OFFSET Mysql like statements in Oracle. + * + * This function is useful to generate an SQL sentence from + * a list of values. Example code: + + * @param string Join operator. AND by default. + * @param string A prefix to be added to the string. It's useful when + * offset could be given to avoid this cases: + + $values = array (); + $values['limit'] = 10; + $values['offset'] = 20; + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values); + // Wrong SQL: SELECT * FROM table WHERE LIMIT 10 OFFSET 20 + + $values = array (); + $values['limit'] = 10; + $values['offset'] = 20; + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values, 'AND', 'WHERE'); + // Good SQL: SELECT * FROM table LIMIT 10 OFFSET 20 + // This in Oracle Sql sintaxis is translate to: + // SELECT * FROM (SELECT ROWNUM AS rnum, a.* FROM (SELECT * FROM table) a) WHERE rnum > 20 AND rnum <= 30 + + $values = array (); + $values['value'] = 5; + $values['limit'] = 10; + $values['offset'] = 20; + $sql = 'SELECT * FROM table WHERE '.format_array_to_where_clause_sql ($values, 'AND', 'WHERE'); + // Good SQL: SELECT * FROM table WHERE value = 5 LIMIT 10 OFFSET 20 + // This in Oracle Sql sintaxis is translate to: + // SELECT * FROM (SELECT ROWNUM AS rnum, a.* FROM (SELECT * FROM table WHERE value = 5) a) WHERE rnum > 20 AND rnum <= 30; + + + * @param string Sql from SELECT to WHERE reserved words: SELECT * FROM mytable WHERE + * @param array Conditions to filter the element. See format_array_to_where_clause_sql() + * for the format. LIMIT + OFFSET are allowed in this function: + + + $values = array(); + $values['limit'] = x; + $values['offset'] = y; + + + * @param string Join operator for the elements in the filter. + * @param bool Whether to return Sql or execute. Note that if you return data in a string format then after execute the query you have + * to discard RNUM column. + * + * @return string Values joined into an SQL string that fits Oracle SQL sintax + * clause of an SQL sentence. + **/ +function oracle_recode_query ($sql, $values, $join = 'AND', $return = true) { + + $fields = array (); + + if (! is_array ($values) || empty($sql)) { + return ''; + } + + $query = ''; + $limit = ''; + $offset = ''; + $order = ''; + $group = ''; + $pre_query = ''; + $post_query = ''; + // LIMIT + OFFSET options have to be recoded into a subquery + if (isset ($values['limit']) && isset($values['offset'])) { + $down = $values['offset']; + $top = $values['offset'] + $values['limit']; + $pre_query = 'SELECT * FROM (SELECT ROWNUM AS rnum, a.* FROM ('; + $post_query = sprintf(") a) WHERE rnum > %d AND rnum <= %d", $down, $top); + unset ($values['limit']); + unset ($values['offset']); + } + else if (isset ($values['limit'])) { + $limit = sprintf (' AND rownum <= %d', $values['limit']); + unset ($values['limit']); + } + // OFFSET without LIMIT option is not supported + else if (isset ($values['offset'])) { + unset ($values['offset']); + } + + if (isset ($values['order'])) { + if (is_array($values['order'])) { + if (!isset($values['order']['order'])) { + $orderTexts = array(); + foreach ($values['order'] as $orderItem) { + $orderTexts[] = $orderItem['field'] . ' ' . $orderItem['order']; + } + $order = ' ORDER BY ' . implode(', ', $orderTexts); + } + else { + $order = sprintf (' ORDER BY %s %s', $values['order']['field'], $values['order']['order']); + } + } + else { + $order = sprintf (' ORDER BY %s', $values['order']); + } + unset ($values['order']); + } + + if (isset ($values['group'])) { + $group = sprintf (' GROUP BY %s', $values['group']); + unset ($values['group']); + } + + $i = 1; + $max = count ($values); + foreach ($values as $field => $value) { + if ($i == 1) { + $query .= ' ( '; + } + + if (is_numeric ($field)) { + /* User provide the exact operation to do */ + $query .= $value; + + if ($i < $max) { + $query .= ' '.$join.' '; + } + $i++; + continue; + } + + if (is_null ($value)) { + $query .= sprintf ("%s IS NULL", $field); + } + elseif (is_int ($value) || is_bool ($value)) { + $query .= sprintf ("%s = %d", $field, $value); + } + else if (is_float ($value) || is_double ($value)) { + $query .= sprintf ("%s = %f", $field, $value); + } + elseif (is_array ($value)) { + $query .= sprintf ("%s IN ('%s')", $field, implode ("', '", $value)); + } + else { + if ($value[0] == ">"){ + $value = substr($value,1,strlen($value)-1); + $query .= sprintf ("%s > '%s'", $field, $value); + } + else if ($value[0] == "<"){ + if ($value[1] == ">"){ + $value = substr($value,2,strlen($value)-2); + $query .= sprintf ("%s <> '%s'", $field, $value); + } + else { + $value = substr($value,1,strlen($value)-1); + $query .= sprintf ("%s < '%s'", $field, $value); + } + } + else if ($value[0] == '%') { + $query .= sprintf ("%s LIKE '%s'", $field, $value); + } + else { + $query .= sprintf ("%s = '%s'", $field, $value); + } + } + + if ($i < $max) { + $query .= ' '.$join.' '; + } + if ($i == $max) { + $query .= ' ) '; + } + $i++; + } + + $result = $pre_query.$sql.$query.$limit.$group.$order.$post_query; + + if ($return){ + return $result; + } + else{ + $result = oracle_process_sql($result); + for ($i=0; $i < count($result); $i++) { + unset($result[$i]['RNUM']); + } + return $result; + } +} + +/** + * Get the first value of the first row of a table result from query. + * + * @param string SQL select statement to execute. + * + * @return the first value of the first row of a table result from query. + * + */ +function oracle_get_db_value_sql($sql) { + $sql = "SELECT * FROM (" . $sql . ") WHERE rownum < 2"; + $result = get_db_all_rows_sql ($sql); + + if($result === false) + return false; + + foreach ($result[0] as $f) + return $f; +} + +/** + * Get the first row of an SQL database query. + * + * @param string SQL select statement to execute. + * + * @return mixed The first row of the result or false + */ +function oracle_get_db_row_sql ($sql, $search_history_db = false) { + $sql .= "SELECT * FROM (" . $sql . ") WHERE rownum < 2"; + $result = get_db_all_rows_sql($sql, $search_history_db); + + if($result === false) + return false; + + return $result[0]; +} + +/** + * Get the row of a table in the database using a complex filter. + * + * @param string Table to retrieve the data (warning: not cleaned) + * @param mixed Filters elements. It can be an indexed array + * (keys would be the field name and value the expected value, and would be + * joined with an AND operator) or a string, including any SQL clause (without + * the WHERE keyword). Example: + + Both are similars: + get_db_row_filter ('table', array ('disabled', 0)); + get_db_row_filter ('table', 'disabled = 0'); + + Both are similars: + get_db_row_filter ('table', array ('disabled' => 0, 'history_data' => 0), 'name, description', 'OR'); + get_db_row_filter ('table', 'disabled = 0 OR history_data = 0', 'name, description'); + get_db_row_filter ('table', array ('disabled' => 0, 'history_data' => 0), array ('name', 'description'), 'OR'); + + * @param mixed Fields of the table to retrieve. Can be an array or a coma + * separated string. All fields are retrieved by default + * @param string Condition to join the filters (AND, OR). + * + * @return mixed Array of the row or false in case of error. + */ +function oracle_get_db_row_filter ($table, $filter, $fields = false, $where_join = 'AND') { + if (empty ($fields)) { + $fields = '*'; + } + else { + if (is_array ($fields)) + $fields = implode (',', $fields); + else if (! is_string ($fields)) + return false; + } + + if (is_array ($filter)) + $filter = format_array_to_where_clause_sql ($filter, $where_join, ' WHERE '); + else if (is_string ($filter)) + $filter = 'WHERE '.$filter; + else + $filter = ''; + + $sql = sprintf ('SELECT %s FROM %s %s', $fields, $table, $filter); + + return get_db_row_sql ($sql); +} + +/** + * Get all the rows of a table in the database that matches a filter. + * + * @param string Table to retrieve the data (warning: not cleaned) + * @param mixed Filters elements. It can be an indexed array + * (keys would be the field name and value the expected value, and would be + * joined with an AND operator) or a string, including any SQL clause (without + * the WHERE keyword). Example: + * + * Both are similars: + * get_db_all_rows_filter ('table', array ('disabled', 0)); + * get_db_all_rows_filter ('table', 'disabled = 0'); + * + * Both are similars: + * get_db_all_rows_filter ('table', array ('disabled' => 0, 'history_data' => 0), 'name', 'OR'); + * get_db_all_rows_filter ('table', 'disabled = 0 OR history_data = 0', 'name'); + * + * @param mixed Fields of the table to retrieve. Can be an array or a coma + * separated string. All fields are retrieved by default + * @param string Condition of the filter (AND, OR). + * @param bool $returnSQL Return a string with SQL instead the data, by default false. + * + * @return mixed Array of the row or false in case of error. + */ +function oracle_get_db_all_rows_filter ($table, $filter = array(), $fields = false, $where_join = 'AND', $search_history_db = false, $returnSQL = false) { + //TODO: Validate and clean fields + if (empty($fields)) { + $fields = '*'; + } + elseif (is_array($fields)) { + $fields = implode(' , ', $fields) ; + } + elseif (!is_string($fields)) { + return false; + } + + //TODO: Validate and clean filter options + if (is_array ($filter)) { + $filter = format_array_to_where_clause_sql ($filter, $where_join, ' WHERE '); + } + elseif (is_string ($filter)) { + $filter = 'WHERE '.$filter; + } + else { + $filter = ''; + } + + $sql = sprintf ('SELECT %s FROM %s %s', $fields, $table, $filter); + + if ($returnSQL) + return $sql; + else + return get_db_all_rows_sql ($sql, $search_history_db); +} + +/** + * Return the count of rows of query. + * + * @param $sql + * @return integer The count of rows of query. + */ +function oracle_get_db_num_rows ($sql) { + global $config; + + $type = explode(' ',strtoupper(trim($sql))); + if ($type[0] == 'SELECT'){ + $sql = "SELECT count(*) as NUM FROM (" . $sql . ")"; + } + $query = oci_parse($config['dbconnection'], $sql); + oci_execute($query); + if ($type[0] == 'SELECT'){ + $row = oci_fetch_assoc($query); + $rows = $row[NUM]; + } + else{ + $rows = oci_num_rows($query); + } + + oci_free_statement($query); + + return $rows; +} + +/** + * Get all the rows in a table of the database filtering from a field. + * + * @param string Database table name. + * @param string Field of the table. + * @param string Condition the field must have to be selected. + * @param string Field to order by. + * + * @return mixed A matrix with all the values in the table that matches the condition in the field or false + */ +function oracle_get_db_all_rows_field_filter ($table, $field, $condition, $order_field = "") { + if (is_int ($condition) || is_bool ($condition)) { + $sql = sprintf ("SELECT * FROM %s WHERE %s = %d", $table, $field, $condition); + } + else if (is_float ($condition) || is_double ($condition)) { + $sql = sprintf ("SELECT * FROM %s WHERE %s = %f", $table, $field, $condition); + } + else { + $sql = sprintf ("SELECT * FROM %s WHERE %s = '%s'", $table, $field, $condition); + } + + if ($order_field != "") + $sql .= sprintf (" ORDER BY %s", $order_field); + + return get_db_all_rows_sql ($sql); +} + +/** + * Get all the rows in a table of the database filtering from a field. + * + * @param string Database table name. + * @param string Field of the table. + * + * @return mixed A matrix with all the values in the table that matches the condition in the field + */ +function oracle_get_db_all_fields_in_table ($table, $field = '', $condition = '', $order_field = '') { + $sql = sprintf ("SELECT * FROM %s", $table); + + if ($condition != '') { + $sql .= sprintf (" WHERE %s = '%s'", $field, $condition); + } + + if ($order_field != "") + $sql .= sprintf (" ORDER BY %s", $order_field); + + return get_db_all_rows_sql ($sql); +} + +/** + * Formats an array of values into a SQL string. + * + * This function is useful to generate an UPDATE SQL sentence from a list of + * values. Example code: + * + * + * $values = array (); + * $values['name'] = "Name"; + * $values['description'] = "Long description"; + * $sql = 'UPDATE table SET '.format_array_to_update_sql ($values).' WHERE id=1'; + * echo $sql; + * + * Will return: + * + * UPDATE table SET name = "Name", description = "Long description" WHERE id=1 + * + * + * @param array Values to be formatted in an array indexed by the field name. + * + * @return string Values joined into an SQL string that can fits into an UPDATE + * sentence. + */ +function oracle_format_array_to_update_sql ($values) { + $fields = array (); + + foreach ($values as $field => $value) { + if (is_numeric($field)) { + array_push ($fields, $value); + continue; + } + else if ($field[0] == "`") { + $field = str_replace('`', '', $field); + } + + if ($value === NULL) { + $sql = sprintf ("%s = NULL", $field); + } + elseif (is_int ($value) || is_bool ($value)) { + $sql = sprintf ("%s = %d", $field, $value); + } + elseif (is_float ($value) || is_double ($value)) { + $sql = sprintf ("%s = %f", $field, $value); + } + else { + /* String */ + if (isset ($value[0]) && $value[0] == '`') + /* Don't round with quotes if it references a field */ + $sql = sprintf ("%s = %s", $field, str_replace('`', '', $value)); + else + $sql = sprintf ("%s = '%s'", $field, $value); + } + array_push ($fields, $sql); + } + + return implode (", ", $fields); +} + +/** + * Updates a database record. + * + * All values should be cleaned before passing. Quoting isn't necessary. + * Examples: + * + * + * process_sql_update ('table', array ('field' => 1), array ('id' => $id)); + * process_sql_update ('table', array ('field' => 1), array ('id' => $id, 'name' => $name)); + * process_sql_update ('table', array ('field' => 1), array ('id' => $id, 'name' => $name), 'OR'); + * process_sql_update ('table', array ('field' => 2), 'id in (1, 2, 3) OR id > 10'); + * + * + * @param string Table to insert into + * @param array An associative array of values to update + * @param mixed An associative array of field and value matches. Will be joined + * with operator specified by $where_join. A custom string can also be provided. + * If nothing is provided, the update will affect all rows. + * @param string When a $where parameter is given, this will work as the glue + * between the fields. "AND" operator will be use by default. Other values might + * be "OR", "AND NOT", "XOR" + * + * @return mixed False in case of error or invalid values passed. Affected rows otherwise + */ +function oracle_process_sql_update($table, $values, $where = false, $where_join = 'AND') { + $query = sprintf ("UPDATE %s SET %s", + $table, + format_array_to_update_sql ($values)); + + if ($where) { + if (is_string ($where)) { + // No clean, the caller should make sure all input is clean, this is a raw function + $query .= " WHERE " . $where; + } + else if (is_array ($where)) { + $query .= format_array_to_where_clause_sql ($where, $where_join, ' WHERE '); + } + } + + return process_sql ($query); +} + +/** + * Delete database records. + * + * All values should be cleaned before passing. Quoting isn't necessary. + * Examples: + * + * + * process_sql_delete ('table', array ('id' => 1)); + * // DELETE FROM table WHERE id = 1 + * process_sql_delete ('table', array ('id' => 1, 'name' => 'example')); + * // DELETE FROM table WHERE id = 1 AND name = 'example' + * process_sql_delete ('table', array ('id' => 1, 'name' => 'example'), 'OR'); + * // DELETE FROM table WHERE id = 1 OR name = 'example' + * process_sql_delete ('table', 'id in (1, 2, 3) OR id > 10'); + * // DELETE FROM table WHERE id in (1, 2, 3) OR id > 10 + * + * + * @param string Table to insert into + * @param array An associative array of values to update + * @param mixed An associative array of field and value matches. Will be joined + * with operator specified by $where_join. A custom string can also be provided. + * If nothing is provided, the update will affect all rows. + * @param string When a $where parameter is given, this will work as the glue + * between the fields. "AND" operator will be use by default. Other values might + * be "OR", "AND NOT", "XOR" + * + * @return mixed False in case of error or invalid values passed. Affected rows otherwise + */ +function oracle_process_sql_delete($table, $where, $where_join = 'AND') { + if (empty ($where)) + /* Should avoid any mistake that lead to deleting all data */ + return false; + + $query = sprintf ("DELETE FROM %s WHERE ", $table); + + if ($where) { + if (is_string ($where)) { + /* FIXME: Should we clean the string for sanity? + Who cares if this is deleting data... */ + $query .= $where; + } + else if (is_array ($where)) { + $query .= format_array_to_where_clause_sql ($where, $where_join); + } + } + + return process_sql ($query); +} + +function oracle_process_sql_delete_temp ($table, $where, $where_join = 'AND'){ + if (empty ($where)) + /* Should avoid any mistake that lead to deleting all data */ + return false; + + $query = sprintf ("DELETE FROM %s WHERE ", $table); + + if ($where) { + if (is_string ($where)) { + /* FIXME: Should we clean the string for sanity? + Who cares if this is deleting data... */ + $query .= $where; + } + else if (is_array ($where)) { + $query .= format_array_to_where_clause_sql ($where, $where_join); + } + } + + $result = ''; + return process_sql ($query, "affected_rows", '', true, $result, false); +} + + +/** + * Get row by row the DB by SQL query. The first time pass the SQL query and + * rest of times pass none for iterate in table and extract row by row, and + * the end return false. + * + * @param bool $new Default true, if true start to query. + * @param resource $result The resource of oracle for access to query. + * @param string $sql + * @return mixed The row or false in error. + */ +function oracle_get_db_all_row_by_steps_sql($new = true, &$result, $sql = null) { + global $config; + + if ($new == true){ + $result = oci_parse($config['dbconnection'], $sql); + oci_execute($result); + } + $row = oci_fetch_assoc($result); + + if (!$row){ + oci_free_statement($result); + } + + return $row; +} + +/** + * Starts a database transaction. + */ +function oracle_process_sql_begin() { + global $config; + + $query = oci_parse($config['dbconnection'], 'SET TRANSACTION READ WRITE'); + oci_execute($query); + oci_free_statement($query); +} + +/** + * Commits a database transaction. + */ +function oracle_process_sql_commit() { + global $config; + + oci_commit($config['dbconnection']); +} + +/** + * Rollbacks a database transaction. + */ +function oracle_process_sql_rollback() { + global $config; + + oci_rollback($config['dbconnection']); +} + +/** + * Put quotes if magic_quotes protection + * + * @param string Text string to be protected with quotes if magic_quotes protection is disabled + */ +function oracle_safe_sql_string($string) { + if (get_magic_quotes_gpc () == 0) + return $string; + + return oracle_escape_string_sql($string); +} + +/** + * Get last error. + * + * @return string Return the string error. + */ +function oracle_get_db_last_error() { + $ora_erno = oci_error(); + + return $ora_erno['message']; +} + +/** + * This function gets the time from either system or sql based on preference and returns it + * + * @return int Unix timestamp + */ +function oracle_get_system_time() { + global $config; + + static $time = 0; + + if ($time != 0) + return $time; + + if ($config["timesource"] = "sql") { + $time = get_db_sql ("SELECT ceil((sysdate - to_date('19700101000000','YYYYMMDDHH24MISS')) * (86400)) as dt FROM dual"); + if (empty ($time)) { + return time (); + } + return $time; + } + else { + return time (); + } +} + +/** + * Get the type of field. + * + * @param string $table The table to examine the type of field. + * @param integer $field The field order in table. + * + * @return mixed Return the type name or False in error case. + */ +function oracle_get_db_type_field_table($table, $field) { + global $config; + + $query = oci_parse($config['dbconnection'], "SELECT * FROM " . $table . " WHERE rownum < 2"); + oci_execute($query); + + $type = oci_field_type($query, $field); + oci_free_statement($query); + + return $type; +} + +?> diff --git a/pandora_console/include/functions_db.php b/pandora_console/include/functions_db.php index 43b7cf35f2..dd4337ee8f 100644 --- a/pandora_console/include/functions_db.php +++ b/pandora_console/include/functions_db.php @@ -31,6 +31,9 @@ function select_db_engine() { case "postgresql": require_once ($config['homedir'] . '/include/db/postgresql.php'); break; + case "oracle": + require_once ($config['homedir'] . '/include/db/oracle.php'); + break; } } @@ -44,6 +47,9 @@ function connect_db($host = null, $db = null, $user = null, $pass = null) { case "postgresql": return postgresql_connect_db($host, $db, $user, $pass); break; + case "oracle": + return oracle_connect_db($host, $db, $user, $pass); + break; } } @@ -111,6 +117,9 @@ function escape_string_sql($string) { case "postgresql": return postgresql_escape_string_sql($string); break; + case "oracle": + return oracle_escape_string_sql($string); + break; } } @@ -596,6 +605,9 @@ function get_group_agents ($id_group = 0, $search = false, $case = "lower", $noA case "postgresql": $search_sql .= ' AND (nombre COLLATE utf8_general_ci LIKE \'%'.$string.'%\' OR direccion LIKE \'%'.$string.'%\')'; break; + case "oracle": + $search_sql .= ' AND (nombre LIKE UPPER(\'%'.$string.'%\') OR direccion LIKE upper(\'%'.$string.'%\'))'; + break; } unset ($search["string"]); @@ -603,7 +615,17 @@ function get_group_agents ($id_group = 0, $search = false, $case = "lower", $noA if (isset ($search["name"])) { $name = safe_input ($search["name"]); - $search_sql .= ' AND nombre COLLATE utf8_general_ci LIKE "' . $name . '" '; + switch ($config["dbtype"]) { + case "mysql": + $search_sql .= ' AND nombre COLLATE utf8_general_ci LIKE "' . $name . '" '; + break; + case "postgresql": + $search_sql .= ' AND nombre COLLATE utf8_general_ci LIKE \'' . $name . '\' '; + break; + case "oracle": + $search_sql .= ' AND nombre LIKE UPPER("' . $name . '") '; + break; + } unset ($search["name"]); } @@ -1051,6 +1073,14 @@ function get_monitor_downs_in_period ($id_agent_module, $period, $date = 0) { AND \"utimestamp\" <= %d", $id_agent_module, $datelimit, $date); break; + case "oracle": + $sql = sprintf ("SELECT COUNT(id_agentmodule) FROM tevento WHERE + event_type = 'monitor_down' + AND id_agentmodule = %d + AND utimestamp > %d + AND utimestamp <= %d", + $id_agent_module, $datelimit, $date); + break; } return get_db_sql ($sql); @@ -1090,6 +1120,14 @@ function get_monitor_last_down_timestamp_in_period ($id_agent_module, $period, $ AND \"utimestamp\" <= %d", $id_agent_module, $datelimit, $date); break; + case "oracle": + $sql = sprintf ("SELECT MAX(timestamp) FROM tevento WHERE + event_type = 'monitor_down' + AND id_agentmodule = %d + AND utimestamp > %d + AND utimestamp <= %d", + $id_agent_module, $datelimit, $date); + break; } return get_db_sql ($sql); @@ -1124,6 +1162,7 @@ function get_monitors_in_group ($id_group) { AND `tagente`.`id_grupo` IN (%s) ORDER BY `tagente`.`nombre`", $id_group); break; case "postgresql": + case "oracle": $sql = sprintf ("SELECT tagente_modulo.* FROM tagente_modulo, ttipo_modulo, tagente WHERE id_tipo_modulo = id_tipo AND tagente.id_agente = tagente_modulo.id_agente @@ -1307,6 +1346,7 @@ function get_monitors_in_agent ($id_agent) { AND `tagente`.`id_agente` = %d", $id_agent); break; case "postgresql": + case "oracle": $sql = sprintf ("SELECT tagente_modulo.* FROM tagente_modulo, ttipo_modulo, tagente WHERE id_tipo_modulo = id_tipo @@ -1371,6 +1411,7 @@ function get_alert_fires_in_period ($id_alert_module, $period, $date = 0) { $id_alert_module, $datelimit, $date); break; case "postgresql": + case "oracle": $sql = sprintf ("SELECT COUNT(id_agentmodule) FROM tevento WHERE event_type = 'alert_fired' @@ -1467,6 +1508,7 @@ function get_alert_last_fire_timestamp_in_period ($id_alert_module, $period, $da $id_alert_module, $datelimit, $date); break; case "postgresql": + case "oracle": $sql = sprintf ("SELECT MAX(utimestamp) FROM tevento WHERE event_type = 'alert_fired' @@ -2021,6 +2063,7 @@ function agent_add_address ($id_agent, $ip_address) { AND ip = '%s' AND id_agent = %d",$ip_address,$id_agent); break; case "postgresql": + case "oracle": $sql = sprintf ("SELECT COUNT(ip) FROM taddress_agent, taddress WHERE taddress_agent.id_a = taddress.id_a AND ip = '%s' AND id_agent = %d", $ip_address, $id_agent); @@ -2103,6 +2146,7 @@ function get_agent_with_ip ($ip_address) { AND ip = "%s"', $ip_address); break; case "postgresql": + case "oracle": $sql = sprintf ('SELECT tagente.* FROM tagente, taddress, taddress_agent WHERE tagente.id_agente = taddress_agent.id_agent @@ -2174,6 +2218,9 @@ function get_db_value($field, $table, $field_search = 1, $condition = 1, $search case "postgresql": return postgresql_get_db_value($field, $table, $field_search, $condition, $search_history_db); break; + case "oracle": + return oracle_get_db_value($field, $table, $field_search, $condition, $search_history_db); + break; } } @@ -2212,6 +2259,9 @@ function get_db_value_filter ($field, $table, $filter, $where_join = 'AND') { case "postgresql": return postgresql_get_db_value_filter($field, $table, $filter, $where_join); break; + case "oracle": + return oracle_get_db_value_filter($field, $table, $filter, $where_join); + break; } } @@ -2233,6 +2283,9 @@ function get_db_value_sql($sql) { case "postgresql": return postgresql_get_db_value_sql($sql); break; + case "oracle": + return oracle_get_db_value_sql($sql); + break; } } @@ -2253,6 +2306,10 @@ function get_db_row_sql($sql, $search_history_db = false) { case "postgresql": return postgresql_get_db_row_sql($sql, $search_history_db); break; + case "oracle": + return oracle_get_db_row_sql($sql, $search_history_db); + break; + } } @@ -2279,6 +2336,9 @@ function get_db_row ($table, $field_search, $condition, $fields = false) { case "postgresql": return postgresql_get_db_row($table, $field_search, $condition, $fields); break; + case "oracle": + return oracle_get_db_row($table, $field_search, $condition, $fields); + break; } } @@ -2316,6 +2376,9 @@ function get_db_row_filter($table, $filter, $fields = false, $where_join = 'AND' case "postgresql": return postgresql_get_db_row_filter($table, $filter, $fields, $where_join); break; + case "oracle": + return oracle_get_db_row_filter($table, $filter, $fields, $where_join); + break; } } @@ -2362,6 +2425,9 @@ function get_db_all_rows_sql($sql, $search_history_db = false, $cache = true) { case "postgresql": return postgresql_get_db_all_rows_sql($sql, $search_history_db, $cache); break; + case "oracle": + return oracle_get_db_all_rows_sql($sql, $search_history_db, $cache); + break; } } @@ -2399,6 +2465,9 @@ function get_db_all_rows_filter($table, $filter = array(), $fields = false, $whe case "postgresql": return postgresql_get_db_all_rows_filter($table, $filter, $fields, $where_join, $search_history_db, $returnSQL); break; + case "oracle": + return oracle_get_db_all_rows_filter($table, $filter, $fields, $where_join, $search_history_db, $returnSQL); + break; } } @@ -2422,6 +2491,9 @@ function get_db_all_row_by_steps_sql($new = true, &$result, $sql = null) { case "postgresql": return postgresql_get_db_all_row_by_steps_sql($new, $result, $sql); break; + case "oracle": + return oracle_get_db_all_row_by_steps_sql($new, $result, $sql); + break; } } @@ -2441,6 +2513,9 @@ function get_db_num_rows($sql) { case "postgresql": return postgresql_get_db_num_rows($sql); break; + case "oracle": + return oracle_get_db_num_rows($sql); + break; } } @@ -2529,9 +2604,11 @@ function clean_cache() { * * @param string $status The status and type of query (support only postgreSQL). * + * @param bool $autocommit (Only oracle) Set autocommit transaction mode true/false + * * @return mixed An array with the rows, columns and values in a multidimensional array or false in error */ -function process_sql($sql, $rettype = "affected_rows", $dbconnection = '', $cache = true, &$status = null) { +function process_sql($sql, $rettype = "affected_rows", $dbconnection = '', $cache = true, &$status = null, $autocommit = true) { global $config; switch ($config["dbtype"]) { @@ -2541,6 +2618,9 @@ function process_sql($sql, $rettype = "affected_rows", $dbconnection = '', $cach case "postgresql": return @postgresql_process_sql($sql, $rettype, $dbconnection, $cache, $status); break; + case "oracle": + return @oracle_process_sql($sql, $rettype, $dbconnection, $cache, $status, $autocommit); + break; } } @@ -2563,6 +2643,9 @@ function get_db_all_rows_in_table ($table, $order_field = "", $order = 'ASC') { case "postgresql": return postgresql_get_db_all_rows_in_table($table, $order_field, $order); break; + case "oracle": + return oracle_get_db_all_rows_in_table($table, $order_field, $order); + break; } } @@ -2586,6 +2669,9 @@ function get_db_all_rows_field_filter($table, $field, $condition, $order_field = case "postgresql": return postgresql_get_db_all_rows_field_filter($table, $field, $condition, $order_field); break; + case "oracle": + return oracle_get_db_all_rows_field_filter($table, $field, $condition, $order_field); + break; } } @@ -2607,6 +2693,9 @@ function get_db_all_fields_in_table($table, $field = '', $condition = '', $order case "postgresql": return postgresql_get_db_all_fields_in_table($table, $field, $condition, $order_field); break; + case "oracle": + return oracle_get_db_all_fields_in_table($table, $field, $condition, $order_field); + break; } } @@ -2643,6 +2732,9 @@ function format_array_to_update_sql($values) { case "postgresql": return postgresql_format_array_to_update_sql($values); break; + case "oracle": + return oracle_format_array_to_update_sql($values); + break; } } @@ -2708,6 +2800,9 @@ function format_array_to_update_sql($values) { * * @return string Values joined into an SQL string that can fits into the WHERE * clause of an SQL sentence. + + // IMPORTANT!!! OFFSET parameter is not allowed for Oracle because Oracle needs to recode the complete query. + // use oracle_format_query() function instead. */ function format_array_to_where_clause_sql ($values, $join = 'AND', $prefix = false) { global $config; @@ -2719,6 +2814,9 @@ function format_array_to_where_clause_sql ($values, $join = 'AND', $prefix = fal case "postgresql": return postgresql_format_array_to_where_clause_sql($values, $join, $prefix); break; + case "oracle": + return oracle_format_array_to_where_clause_sql($values, $join, $prefix); + break; } } @@ -2800,6 +2898,12 @@ function get_agent_status($id_agent = 0) { array ('id_agente' => (int) $id_agent, 'ceil(date_part(\'epoch\', ultimo_contacto)) + intervalo * 2 > '.$time)); break; + case "oracle": + $status = get_db_value_filter ('COUNT(*)', + 'tagente', + array ('id_agente' => (int) $id_agent, + 'ceil((to_date(ultimo_contacto, \'DD/MM/YYYY HH24:MI:SS\') - to_date(\'19700101000000\',\'YYYYMMDDHH24MISS\')) * (86400)) > ' . $time)); + break; } if (! $status) @@ -3111,6 +3215,10 @@ function check_server_status () { case "postgresql": $sql = "SELECT COUNT(id_server) FROM tserver WHERE status = 1 AND keepalive > NOW() - INTERVAL '15 MINUTE'"; break; + + case "oracle": + $sql = "SELECT COUNT(id_server) FROM tserver WHERE status = 1 AND keepalive > systimestamp - INTERVAL '15' MINUTE"; + break; } $status = (int) get_db_sql ($sql); //Cast as int will assure a number value // This function should just ack of server down, not set it down. @@ -3131,13 +3239,22 @@ function server_status ($id_server) { } /** - * Subfunciton for less typing + * Subfunction for less typing * @ignore */ function temp_sql_delete ($table, $row, $value) { global $error; //Globalize the errors variable - $result = process_sql_delete ($table, $row.' = '.$value); + switch ($config["dbtype"]) { + case "mysql": + case "postgresql": + $result = process_sql_delete ($table, $row.' = '.$value); + break; + case "oracle": + $result = oracle_process_sql_delete_temp ($table, $row.' = '.$value); + break; + } + if ($result === false) { $error = true; } @@ -3385,6 +3502,9 @@ function process_sql_insert($table, $values) { case "postgresql": return postgresql_process_sql_insert($table, $values); break; + case "oracle": + return oracle_process_sql_insert($table, $values); + break; } } @@ -3422,6 +3542,9 @@ function process_sql_update($table, $values, $where = false, $where_join = 'AND' case "postgresql": return postgresql_process_sql_update($table, $values, $where, $where_join); break; + case "oracle": + return oracle_process_sql_update($table, $values, $where, $where_join); + break; } } @@ -3463,6 +3586,9 @@ function process_sql_delete($table, $where, $where_join = 'AND') { case "postgresql": return postgresql_process_sql_delete($table, $where, $where_join); break; + case "oracle": + return oracle_process_sql_delete($table, $where, $where_join); + break; } } @@ -3479,6 +3605,9 @@ function process_sql_begin() { case "postgresql": return postgresql_process_sql_begin(); break; + case "oracle": + return oracle_process_sql_begin(); + break; } } @@ -3495,6 +3624,9 @@ function process_sql_commit() { case "postgresql": return postgresql_process_sql_commit(); break; + case "oracle": + return oracle_process_sql_commit(); + break; } } @@ -3511,6 +3643,9 @@ function process_sql_rollback() { case "postgresql": return postgresql_process_sql_rollback(); break; + case "oracle": + return oracle_process_sql_rollback(); + break; } } @@ -3657,6 +3792,9 @@ function get_db_last_error() { case "postgresql": return postgresql_get_db_last_error(); break; + case "oracle": + return oracle_get_db_last_error(); + break; } } @@ -3678,6 +3816,9 @@ function get_db_type_field_table($table, $field) { case "postgresql": return postgresql_get_db_type_field_table($table, $field); break; + case "oracle": + return oracle_get_db_type_field_table($table, $field); + break; } } ?> diff --git a/pandora_console/pandoradb.oracle.sql b/pandora_console/pandoradb.oracle.sql index b80ef95edf..43df04e67e 100644 --- a/pandora_console/pandoradb.oracle.sql +++ b/pandora_console/pandoradb.oracle.sql @@ -52,13 +52,13 @@ CREATE TABLE tagente ( direccion VARCHAR2(100) default NULL, comentarios VARCHAR2(255) default '', id_grupo NUMBER(10, 0) default 0 NOT NULL, - ultimo_contacto DATE default NULL, + ultimo_contacto TIMESTAMP default NULL, modo NUMBER(5, 0) default 0 NOT NULL, intervalo NUMBER(10, 0) default 300 NOT NULL, id_os NUMBER(10, 0) default 0, os_version VARCHAR2(100) default '', agent_version VARCHAR2(100) default '', - ultimo_contacto_remoto DATE default NULL, + ultimo_contacto_remoto TIMESTAMP default NULL, disabled NUMBER(5, 0) default 0 NOT NULL, id_parent NUMBER(10, 0) default 0, custom_id VARCHAR2(255) default '', @@ -125,10 +125,10 @@ CREATE TABLE tagente_estado ( id_agente_estado NUMBER(10, 0) NOT NULL PRIMARY KEY, id_agente_modulo NUMBER(10, 0) default 0 NOT NULL, datos NCLOB default '' NOT NULL, - timestamp DATE default NULL, + timestamp TIMESTAMP default NULL, estado NUMBER(10, 0) default 0 NOT NULL, id_agente NUMBER(10, 0) default 0 NOT NULL, - last_try DATE default NULL, + last_try TIMESTAMP default NULL, utimestamp NUMBER(19, 0) default 0 NOT NULL, current_interval NUMBER(10, 0) default 0 NOT NULL, running_by NUMBER(10, 0) default 0, @@ -231,7 +231,7 @@ CREATE TABLE talert_snmp ( oid VARCHAR2(255) default '' NOT NULL, time_threshold NUMBER(10, 0) default 0 NOT NULL, times_fired NUMBER(5, 0) default 0 NOT NULL, - last_fired DATE default NULL, + last_fired TIMESTAMP default NULL, max_alerts NUMBER(10, 0) default 1 NOT NULL, min_alerts NUMBER(10, 0) default 1 NOT NULL, internal_counter NUMBER(10, 0) default 0 NOT NULL, @@ -930,7 +930,7 @@ CREATE TABLE treport_content ( show_resume NUMBER(10, 0) default 0 NOT NULL, order_uptodown NUMBER(10, 0) default 0 NOT NULL, show_graph NUMBER(10, 0) default 0 NOT NULL, - group_by_agent NUMBER(10, 0) default 0 NOT NULL + group_by_agent NUMBER(10, 0) default 0 NOT NULL, style NCLOB default '' NOT NULL ); @@ -1391,3 +1391,7 @@ CREATE OR REPLACE TRIGGER tagent_custom_data_update AFTER UPDATE OF ID_FIELD ON -- on update trigger 1 CREATE OR REPLACE TRIGGER tagent_custom_data_update1 AFTER UPDATE OF ID_AGENTE ON tagente FOR EACH ROW BEGIN UPDATE tagent_custom_data SET ID_AGENT = :NEW.ID_AGENTE WHERE ID_AGENT = :OLD.ID_AGENTE; END;; + +-- Procedure for retrieve PK information after an insert statement +CREATE OR REPLACE PROCEDURE insert_id (table_name IN VARCHAR2, sql_insert IN VARCHAR2, id OUT NUMBER) IS BEGIN EXECUTE IMMEDIATE sql_insert; EXECUTE IMMEDIATE 'SELECT ' ||table_name||'_s.currval FROM DUAL' INTO id; EXCEPTION WHEN others THEN RAISE_APPLICATION_ERROR(-20001, 'ERROR on insert_id procedure, please check input parameters or procedure logic.'); END insert_id;; +