Added a common database backend implementation.

Added sqlite (proof of concept)
This commit is contained in:
jvelilla
2014-09-17 10:33:37 -03:00
parent fbb5c57b8f
commit 4227b82c7e
37 changed files with 1889 additions and 153 deletions

View File

@@ -0,0 +1,29 @@
note
description: "Database configuration"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
deferred class
DATABASE_CONFIG
feature -- Database access
hostname: STRING = ""
-- Database hostname.
username: STRING = ""
-- Database username.
password: STRING = ""
-- Database password.
database_name: STRING = "EiffelDB"
-- Database name.
is_keep_connection: BOOLEAN
-- Keep Connection to database?
do
Result := True
end
end

View File

@@ -0,0 +1,110 @@
note
description: "Abstract class to handle a database connection"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
deferred class
DATABASE_CONNECTION
inherit
DATABASE_CONFIG
SHARED_ERROR
feature {NONE} -- Initialization
make_common
-- Create a database handler with common settings.
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
make_basic ( a_database_name: STRING)
-- Create a database handler with common settings and
-- set database_name with `a_database_name'.
require
database_name_not_void: a_database_name /= Void
database_name_not_empty: not a_database_name.is_empty
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler with user `a_username', password `a_password',
-- host `a_hostname', database_name `a_database_name', and keep_connection `connection'.
require
username_not_void: a_username /= Void
username_not_empty: not a_username.is_empty
password_not_void: a_password /= Void
hostname_not_void: a_hostname /= Void
hotname_not_empty: not a_hostname.is_empty
database_name_not_void: a_database_name /= Void
database_name_not_empty: not a_database_name.is_empty
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
login_with_connection_string (a_connection_string: STRING)
-- Login with `a_connection_string'
-- and immediately connect to database.
deferred
ensure
db_application_not_void: db_application /= Void
db_control_not_void: db_control /= Void
end
feature -- Database Setup
db_application: DATABASE_APPL [DATABASE]
-- Database application.
db_control: DB_CONTROL
-- Database control.
keep_connection: BOOLEAN
-- Keep connection alive?
feature -- Change Element
not_keep_connection
do
keep_connection := False
end
feature -- Conection
connect
-- Connect to the database.
require else
db_control_not_void: db_control /= Void
do
if not is_connected then
db_control.connect
end
end
disconnect
-- Disconnect from the database.
require else
db_control_not_void: db_control /= Void
do
db_control.disconnect
end
is_connected: BOOLEAN
-- True if connected to the database.
require else
db_control_not_void: db_control /= Void
do
Result := db_control.is_connected
end
end

View File

@@ -0,0 +1,67 @@
note
description: "Null object to meet Void Safe."
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_CONNECTION_NULL
inherit
DATABASE_CONNECTION
redefine
db_application,
is_connected
end
create
make, make_common, make_basic
feature -- Initialization
make_common
-- Create a database handler for ODBC with common settings.
do
create db_application.login (username, password)
db_application.set_hostname (hostname)
db_application.set_data_source (database_name)
db_application.set_base
create db_control.make
end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler for ODBC.
do
make_common
end
make_basic (a_database_name: STRING)
-- Create a database handler for ODBC.
do
make_common
end
login_with_connection_string (a_string: STRING)
-- Login with `a_connection_string'
-- and immediately connect to database.
do
make_common
end
feature -- Databse Connection
db_application: DATABASE_APPL[DATABASE_NULL]
-- Database application.
is_connected: BOOLEAN
-- True if connected to the database.
do
Result := True
end
end

View File

@@ -0,0 +1,126 @@
note
description: "Object that handle a database connection for ODBC"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_CONNECTION_ODBC
inherit
DATABASE_CONNECTION
redefine
db_application
end
create
make, make_common, make_basic, login_with_connection_string
feature -- Initialization
make_common
-- Create a database handler for ODBC with common settings.
local
l_retried: BOOLEAN
do
create db_application.login (username, password)
if not l_retried then
db_application.set_hostname (hostname)
db_application.set_data_source (database_name)
db_application.set_base
create db_control.make
keep_connection := is_keep_connection
if keep_connection then
connect
end
set_successful
else
create db_control.make
end
rescue
create db_control.make
set_last_error_from_exception ("Connection execution")
log.write_critical (generator + ".make_common:" + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
make_basic (a_database_name: STRING)
-- Create a database handler and
-- set database_name to `a_database_name'.
local
l_retried: BOOLEAN
do
create db_application.login (username, password)
if not l_retried then
db_application.set_hostname (hostname)
db_application.set_data_source (a_database_name)
db_application.set_base
create db_control.make
keep_connection := is_keep_connection
if keep_connection then
connect
end
set_successful
else
create db_control.make
end
rescue
create db_control.make
set_last_error_from_exception ("Connection execution")
log.write_critical (generator + ".make_common:" + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
make (a_username: STRING; a_password: STRING; a_hostname: STRING; a_database_name: STRING; connection: BOOLEAN)
-- Create a database handler for ODBC and set `username' to `a_username',
-- `password' to `a_password'
-- `database_name' to `a_database_name'
-- `connection' to `a_connection'
do
create db_application.login (a_username, a_password)
db_application.set_hostname (a_hostname)
db_application.set_data_source (a_database_name)
db_application.set_base
create db_control.make
keep_connection := connection
if keep_connection then
connect
end
end
login_with_connection_string (a_string: STRING)
-- Login with `a_connection_string'and immediately connect to database.
do
log.write_debug (generator +".login_with_connection_string")
create db_application.login_with_connection_string (a_string)
db_application.set_base
create db_control.make
log.write_debug (generator +".login_with_connection_string, is_keep_connection? "+ is_keep_connection.out )
keep_connection := is_keep_connection
if keep_connection then
connect
if not db_control.is_ok then
log.write_critical (generator +".login_with_connection_string:"+ db_control.error_code.out )
log.write_critical (generator +".login_with_connection_string:"+ db_control.error_message_32 )
end
log.write_debug (generator +".login_with_connection_string, After connect, is_connected? "+ is_connected.out)
end
end
feature -- Databse Connection
db_application: DATABASE_APPL [ODBC]
-- Database application.
end

View File

@@ -0,0 +1,177 @@
note
description: "Abstract Database Handler"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
deferred class
DATABASE_HANDLER
inherit
SHARED_ERROR
feature -- Access
store: detachable DATABASE_STORE_PROCEDURE
-- Database stored_procedure to handle.
query: detachable DATABASE_QUERY
-- Database query.
feature -- Modifiers
set_store (a_store: DATABASE_STORE_PROCEDURE)
-- Set `store' to `a_store' to execute.
require
store_not_void: a_store /= Void
do
store := a_store
ensure
store_set: store = a_store
end
set_query (a_query: DATABASE_QUERY)
-- Set `query' to `a_query' to execute.
require
query_not_void: a_query /= Void
do
query := a_query
ensure
query_set: query = a_query
end
feature -- Functionality Store Procedures
execute_reader
-- Execute store.
require
store_not_void: store /= void
deferred
end
execute_writer
-- Execute store.
require
store_not_void: store /= void
deferred
end
feature -- SQL Queries
execute_query
-- Execute query.
require
query_not_void: query /= void
deferred
end
execute_change
-- Execute sqlquery that update/add data.
require
query_not_void: query /= void
deferred
end
feature -- Iteration
start
-- Set the cursor on first element.
deferred
end
item: ANY
-- Item at current cursor position.
require
valid_position: not after
deferred
end
after: BOOLEAN
-- Are there no more items to iterate over?
deferred
end
forth
-- Move to next position.
require
valid_position: not after
deferred
end
feature -- Access
read_integer_32 (a_index: INTEGER): INTEGER_32
-- Retrieved value at `a_index' position in `item'.
do
if attached {DB_TUPLE} item as l_item then
if attached {INTEGER_32_REF} l_item.item (a_index) as ll_item then
Result := ll_item.item
end
end
end
read_string (a_index: INTEGER): detachable STRING
-- Retrieved value at `a_index' position in `item'.
do
if attached {DB_TUPLE} item as l_item then
if attached {STRING} l_item.item (a_index) as ll_item then
Result := ll_item
elseif attached {BOOLEAN_REF} l_item.item (a_index) as ll_item then
Result := ll_item.item.out
end
end
end
read_date_time (a_index: INTEGER): detachable DATE_TIME
-- Retrieved value at `a_index' position in `item'.
do
if attached {DB_TUPLE} item as l_item then
if attached {DATE_TIME} l_item.item (a_index) as ll_item then
Result := ll_item
end
end
end
read_boolean (a_index: INTEGER): detachable BOOLEAN
-- Retrieved value at `a_index' position in `item'.
do
if attached {DB_TUPLE} item as l_item then
if attached {BOOLEAN} l_item.item (a_index) as ll_item then
Result := ll_item
elseif attached {BOOLEAN_REF} l_item.item (a_index) as ll_item then
Result := ll_item.item
end
end
end
feature -- Status Report
has_error: BOOLEAN
-- Is there an error?
count: INTEGER
-- Number of rows, last execution.
deferred
end
feature {NODE_DATA_PROVIDER}-- Implementation
connect
-- Connect to the database.
deferred
end
disconnect
-- Disconnect from the database.
deferred
ensure
not_connected: not is_connected
end
is_connected: BOOLEAN
-- True if connected to the database.
deferred
end
end

View File

@@ -0,0 +1,284 @@
note
description: "Database handler Implementation"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_HANDLER_IMPL
inherit
DATABASE_HANDLER
REFACTORING_HELPER
create
make
feature {NONE} -- Initialization
make (a_connection: DATABASE_CONNECTION)
-- Create a database handler with connnection `connection'.
do
connection := a_connection
create last_query.make_now
set_successful
ensure
connection_not_void: connection /= Void
last_query_not_void: last_query /= Void
end
feature -- Functionality
execute_reader
-- Execute stored procedure that returns data.
local
l_db_selection: DB_SELECTION
l_retried: BOOLEAN
do
if not l_retried then
if not keep_connection then
connect
end
if attached store as l_store then
create l_db_selection.make
db_selection := l_db_selection
items := l_store.execute_reader (l_db_selection)
end
if not keep_connection then
disconnect
end
set_successful
log.write_debug ( generator+".execute_reader Successful")
end
rescue
set_last_error_from_exception ("Store procedure execution")
log.write_critical (generator+ ".execute_reader " + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
execute_writer
-- Execute stored procedure that update/add data.
local
l_db_change: DB_CHANGE
l_retried : BOOLEAN
do
if not l_retried then
if not keep_connection and not is_connected then
connect
end
if attached store as l_store then
create l_db_change.make
db_update := l_db_change
l_store.execute_writer (l_db_change)
if not l_store.has_error then
db_control.commit
end
end
if not keep_connection then
disconnect
end
set_successful
log.write_debug ( generator+".execute_writer Successful")
end
rescue
set_last_error_from_exception ("Store procedure execution")
log.write_critical (generator+ ".execute_writer " + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
feature -- SQL Queries
execute_query
-- Execute query.
local
l_db_selection: DB_SELECTION
l_retried: BOOLEAN
do
if not l_retried then
if not keep_connection then
connect
end
if attached query as l_query then
create l_db_selection.make
db_selection := l_db_selection
items := l_query.execute_reader (l_db_selection)
end
if not keep_connection then
disconnect
end
set_successful
end
rescue
set_last_error_from_exception ("execute_query")
log.write_critical (generator+ ".execute_query " + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
execute_change
-- Execute sqlquery that update/add data.
local
l_db_change: DB_CHANGE
l_retried : BOOLEAN
do
if not l_retried then
if not keep_connection and not is_connected then
connect
end
if attached query as l_query then
create l_db_change.make
db_update := l_db_change
l_query.execute_change (l_db_change)
db_control.commit
end
if not keep_connection then
disconnect
end
set_successful
end
rescue
set_last_error_from_exception ("Store procedure execution")
log.write_critical (generator+ ".execute_writer " + last_error_message)
if is_connected then
disconnect
end
l_retried := True
retry
end
feature -- Iteration
start
-- Set the cursor on first element.
do
if attached db_selection as l_db_selection and then l_db_selection.container /= Void then
l_db_selection.start
end
end
forth
-- Move cursor to next element.
do
if attached db_selection as l_db_selection then
l_db_selection.forth
else
check False end
end
end
after: BOOLEAN
-- True for the last element.
do
if attached db_selection as l_db_selection and then l_db_selection.container /= Void then
Result := l_db_selection.after or else l_db_selection.cursor = Void
else
Result := True
end
end
item: DB_TUPLE
-- Current element.
do
if attached db_selection as l_db_selection and then attached l_db_selection.cursor as l_cursor then
create {DB_TUPLE} Result.copy (l_cursor)
else
check False then end
end
end
feature {NONE} -- Implementation
connection: DATABASE_CONNECTION
-- Database connection.
db_control: DB_CONTROL
-- Database control.
do
Result := connection.db_control
end
db_result: detachable DB_RESULT
-- Database query result.
db_selection: detachable DB_SELECTION
-- Database selection.
db_update: detachable DB_CHANGE
-- Database modification.
last_query: DATE_TIME
-- Last time when a query was executed.
keep_connection: BOOLEAN
-- Keep connection alive?
do
Result := connection.keep_connection
end
connect
-- Connect to the database.
require else
db_control_not_void: db_control /= Void
do
if not is_connected then
db_control.connect
end
end
disconnect
-- Disconnect from the database.
require else
db_control_not_void: db_control /= Void
do
db_control.disconnect
end
is_connected: BOOLEAN
-- True if connected to the database.
require else
db_control_not_void: db_control /= Void
do
Result := db_control.is_connected
end
affected_row_count: INTEGER
-- The number of rows changed, deleted, or inserted by the last statement.
do
if attached db_update as l_update then
Result := l_update.affected_row_count
end
end
feature -- Result
items : detachable LIST[DB_RESULT]
-- Query result.
count: INTEGER
-- <Precursor>
do
if attached items as l_items then
Result := l_items.count
end
end
end

View File

@@ -0,0 +1,91 @@
note
description: "External iteration cursor for {ESA_DATABASE_HANDLER}"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_ITERATION_CURSOR [G]
inherit
ITERATION_CURSOR [G]
ITERABLE [G]
create
make
feature -- Initialization
make (a_handler: DATABASE_HANDLER; a_action: like action)
-- Create an iterator and set `db_handlet' to `a_handler'
-- `action' to `a_action'
do
db_handler := a_handler
action := a_action
ensure
db_handler_set: db_handler = a_handler
action_set: action = a_action
end
feature -- Access
item: G
-- Item at current cursor position.
do
Result := action.item ([db_item])
end
db_item: DB_TUPLE
-- Current element.
do
if attached {DB_TUPLE} db_handler.item as l_item then
Result := l_item
else
check False then
end
end
end
feature -- Status report
after: BOOLEAN
-- Are there no more items to iterate over?
do
Result := db_handler.after
end
feature -- Cursor movement
start
-- Set the cursor on first element.
do
db_handler.start
end
forth
-- Move to next position.
do
db_handler.forth
end
feature -- Cursor
new_cursor: DATABASE_ITERATION_CURSOR [G]
-- <Precursor>
do
Result := twin
Result.start
end
feature -- Action
action: FUNCTION [ANY, detachable TUPLE [], G]
-- Agent to create a new item of type G.
feature {NONE} -- Implementation
db_handler: DATABASE_HANDLER
-- Associated handler used for iteration.
end

View File

@@ -0,0 +1,538 @@
note
description: "Null object to meet void safe"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_NULL
inherit
DATABASE
feature -- Acccess
database_handle_name: STRING = "NULL"
-- Handle name
feature -- For DATABASE_STATUS
is_error_updated: BOOLEAN
-- Has an NULL function been called since last update which may have
-- updated error code, error message?
is_warning_updated: BOOLEAN
-- Has an ODBC function been called since last update which may have
-- updated warning message?
found: BOOLEAN
-- Is there any record matching the last
-- selection condition used ?
clear_error
-- Reset database error status.
do
end
insert_auto_identity_column: BOOLEAN = False
-- For INSERTs and UPDATEs should table auto-increment identity columns be explicitly included in the statement?
feature -- For DATABASE_CHANGE
descriptor_is_available: BOOLEAN
do
end
feature -- For DATABASE_FORMAT
date_to_str (object: DATE_TIME): STRING
-- String representation in SQL of `object'
-- For ODBC, ORACLE
do
create Result.make_empty
end
string_format (object: detachable STRING): STRING
-- String representation in SQL of `object'
obsolete
"Use `string_format_32' instead."
do
Result := ""
end
string_format_32 (object: detachable READABLE_STRING_GENERAL): STRING_32
-- String representation in SQL of `object'
do
Result := ""
end
True_representation: STRING
-- Database representation of the boolean True
do
Result := ""
end
False_representation: STRING
-- Database representation of the boolean False
do
Result := ""
end
feature -- For DATABASE_SELECTION, DATABASE_CHANGE
normal_parse: BOOLEAN
-- Should the SQL string be normal parsed,
-- using SQL_SCAN?
do
end
feature -- DATABASE_STRING
sql_name_string: STRING
-- SQL type name of string
do
Result := ""
end
feature -- DATABASE_REAL
sql_name_real: STRING
-- SQL type name for real
do
Result := ""
end
feature -- DATABASE_DATETIME
sql_name_datetime: STRING
-- SQL type name for datetime
do
Result := ""
end
feature -- DATABASE_DECIMAL
sql_name_decimal: STRING
-- SQL type name for decimal
do
Result := ""
end
feature -- DATABASE_DOUBLE
sql_name_double: STRING
-- SQL type name for double
do
Result := ""
end
feature -- DATABASE_CHARACTER
sql_name_character: STRING
-- SQL type name for character
do
Result := ""
end
feature -- DATABASE_INTEGER
sql_name_integer: STRING
-- SQL type name for integer
do
Result := ""
end
sql_name_integer_16: STRING
-- SQL type name for integer
do
Result := ""
end
sql_name_integer_64: STRING
-- SQL type name for integer
do
Result := ""
end
feature -- DATABASE_BOOLEAN
sql_name_boolean: STRING
-- SQL type name for boolean
do
Result := ""
end
feature -- LOGIN and DATABASE_APPL only for password_ok
password_ok (upasswd: STRING): BOOLEAN
-- Can the user password be Void?
do
end
password_ensure (name, passwd, uname, upasswd: STRING): BOOLEAN
-- Is name equal to uname and passwd equal to upasswd?
do
end
feature -- For DATABASE_PROC
support_sql_of_proc: BOOLEAN
-- Does the database support SQL attachment to the stored procedure?
do
end
support_stored_proc: BOOLEAN
-- Does the database support creating a stored procedure?
do
end
sql_as: STRING
-- Creating a stored procedure "as"...
do
Result := ""
end
sql_end: STRING
-- End of the stored procedure creation string.
do
Result := ""
end
sql_execution: STRING
-- Begining of the stored procedure execution string.
do
Result := ""
end
sql_creation: STRING
-- Begining of the stored procedure creation string.
do
Result := ""
end
sql_after_exec: STRING
-- End of the stored procedure execution string.
do
Result := ""
end
support_drop_proc: BOOLEAN
-- Does the database support stored procedure dropping from server?
do
end
name_proc_lower: BOOLEAN
-- Has the name of the stored procedure to be in lower case?
do
end
map_var_between: STRING
-- @ symbol for ODBC and Sybase
do
Result := ""
end
map_var_name_32 (par_name: READABLE_STRING_GENERAL): STRING_32
-- Redefined for Sybase
do
Result := ""
end
Select_text_32 (proc_name: READABLE_STRING_GENERAL): STRING_32
-- SQL query to get stored procedure text
do
Result := ""
end
Select_exists_32 (name: READABLE_STRING_GENERAL): STRING_32
-- SQL query to test stored procedure existing
do
Result := ""
end
Selection_string (rep_qualifier, rep_owner, repository_name: STRING): STRING
-- String to select the table needed
do
Result := ""
end
sql_string: STRING
-- Database type of a string
-- with a size less than Max_char_size
do
Result := ""
end
sql_string2 (int: INTEGER): STRING
-- Database type of a string
-- with a size more than Max_char_size
do
Result := ""
end
sql_wstring: STRING
-- Database type of a string
-- with a size less than Max_char_size
do
Result := ""
end
sql_wstring2 (int: INTEGER): STRING
-- Database type of a string
-- with a size more than Max_char_size
do
Result := ""
end
feature -- External features
get_error_message: POINTER
-- Function related with the error processing
do
create Result
end
get_error_message_string: STRING_32
-- Function related with the error processing
do
Result := ""
end
get_error_code: INTEGER
-- Function related with the error processing
do
end
get_warn_message: POINTER
-- Function related with the error processing
do
create Result
end
get_warn_message_string: STRING_32
-- Function related with the error processing
do
Result := ""
end
new_descriptor: INTEGER
-- A descriptor is used to store a row fetched by FETCH command
-- Whenever perform a SELECT statement, allocate a new descriptor
-- by int_new_descriptor(), the descriptor is freed
-- when the SELECT statement terminates.
do
end
init_order (no_descriptor: INTEGER; command: READABLE_STRING_GENERAL)
-- In DYNAMICALLY EXECUTE mode perform the SQL statement
-- But this routine only get things ready for dynamic execution:
-- 1. get the SQL statement PREPAREd; and check if there are
-- warning message for the SQL statement;
-- 2. DESCRIBE the SQL statement and get enough information to
-- allocate enough memory space for the corresponding descriptor.
do
end
start_order (no_descriptor: INTEGER)
-- Finish execution of a SQL statement in DYNAMICLLY EXECUTION mode: */
-- 1. if the PREPAREd SQL statement is a NON_SELECT statement,
-- just EXECUTE it; otherwise, DEFINE a CURSOR for it and
-- OPEN the CURSOR. In the process, if error occurs, do some
-- clearence;
do
end
next_row (no_descriptor: INTEGER)
-- A SELECT statement is now being executed in DYNAMIC EXECUTION mode,
-- the routine is to FETCH a new tuple from database
-- and if a new tuple is fetched, return 1 otherwise return 0.
do
end
terminate_order (no_descriptor: INTEGER)
-- A SQL has been performed in DYNAMIC EXECUTION mode,
-- so the routine is to do some clearence:
-- 1. if the DYNAMICALLY EXECUTED SQL statement is a NON_SELECT
-- statement, just free the memory for ODBCSQLDA and clear
-- the cell in 'descriptor' to NULL; otherwise, CLOSE the CURSOR
-- and then do the same clearence.
-- 2. return error number.
do
end
close_cursor (no_descriptor: INTEGER)
-- A SQL has been performed in DYNAMIC EXECUTION mode,
-- Then if the DYNAMICALLY EXECUTED SQL statement is a SELECT
-- statement, then the cursor is closed.
-- Then one can do an other selection on the previous cursor.
do
end
exec_immediate (no_descriptor: INTEGER; command: READABLE_STRING_GENERAL)
-- In IMMEDIATE EXECUTE mode perform the SQL statement,
-- and then check if there is warning message for the execution,
do
end
put_col_name (no_descriptor: INTEGER; index: INTEGER; ar: STRING; max_len:INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
put_data (no_descriptor: INTEGER; index: INTEGER; ar: STRING; max_len:INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
put_data_32 (no_descriptor: INTEGER; index: INTEGER; ar: STRING_32; max_len:INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
conv_type (indicator: INTEGER; index: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
--| FIXME
--| This description really does not explain a thing...
do
end
get_count (no_descriptor: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_data_len (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_col_len (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_col_type (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_integer_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_integer_16_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER_16
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_integer_64_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER_64
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_float_data (no_descriptor: INTEGER; ind: INTEGER): DOUBLE
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_real_data (no_descriptor: INTEGER; ind: INTEGER): REAL
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_boolean_data (no_descriptor: INTEGER; ind: INTEGER): BOOLEAN
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
is_null_data (no_descriptor: INTEGER; ind: INTEGER): BOOLEAN
-- Is last retrieved data null?
do
end
get_date_data (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_hour (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_sec (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_min (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_year (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_day (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_month (no_descriptor: INTEGER; ind: INTEGER): INTEGER
-- Function used to get data from structure SQLDA filled by FETCH clause.
do
end
get_decimal (no_descriptor: INTEGER; ind: INTEGER): detachable TUPLE [digits: STRING_8; sign, precision, scale: INTEGER]
-- Function used to get decimal info
do
end
database_make (i: INTEGER)
-- Initialize database c-module
do
end
connect (user_name, user_passwd, data_source, application, hostname, role_id: STRING; role_passwd: detachable STRING; group_id: STRING)
-- Connect to database
do
end
connect_by_connection_string (a_connect_string: STRING)
-- Connect to database by connection string
do
end
disconnect
-- Disconnect the current connection with an database
do
end
commit
-- Commit the current transaction
do
end
rollback
-- Commit the current transaction
do
end
trancount: INTEGER
-- Return the number of transactions now active
do
end
begin
-- Begin a data base transaction
do
end
end

View File

@@ -0,0 +1,137 @@
note
description: "Abstract Database Query"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_QUERY
inherit
SHARED_LOGGER
REFACTORING_HELPER
create
data_reader
feature -- Intialization
data_reader (a_query: STRING; a_parameters: STRING_TABLE [detachable ANY])
-- SQL data reader for the query `a_query' with arguments `a_parameters'
do
log.write_information (generator + ".data_reader" + " execute query: " + a_query)
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
query := a_query
parameters := a_parameters
ensure
query_set: query = a_query
parameters_set: parameters = a_parameters
end
execute_reader (a_base_selection: DB_SELECTION): detachable LIST [DB_RESULT]
-- Execute the Current sql query.
do
to_implement ("Check test dynamic sequel. to redesign.")
create {ARRAYED_LIST [DB_RESULT]} Result.make (100)
a_base_selection.set_container (Result)
set_map_name (a_base_selection)
a_base_selection.set_query (query)
a_base_selection.execute_query
if a_base_selection.is_ok then
a_base_selection.load_result
Result := a_base_selection.container
else
log.write_error (generator + "." + a_base_selection.error_message_32)
end
unset_map_name (a_base_selection)
a_base_selection.terminate
end
execute_change (a_base_change: DB_CHANGE)
-- Execute the Current sql query .
do
to_implement ("Check test dynamic sequel. to redesign.")
set_map_name (a_base_change)
a_base_change.set_query (query)
a_base_change.execute_query
unset_map_name (a_base_change)
end
feature -- Access
query: STRING
-- SQL query to execute.
parameters: STRING_TABLE [detachable ANY]
-- query parameters.
feature -- Status Report
has_error: BOOLEAN
-- is there an error?
error_message: detachable STRING_32
-- Error message if any.
error_code: INTEGER
-- Error code.
feature {NONE} -- Implementation
set_map_name (a_base_selection: DB_EXPRESSION)
-- Store parameters `item' and their `key'.
do
from
parameters.start
until
parameters.after
loop
a_base_selection.set_map_name (parameters.item_for_iteration, parameters.key_for_iteration)
parameters.forth
end
end
unset_map_name (a_base_selection: DB_EXPRESSION)
-- Remove parameters item associated with key `key'.
do
from
parameters.start
until
parameters.after
loop
a_base_selection.unset_map_name (parameters.key_for_iteration)
parameters.forth
end
end
log_parameters (a_parameters: like parameters): STRING
-- Parameters to log with name and value
-- exclude sensitive information.
do
create Result.make_empty
from
a_parameters.start
until
a_parameters.after
loop
Result.append ("name:")
Result.append (a_parameters.key_for_iteration.as_string_32)
Result.append (", value:")
if
a_parameters.key_for_iteration.has_substring ("Password") or else
a_parameters.key_for_iteration.has_substring ("password")
then
-- Data to exclude
else
if attached a_parameters.item_for_iteration as l_item then
Result.append (l_item.out)
end
end
Result.append ("%N")
a_parameters.forth
end
end
end -- ESA_DATABASE_QUERY

View File

@@ -0,0 +1,33 @@
note
description: "Help to encode sql queries, to prevent sql injections."
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
EIS: "SQL server injection", "src=http://blogs.msdn.com/b/raulga/archive/2007/01/04/dynamic-sql-sql-injection.aspx", "protocol=url"
expanded class
DATABASE_SQL_SERVER_ENCODER
inherit
SHARED_LOGGER
feature -- Escape SQL input
encode (a_string:READABLE_STRING_32): READABLE_STRING_32
-- Escape single quote (') and braces ([,]).
local
l_string: STRING
do
l_string := a_string.twin
if not l_string.is_empty then
l_string.replace_substring_all ("[", "[[")
l_string.replace_substring_all ("]", "]]")
if l_string.index_of ('%'', 1) > 0 then
l_string.replace_substring ("[", 1, l_string.index_of ('%'', 1))
end
if l_string.last_index_of ('%'', l_string.count) > 0 then
l_string.replace_substring ("]", l_string.last_index_of ('%'', l_string.count), l_string.count)
end
end
Result := l_string
end
end

View File

@@ -0,0 +1,193 @@
note
description: "Database Store Procedure"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
class
DATABASE_STORE_PROCEDURE
inherit
SHARED_ERROR
create
data_reader, data_writer
feature -- Intialization
data_reader (a_sp: STRING; a_parameters: HASH_TABLE [ANY, STRING_32])
-- SQL data reader for the stored procedure `a_sp' with arguments `a_parameters'.
local
l_retried: BOOLEAN
do
log.write_information (generator + ".data_reader" + " execute store procedure: " + a_sp)
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
if not l_retried then
stored_procedure := a_sp
parameters := a_parameters
create proc.make (stored_procedure)
proc.load
if not a_parameters.is_empty then
proc.set_arguments_32 (a_parameters.current_keys, a_parameters.linear_representation.to_array)
end
if proc.exists then
if proc.text_32 /= Void then
debug
log.write_debug ( generator + ".data_reader: " + proc.text_32)
end
end
else
has_error := True
error_message := proc.error_message_32
error_code := proc.error_code
log.write_error (generator + ".data_witer message:" + proc.error_message_32 + " code:" + proc.error_code.out)
end
else
stored_procedure := a_sp
parameters := a_parameters
create proc.make (stored_procedure)
end
rescue
set_last_error_from_exception ("SQL execution")
log.write_critical (generator+ ".data_reader " + last_error_message)
l_retried := True
retry
end
data_writer (a_sp: STRING; a_parameters: HASH_TABLE [ANY, STRING_32])
-- SQL data reader for the stored procedure `a_sp' with arguments `a_parameters'
local
l_retried: BOOLEAN
do
log.write_information (generator + ".data_reader" + " execute store procedure: " + a_sp)
log.write_debug (generator + ".data_reader" + " arguments:" + log_parameters (a_parameters))
if not l_retried then
stored_procedure := a_sp
parameters := a_parameters
create proc.make (stored_procedure)
proc.load
proc.set_arguments_32 (a_parameters.current_keys, a_parameters.linear_representation.to_array)
if proc.exists then
if proc.text_32 /= Void then
debug
log.write_debug ( generator + ".data_writer: " + proc.text_32)
end
end
else
has_error := True
error_message := proc.error_message_32
error_code := proc.error_code
log.write_error (generator + ".data_witer message:" + proc.error_message_32 + " code:" + proc.error_code.out)
end
else
stored_procedure := a_sp
parameters := a_parameters
create proc.make (stored_procedure)
end
rescue
set_last_error_from_exception ("SQL execution")
log.write_critical (generator+ ".data_reader " + last_error_message)
l_retried := True
retry
end
execute_reader (a_base_selection: DB_SELECTION): detachable LIST [DB_RESULT]
-- Execute the Current store procedure.
do
create {ARRAYED_LIST [DB_RESULT]} Result.make (100)
a_base_selection.set_container (Result)
set_map_name (a_base_selection)
proc.execute (a_base_selection)
a_base_selection.load_result
Result := a_base_selection.container
unset_map_name (a_base_selection)
end
execute_writer (a_base_change: DB_CHANGE)
-- Execute the Current store procedure.
do
set_map_name (a_base_change)
proc.execute (a_base_change)
unset_map_name (a_base_change)
end
feature -- Access
proc: DB_PROC
-- object to create and execute stored procedure.
parameters: HASH_TABLE [detachable ANY, STRING_32]
-- Parameters to be used by the stored procedure.
stored_procedure: STRING
-- Store procedure to execute
feature -- Status Report
has_error: BOOLEAN
-- Is there an error.
error_message: detachable STRING_32
-- Last error message.
error_code: INTEGER
-- Last error code.
feature {NONE} -- Implementation
set_map_name (a_base_selection: DB_EXPRESSION)
-- Store parameters `item' and their `key'.
do
from
parameters.start
until
parameters.after
loop
a_base_selection.set_map_name (parameters.item_for_iteration, parameters.key_for_iteration)
parameters.forth
end
end
unset_map_name (a_base_selection: DB_EXPRESSION)
-- Remove parameters item associated with key `key'.
do
from
parameters.start
until
parameters.after
loop
a_base_selection.unset_map_name (parameters.key_for_iteration)
parameters.forth
end
end
log_parameters (a_parameters: like parameters): STRING
-- Parameters to log with name and value
-- exclude sensitive information.
do
create Result.make_empty
from
a_parameters.start
until
a_parameters.after
loop
Result.append ("name:")
Result.append (a_parameters.key_for_iteration)
Result.append (", value:")
if
a_parameters.key_for_iteration.has_substring ("Password") or else
a_parameters.key_for_iteration.has_substring ("password")
then
-- Data to exclude
else
if attached a_parameters.item_for_iteration as l_item then
Result.append (l_item.out)
end
end
Result.append ("%N")
a_parameters.forth
end
end
end

View File

@@ -0,0 +1,23 @@
note
description: "Helper for paramenter Names"
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
revision: "$Revision: 95678 $"
deferred class
PARAMETER_NAME_HELPER
feature -- String
string_parameter (a_value: STRING; a_length: INTEGER): STRING
-- Adjust a parameter `a_value' to the lenght `a_length'.
require
valid_length: a_length > 0
do
if a_value.count <= a_length then
Result := a_value
else
create Result.make_from_string (a_value.substring (1, a_length))
end
end
end