Refactor persistence library.
Added a persistence speficication cluster and implementation cluser, Implementation MySQL. Added test cases for mysql implementation.
This commit is contained in:
28
persistence/implementation/mysql/persistence_mysql.ecf
Normal file
28
persistence/implementation/mysql/persistence_mysql.ecf
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="persistence_mysql" uuid="DC757CBD-D8C4-44D6-A07F-C1148D8D233E" library_target="persistence_mysql">
|
||||
<target name="persistence_mysql">
|
||||
<root all_classes="true"/>
|
||||
<option warning="true" void_safety="all">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="console_application" value="true"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="encoder" location="$ISE_LIBRARY\contrib\library\web\framework\ewf\text\encoder\encoder-safe.ecf"/>
|
||||
<library name="json" location="$ISE_LIBRARY\contrib\library\text\parser\json\library\json-safe.ecf" readonly="false"/>
|
||||
<library name="layout" location="..\..\..\layout\layout.ecf"/>
|
||||
<library name="logging" location="$ISE_LIBRARY\library\runtime\logging\logging-safe.ecf"/>
|
||||
<library name="mysql" location="$ISE_LIBRARY\library\store\dbms\rdbms\mysql\mysql-safe.ecf"/>
|
||||
<library name="store" location="$ISE_LIBRARY\library\store\store-safe.ecf" readonly="false"/>
|
||||
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
|
||||
<library name="time" location="$ISE_LIBRARY\library\time\time-safe.ecf"/>
|
||||
<cluster name="persistence_mysql" location=".\src\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
<cluster name="interface" location="..\..\interface\" recursive="true"/>
|
||||
</target>
|
||||
</system>
|
||||
1
persistence/implementation/mysql/scripts/Readme.txt
Normal file
1
persistence/implementation/mysql/scripts/Readme.txt
Normal file
@@ -0,0 +1 @@
|
||||
Added Stored Procedures
|
||||
105
persistence/implementation/mysql/scripts/create_database.sql
Normal file
105
persistence/implementation/mysql/scripts/create_database.sql
Normal file
@@ -0,0 +1,105 @@
|
||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
||||
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Schema cms
|
||||
-- -----------------------------------------------------
|
||||
CREATE SCHEMA IF NOT EXISTS `cms` DEFAULT CHARACTER SET latin1 ;
|
||||
USE `cms` ;
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms`.`nodes`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms`.`nodes` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`publication_date` DATE NOT NULL,
|
||||
`creation_date` DATE NOT NULL,
|
||||
`modification_date` DATE NOT NULL,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`summary` TEXT NOT NULL,
|
||||
`content` MEDIUMTEXT NOT NULL,
|
||||
PRIMARY KEY (`id`))
|
||||
ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 1
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms`.`roles`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms`.`roles` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`role` VARCHAR(100) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `role` (`role` ASC))
|
||||
ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 1
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms`.`users`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms`.`users` (
|
||||
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`username` VARCHAR(100) NOT NULL,
|
||||
`password` VARCHAR(100) NOT NULL,
|
||||
`salt` VARCHAR(100) NOT NULL,
|
||||
`email` VARCHAR(250) NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE INDEX `username` (`username` ASC))
|
||||
ENGINE = InnoDB
|
||||
AUTO_INCREMENT = 1
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms`.`users_nodes`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms`.`users_nodes` (
|
||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
||||
`nodes_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`users_id`, `nodes_id`),
|
||||
INDEX `fk_users_has_nodes_nodes1_idx` (`nodes_id` ASC),
|
||||
INDEX `fk_users_has_nodes_users_idx` (`users_id` ASC),
|
||||
CONSTRAINT `fk_users_has_nodes_nodes1`
|
||||
FOREIGN KEY (`nodes_id`)
|
||||
REFERENCES `cms`.`nodes` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `fk_users_has_nodes_users`
|
||||
FOREIGN KEY (`users_id`)
|
||||
REFERENCES `cms`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
-- -----------------------------------------------------
|
||||
-- Table `cms`.`users_roles`
|
||||
-- -----------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `cms`.`users_roles` (
|
||||
`users_id` INT(10) UNSIGNED NOT NULL,
|
||||
`roles_id` INT(10) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`users_id`, `roles_id`),
|
||||
INDEX `fk_users_has_roles_roles1_idx` (`roles_id` ASC),
|
||||
INDEX `fk_users_has_roles_users1_idx` (`users_id` ASC),
|
||||
CONSTRAINT `fk_users_has_roles_roles1`
|
||||
FOREIGN KEY (`roles_id`)
|
||||
REFERENCES `cms`.`roles` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION,
|
||||
CONSTRAINT `fk_users_has_roles_users1`
|
||||
FOREIGN KEY (`users_id`)
|
||||
REFERENCES `cms`.`users` (`id`)
|
||||
ON DELETE NO ACTION
|
||||
ON UPDATE NO ACTION)
|
||||
ENGINE = InnoDB
|
||||
DEFAULT CHARACTER SET = latin1;
|
||||
|
||||
|
||||
SET SQL_MODE=@OLD_SQL_MODE;
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
||||
14
persistence/implementation/mysql/scripts/tables.sql
Normal file
14
persistence/implementation/mysql/scripts/tables.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
DROP TABLE IF EXISTS nodes;
|
||||
|
||||
CREATE TABLE nodes
|
||||
(
|
||||
id smallint unsigned NOT NULL auto_increment,
|
||||
publication_date date NOT NULL, #When the article was published
|
||||
creation_date date NOT NULL, #When the article was created
|
||||
modification_date date NOT NULL, #When the article was updated
|
||||
title varchar(255) NOT NULL, #Full title of the article
|
||||
summary text NOT NULL, #A short summary of the articule
|
||||
content mediumtext NOT NULL, #The HTML content of the article
|
||||
|
||||
PRIMARY KEY (ID)
|
||||
);
|
||||
217
persistence/implementation/mysql/src/cms_storage_mysql.e
Normal file
217
persistence/implementation/mysql/src/cms_storage_mysql.e
Normal file
@@ -0,0 +1,217 @@
|
||||
note
|
||||
description: "Summary description for {CMS_STORAGE_MYSQL}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_STORAGE_MYSQL
|
||||
|
||||
inherit
|
||||
|
||||
CMS_STORAGE
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
--
|
||||
require
|
||||
is_connected: a_connection.is_connected
|
||||
do
|
||||
log.write_information (generator+".make_with_database is database connected? "+ a_connection.is_connected.out )
|
||||
create node_provider.make (a_connection)
|
||||
create user_provider.make (a_connection)
|
||||
post_node_provider_execution
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- Access: user
|
||||
|
||||
has_user: BOOLEAN
|
||||
-- Has any user?
|
||||
do
|
||||
to_implement("Not implemented!!!")
|
||||
end
|
||||
|
||||
|
||||
all_users: LIST [CMS_USER]
|
||||
do
|
||||
to_implement("Not implemented!!!")
|
||||
create {ARRAYED_LIST[CMS_USER]} Result.make (0)
|
||||
end
|
||||
|
||||
user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER
|
||||
do
|
||||
Result := user_provider.user (a_id)
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER
|
||||
do
|
||||
Result := user_provider.user_by_name (a_name)
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER
|
||||
do
|
||||
Result := user_provider.user_by_email (a_email)
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN
|
||||
local
|
||||
l_security: SECURITY_PROVIDER
|
||||
do
|
||||
if attached user_provider.user_salt (l_auth_login) as l_hash then
|
||||
if attached user_provider.user_by_name (l_auth_login) as l_user then
|
||||
create l_security
|
||||
if
|
||||
attached l_user.password as l_password and then
|
||||
l_security.password_hash (l_auth_password, l_hash).is_case_insensitive_equal (l_password)
|
||||
then
|
||||
Result := True
|
||||
else
|
||||
log.write_information (generator + ".login_valid User: wrong username or password" )
|
||||
end
|
||||
else
|
||||
log.write_information (generator + ".login_valid User:" + l_auth_login + "does not exist" )
|
||||
end
|
||||
end
|
||||
post_user_provider_execution
|
||||
end
|
||||
|
||||
feature -- Change: user
|
||||
|
||||
save_user (a_user: CMS_USER)
|
||||
-- Add a new user `a_user'.
|
||||
do
|
||||
if
|
||||
attached a_user.password as l_password and then
|
||||
attached a_user.email as l_email
|
||||
then
|
||||
user_provider.new_user (a_user.name, l_password, l_email)
|
||||
else
|
||||
-- set error
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Access: node
|
||||
|
||||
nodes: LIST[CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
|
||||
across node_provider.nodes as c loop
|
||||
Result.force (c.item)
|
||||
end
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
recent_nodes (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_NODE]
|
||||
-- List of the `a_count' most recent nodes, starting from `a_lower'.
|
||||
do
|
||||
create {ARRAYED_LIST[CMS_NODE]} Result.make (0)
|
||||
across node_provider.recent_nodes (a_lower,a_count) as c loop
|
||||
Result.force (c.item)
|
||||
end
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
node (a_id: INTEGER_64): detachable CMS_NODE
|
||||
--
|
||||
do
|
||||
Result := node_provider.node (a_id)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- Node
|
||||
|
||||
save_node (a_node: CMS_NODE)
|
||||
-- Add a new node
|
||||
do
|
||||
node_provider.new_node (a_node)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64)
|
||||
do
|
||||
node_provider.delete_node (a_id)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
update_node (a_node: CMS_NODE)
|
||||
do
|
||||
node_provider.update_node (a_node)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
update_node_title (a_id: INTEGER_64; a_title: READABLE_STRING_32)
|
||||
do
|
||||
node_provider.update_node_title (a_id, a_title)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
update_node_summary (a_id: INTEGER_64; a_summary: READABLE_STRING_32)
|
||||
do
|
||||
node_provider.update_node_summary (a_id, a_summary)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
update_node_content (a_id: INTEGER_64; a_content: READABLE_STRING_32)
|
||||
do
|
||||
node_provider.update_node_content (a_id, a_content)
|
||||
post_node_provider_execution
|
||||
end
|
||||
|
||||
|
||||
feature -- User
|
||||
|
||||
new_user (a_user: CMS_USER)
|
||||
-- Add a new user `a_user'.
|
||||
do
|
||||
if
|
||||
attached a_user.password as l_password and then
|
||||
attached a_user.email as l_email
|
||||
then
|
||||
user_provider.new_user (a_user.name, l_password, l_email)
|
||||
else
|
||||
-- set error
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Post process
|
||||
|
||||
post_node_provider_execution
|
||||
do
|
||||
if node_provider.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached node_provider.last_error then
|
||||
set_last_error_from_handler (node_provider.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
post_user_provider_execution
|
||||
do
|
||||
if user_provider.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached user_provider.last_error then
|
||||
set_last_error_from_handler (user_provider.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
node_provider: NODE_DATA_PROVIDER
|
||||
-- Node Data provider.
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- User Data provider.
|
||||
|
||||
end
|
||||
@@ -0,0 +1,132 @@
|
||||
note
|
||||
description: "Stored procedures paramters names"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
DATA_PARAMETERS_NAMES
|
||||
|
||||
feature -- Access
|
||||
|
||||
Contactid_param: STRING = "ContactID"
|
||||
|
||||
Username_param: STRING = "Username"
|
||||
|
||||
Submitter_username_param: STRING = "SubmitterUsername"
|
||||
|
||||
Responsibleid_param: STRING = "ResponsibleID"
|
||||
|
||||
Email_param: STRING = "Email"
|
||||
|
||||
Synopsis_param: STRING = "Synopsis"
|
||||
|
||||
Openonly_param: STRING = "OpenOnly"
|
||||
|
||||
Number_param: STRING = "Number"
|
||||
|
||||
Categoryid_param: STRING = "CategoryID"
|
||||
|
||||
Category_synopsis_param: STRING = "CategorySynopsis"
|
||||
|
||||
Statusid_param: STRING = "StatusID"
|
||||
|
||||
Private_param: STRING = "Private"
|
||||
|
||||
Priorityid_param: STRING = "PriorityID"
|
||||
|
||||
Severityid_param: STRING = "SeverityID"
|
||||
|
||||
Searchtext_param: STRING = "SearchText"
|
||||
|
||||
Searchsynopsis_param: STRING = "SearchSynopsis"
|
||||
|
||||
Searchdescription_param: STRING = "SearchDescription"
|
||||
|
||||
Reportid_param: STRING = "ReportID"
|
||||
|
||||
Interactionid_param: STRING = "InteractionID"
|
||||
|
||||
Attachmentid_param: STRING = "AttachmentID"
|
||||
|
||||
Fieldtitle_param: STRING = "FieldTitle"
|
||||
|
||||
Passwordhash_param: STRING = "PasswordHash"
|
||||
|
||||
Registrationtoken_param: STRING = "RegistrationToken"
|
||||
|
||||
Answerhash_param: STRING = "AnswerHash"
|
||||
|
||||
Classid_param: STRING = "Classid"
|
||||
|
||||
Confidential_param: STRING = "Confidential"
|
||||
|
||||
Release_param: STRING = "Release"
|
||||
|
||||
Environment_param: STRING = "Environment"
|
||||
|
||||
Description_param: STRING = "Description"
|
||||
|
||||
Toreproduce_param: STRING = "ToReproduce"
|
||||
|
||||
Content_param: STRING = "Content"
|
||||
|
||||
Alreadyexists_param: STRING = "AlreadyExists"
|
||||
|
||||
Firstname_param: STRING = "FirstName"
|
||||
|
||||
Lastname_param: STRING = "LastName"
|
||||
|
||||
Responsible_param: STRING = "Responsible"
|
||||
|
||||
Responsible_firstname_param: STRING = "ResponsibleFirstName"
|
||||
|
||||
Responsible_lastname_param: STRING = "ResponsibleLastName"
|
||||
|
||||
Length_param: STRING = "Length"
|
||||
|
||||
Filename_param: STRING = "Filename"
|
||||
|
||||
Position_param: STRING = "Position"
|
||||
|
||||
Address_param: STRING = "Address"
|
||||
|
||||
City_param: STRING = "City"
|
||||
|
||||
Country_param: STRING = "Country"
|
||||
|
||||
Region_param: STRING = "Region"
|
||||
|
||||
Code_param: STRING = "Code"
|
||||
|
||||
Tel_param: STRING = "Tel"
|
||||
|
||||
Fax_param: STRING = "Fax"
|
||||
|
||||
Name_param: STRING = "Name"
|
||||
|
||||
Url_param: STRING = "URL"
|
||||
|
||||
Token_param: STRING = "Token"
|
||||
|
||||
Filter_param: STRING = "Filter"
|
||||
|
||||
feature -- Login
|
||||
|
||||
Passwordsalt_param: STRING = "PasswordSalt"
|
||||
|
||||
Answersalt_param: STRING = "AnswerSalt"
|
||||
|
||||
Questionid_param: STRING = "QuestionID"
|
||||
|
||||
|
||||
feature -- Download Parameter Names
|
||||
|
||||
Subject_param: STRING = "Subject"
|
||||
|
||||
Notes_param: STRING = "Notes"
|
||||
|
||||
Platform_param: STRING = "Platform"
|
||||
|
||||
Newsletter_param: STRING = "Newsletter"
|
||||
|
||||
end
|
||||
@@ -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
|
||||
@@ -0,0 +1,103 @@
|
||||
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 -- 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
|
||||
@@ -0,0 +1,137 @@
|
||||
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_MYSQL
|
||||
|
||||
inherit
|
||||
|
||||
DATABASE_CONNECTION
|
||||
redefine
|
||||
db_application
|
||||
end
|
||||
|
||||
create
|
||||
make, make_common, make_basic, login_with_connection_string, login_with_schema
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make_common
|
||||
-- Create a database handler for MYSQL 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
|
||||
|
||||
login_with_schema (a_schema: STRING; a_username: STRING; a_password: STRING)
|
||||
-- Login with `a_connection_string'and immediately connect to database.
|
||||
do
|
||||
create db_application
|
||||
db_application.set_application (a_schema)
|
||||
db_application.login_and_connect (a_username, a_password)
|
||||
db_application.set_base
|
||||
create db_control.make
|
||||
keep_connection := is_keep_connection
|
||||
end
|
||||
|
||||
feature -- Databse Connection
|
||||
|
||||
db_application: DATABASE_APPL [MYSQL]
|
||||
-- Database application.
|
||||
|
||||
end
|
||||
@@ -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
|
||||
177
persistence/implementation/mysql/src/database/database_handler.e
Normal file
177
persistence/implementation/mysql/src/database/database_handler.e
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
538
persistence/implementation/mysql/src/database/database_null.e
Normal file
538
persistence/implementation/mysql/src/database/database_null.e
Normal 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
|
||||
137
persistence/implementation/mysql/src/database/database_query.e
Normal file
137
persistence/implementation/mysql/src/database/database_query.e
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
114
persistence/implementation/mysql/src/model/cms_node.e
Normal file
114
persistence/implementation/mysql/src/model/cms_node.e
Normal file
@@ -0,0 +1,114 @@
|
||||
note
|
||||
description: "Summary description for {NODE}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_NODE
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature{NONE} -- Initialization
|
||||
make (a_content: READABLE_STRING_32; a_summary:READABLE_STRING_32; a_title: READABLE_STRING_32)
|
||||
local
|
||||
l_time: DATE_TIME
|
||||
do
|
||||
create l_time.make_now_utc
|
||||
set_content (a_content)
|
||||
set_summary (a_summary)
|
||||
set_title (a_title)
|
||||
set_creation_date (l_time)
|
||||
set_modification_date (l_time)
|
||||
set_publication_date (l_time)
|
||||
ensure
|
||||
content_set: content = a_content
|
||||
summary_set: summary = a_summary
|
||||
title_set: title = a_title
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
content: READABLE_STRING_32
|
||||
-- Content of the node.
|
||||
|
||||
summary: READABLE_STRING_32
|
||||
-- A short summary of the node.
|
||||
|
||||
title: READABLE_STRING_32
|
||||
-- Full title of the node.
|
||||
|
||||
modification_date: DATE_TIME
|
||||
-- When the node was updated.
|
||||
|
||||
creation_date: DATE_TIME
|
||||
-- When the node was created.
|
||||
|
||||
publication_date: DATE_TIME
|
||||
-- When the node was published.
|
||||
|
||||
publication_date_output: READABLE_STRING_32
|
||||
|
||||
id: INTEGER_64 assign set_id
|
||||
-- Unique id.
|
||||
|
||||
feature -- Element change
|
||||
|
||||
set_content (a_content: like content)
|
||||
-- Assign `content' with `a_content'.
|
||||
do
|
||||
content := a_content
|
||||
ensure
|
||||
content_assigned: content = a_content
|
||||
end
|
||||
|
||||
set_summary (a_summary: like summary)
|
||||
-- Assign `summary' with `a_summary'.
|
||||
do
|
||||
summary := a_summary
|
||||
ensure
|
||||
summary_assigned: summary = a_summary
|
||||
end
|
||||
|
||||
set_title (a_title: like title)
|
||||
-- Assign `title' with `a_title'.
|
||||
do
|
||||
title := a_title
|
||||
ensure
|
||||
title_assigned: title = a_title
|
||||
end
|
||||
|
||||
set_modification_date (a_modification_date: like modification_date)
|
||||
-- Assign `modification_date' with `a_modification_date'.
|
||||
do
|
||||
modification_date := a_modification_date
|
||||
ensure
|
||||
modification_date_assigned: modification_date = a_modification_date
|
||||
end
|
||||
|
||||
set_creation_date (a_creation_date: like creation_date)
|
||||
-- Assign `creation_date' with `a_creation_date'.
|
||||
do
|
||||
creation_date := a_creation_date
|
||||
ensure
|
||||
creation_date_assigned: creation_date = a_creation_date
|
||||
end
|
||||
|
||||
set_publication_date (a_publication_date: like publication_date)
|
||||
-- Assign `publication_date' with `a_publication_date'.
|
||||
do
|
||||
publication_date := a_publication_date
|
||||
publication_date_output := publication_date.formatted_out ("yyyy/[0]mm/[0]dd")
|
||||
ensure
|
||||
publication_date_assigned: publication_date = a_publication_date
|
||||
end
|
||||
|
||||
set_id (an_id: like id)
|
||||
-- Assign `id' with `an_id'.
|
||||
do
|
||||
id := an_id
|
||||
ensure
|
||||
id_assigned: id = an_id
|
||||
end
|
||||
|
||||
end
|
||||
68
persistence/implementation/mysql/src/model/cms_user.e
Normal file
68
persistence/implementation/mysql/src/model/cms_user.e
Normal file
@@ -0,0 +1,68 @@
|
||||
note
|
||||
description: "Summary description for {USER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
CMS_USER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_name: READABLE_STRING_32)
|
||||
-- Create an object with name `a_name'.
|
||||
do
|
||||
name := a_name
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
id: INTEGER_64
|
||||
-- Unique id.
|
||||
|
||||
name: READABLE_STRING_32
|
||||
-- User name.
|
||||
|
||||
password: detachable READABLE_STRING_32
|
||||
-- User password.
|
||||
|
||||
email: detachable READABLE_STRING_32
|
||||
-- User email.
|
||||
|
||||
feature -- Change element
|
||||
|
||||
set_id (a_id: like id)
|
||||
-- Set `id' with `a_id'.
|
||||
do
|
||||
id := a_id
|
||||
ensure
|
||||
id_set: id = a_id
|
||||
end
|
||||
|
||||
set_name (n: like name)
|
||||
-- Set `name' with `n'.
|
||||
do
|
||||
name := n
|
||||
ensure
|
||||
name_set: name = n
|
||||
end
|
||||
|
||||
set_password (p: like password)
|
||||
-- Set `password' with `p'.
|
||||
do
|
||||
password := p
|
||||
ensure
|
||||
password_set: password = p
|
||||
end
|
||||
|
||||
set_email (m: like email)
|
||||
-- Set `email' with `m'.
|
||||
do
|
||||
email := m
|
||||
ensure
|
||||
email_set: email = m
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,272 @@
|
||||
note
|
||||
description: "Database access for node uses cases."
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
NODE_DATA_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
PARAMETER_NAME_HELPER
|
||||
|
||||
SHARED_ERROR
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
-- Create a data provider.
|
||||
do
|
||||
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := db_handler.successful
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
nodes: DATABASE_ITERATION_CURSOR [CMS_NODE]
|
||||
-- List of nodes.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (0)
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_nodes, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_node)
|
||||
post_execution
|
||||
end
|
||||
|
||||
recent_nodes (a_lower, a_rows: INTEGER): DATABASE_ITERATION_CURSOR [CMS_NODE]
|
||||
-- The most recent `a_rows'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_query: STRING
|
||||
do
|
||||
log.write_information (generator + ".recent_nodes")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_rows, "rows")
|
||||
create l_query.make_from_string (select_recent_nodes)
|
||||
l_query.replace_substring_all ("$offset", a_lower.out)
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (l_query, l_parameters))
|
||||
db_handler.execute_query
|
||||
create Result.make (db_handler, agent fetch_node)
|
||||
post_execution
|
||||
end
|
||||
|
||||
node (a_id: INTEGER_64): detachable CMS_NODE
|
||||
-- Node for the given id `a_id', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id,"id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_node_by_id, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_node
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Basic operations
|
||||
|
||||
new_node (a_node: CMS_NODE)
|
||||
-- Create a new node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (6)
|
||||
l_parameters.put (a_node.title, "title")
|
||||
l_parameters.put (a_node.summary, "summary")
|
||||
l_parameters.put (a_node.content, "content")
|
||||
l_parameters.put (a_node.publication_date, "publication_date")
|
||||
l_parameters.put (a_node.creation_date, "creation_date")
|
||||
l_parameters.put (a_node.modification_date, "modification_date")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node_title (a_id: INTEGER_64; a_title: READABLE_STRING_32)
|
||||
-- Update node title for the corresponding the report with id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_title, "title")
|
||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
|
||||
l_parameters.put (a_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_title, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node_summary (a_id: INTEGER_64; a_summary: READABLE_STRING_32)
|
||||
-- Update node summary for the corresponding the report with id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_summary, "summary")
|
||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
|
||||
l_parameters.put (a_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_summary, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node_content (a_id: INTEGER_64; a_content: READABLE_STRING_32)
|
||||
-- Update node content for the corresponding the report with id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_content, "content")
|
||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
|
||||
l_parameters.put (a_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node_content, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
update_node (a_node: CMS_NODE)
|
||||
-- Update node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (7)
|
||||
l_parameters.put (a_node.title, "title")
|
||||
l_parameters.put (a_node.summary, "summary")
|
||||
l_parameters.put (a_node.content, "content")
|
||||
l_parameters.put (a_node.publication_date, "publication_date")
|
||||
l_parameters.put (a_node.creation_date, "creation_date")
|
||||
l_parameters.put (create {DATE_TIME}.make_now_utc, "modification_date")
|
||||
l_parameters.put (a_node.id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_update_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
delete_node (a_id: INTEGER_64;)
|
||||
-- Delete node with id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_delete_node, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- Connection
|
||||
|
||||
connect
|
||||
-- Connect to the database.
|
||||
do
|
||||
if not db_handler.is_connected then
|
||||
db_handler.connect
|
||||
end
|
||||
end
|
||||
|
||||
disconnect
|
||||
-- Disconnect to the database.
|
||||
do
|
||||
if db_handler.is_connected then
|
||||
db_handler.disconnect
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Queries
|
||||
|
||||
Select_nodes: STRING = "select * from Nodes;"
|
||||
-- SQL Query to retrieve all nodes.
|
||||
|
||||
Select_node_by_id: STRING = "select * from Nodes where id =:id order by id desc, publication_date desc;"
|
||||
|
||||
Select_recent_nodes: STRING = "select * from Nodes order by id desc, publication_date desc Limit $offset , :rows "
|
||||
|
||||
SQL_Insert_node: STRING = "insert into nodes (title, summary, content, publication_date, creation_date, modification_date) values (:title, :summary, :content, :publication_date, :creation_date, :modification_date);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
SQL_Update_node_title: STRING ="update nodes SET title=:title, modification_date=:modification_date where id=:id;"
|
||||
-- SQL update node title.
|
||||
|
||||
SQL_Update_node_summary: STRING ="update nodes SET summary=:summary, modification_date=:modification_date where id=:id;"
|
||||
-- SQL update node summary.
|
||||
|
||||
SQL_Update_node_content: STRING ="update nodes SET content=:content, modification_date=:modification_date where id=:id;"
|
||||
-- SQL node content.
|
||||
|
||||
SQL_Update_node : STRING = "update nodes SET title=:title, summary=:summary, content=:content, publication_date=:publication_date, creation_date=:creation_date, modification_date=:modification_date where id=:id;"
|
||||
-- SQL node.
|
||||
|
||||
SQL_Delete_node: STRING = "delete from nodes where id=:id;"
|
||||
|
||||
|
||||
feature -- New Object
|
||||
|
||||
fetch_node: CMS_NODE
|
||||
do
|
||||
create Result.make ("", "", "")
|
||||
if attached db_handler.read_integer_32 (1) as l_id then
|
||||
Result.set_id (l_id)
|
||||
end
|
||||
if attached db_handler.read_date_time (2) as l_pd then
|
||||
Result.set_publication_date (l_pd)
|
||||
end
|
||||
if attached db_handler.read_date_time (3) as l_cd then
|
||||
Result.set_creation_date (l_cd)
|
||||
end
|
||||
if attached db_handler.read_date_time (4) as l_md then
|
||||
Result.set_modification_date (l_md)
|
||||
end
|
||||
if attached db_handler.read_string (5) as l_t then
|
||||
Result.set_title (l_t)
|
||||
end
|
||||
if attached db_handler.read_string (6) as l_s then
|
||||
Result.set_summary (l_s)
|
||||
end
|
||||
if attached db_handler.read_string (7) as l_c then
|
||||
Result.set_content (l_c)
|
||||
end
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
if db_handler.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached db_handler.last_error then
|
||||
set_last_error_from_handler (db_handler.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,182 @@
|
||||
note
|
||||
description: "Summary description for {USER_DATA_PROVIDER}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
USER_DATA_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
PARAMETER_NAME_HELPER
|
||||
|
||||
SHARED_ERROR
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature -- Initialization
|
||||
|
||||
make (a_connection: DATABASE_CONNECTION)
|
||||
-- Create a data provider.
|
||||
do
|
||||
create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection)
|
||||
post_execution
|
||||
end
|
||||
|
||||
db_handler: DATABASE_HANDLER
|
||||
-- Db handler.
|
||||
|
||||
feature -- Status Report
|
||||
|
||||
is_successful: BOOLEAN
|
||||
-- Is the last execution sucessful?
|
||||
do
|
||||
Result := db_handler.successful
|
||||
end
|
||||
|
||||
feature -- Basic Operations
|
||||
|
||||
new_user (a_user_name: READABLE_STRING_32; a_password: READABLE_STRING_32; a_email: READABLE_STRING_32)
|
||||
-- Create a new node.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
l_password_salt, l_password_hash: STRING
|
||||
l_security: SECURITY_PROVIDER
|
||||
do
|
||||
create l_security
|
||||
l_password_salt := l_security.salt
|
||||
l_password_hash := l_security.password_hash (a_password, l_password_salt)
|
||||
|
||||
log.write_information (generator + ".new_user")
|
||||
create l_parameters.make (4)
|
||||
l_parameters.put (a_user_name,"username")
|
||||
l_parameters.put (l_password_hash,"password")
|
||||
l_parameters.put (l_password_salt,"salt")
|
||||
l_parameters.put (a_email,"email")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (sql_insert_user, l_parameters))
|
||||
db_handler.execute_change
|
||||
post_execution
|
||||
end
|
||||
|
||||
user (a_id: INTEGER_64): detachable CMS_USER
|
||||
-- User for the given id `a_id', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id,"id")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_id, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_user
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
user_by_name (a_name: READABLE_STRING_32): detachable CMS_USER
|
||||
-- User for the given name `a_name', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".user_by_name")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_name,"name")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_name, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_user
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
|
||||
user_by_email (a_email: detachable READABLE_STRING_32): detachable CMS_USER
|
||||
-- User for the given email `a_email', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
log.write_information (generator + ".user_by_name")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_email,"email")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_user_by_email, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
Result := fetch_user
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
user_salt (a_username: READABLE_STRING_32): detachable READABLE_STRING_32
|
||||
-- User salt for the given user `a_username', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
log.write_information (generator + ".nodes")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_username,"name")
|
||||
db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_salt_by_username, l_parameters))
|
||||
db_handler.execute_query
|
||||
if db_handler.count = 1 then
|
||||
if attached db_handler.read_string (1) as l_salt then
|
||||
Result := l_salt.as_string_32
|
||||
end
|
||||
end
|
||||
post_execution
|
||||
end
|
||||
|
||||
feature -- New Object
|
||||
|
||||
fetch_user: CMS_USER
|
||||
do
|
||||
create Result.make ("")
|
||||
if attached db_handler.read_integer_32 (1) as l_id then
|
||||
Result.set_id (l_id)
|
||||
end
|
||||
if attached db_handler.read_string (2) as l_u then
|
||||
Result.set_name (l_u)
|
||||
end
|
||||
if attached db_handler.read_string (3) as l_p then
|
||||
Result.set_password (l_p)
|
||||
end
|
||||
if attached db_handler.read_string (5) as l_e then
|
||||
Result.set_email (l_e)
|
||||
end
|
||||
end
|
||||
|
||||
feature -- Sql Queries
|
||||
|
||||
Select_user_by_id: STRING = "select * from Users where id =:id;"
|
||||
-- Retrieve user by id if exists.
|
||||
|
||||
Select_user_by_name: STRING = "select * from Users where username =:name;"
|
||||
-- Retrieve user by name if exists.
|
||||
|
||||
Select_user_by_email: STRING = "select * from Users where email =:email;"
|
||||
-- Retrieve user by email if exists.
|
||||
|
||||
Select_salt_by_username: STRING = "select salt from Users where username =:name;"
|
||||
-- Retrieve salt by username if exists.
|
||||
|
||||
SQL_Insert_user: STRING = "insert into users (username, password, salt, email) values (:username, :password, :salt, :email);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
post_execution
|
||||
-- Post database execution.
|
||||
do
|
||||
if db_handler.successful then
|
||||
set_successful
|
||||
else
|
||||
if attached db_handler.last_error then
|
||||
set_last_error_from_handler (db_handler.last_error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,153 @@
|
||||
note
|
||||
description: "Provides security routine helpers"
|
||||
date: "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision: "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
SECURITY_PROVIDER
|
||||
|
||||
inherit
|
||||
|
||||
REFACTORING_HELPER
|
||||
|
||||
feature -- Access
|
||||
|
||||
token: STRING
|
||||
-- Cryptographic random base 64 string.
|
||||
do
|
||||
Result := salt_with_size (5)
|
||||
-- Remove trailing equal sign
|
||||
Result.keep_head (Result.count - 1)
|
||||
end
|
||||
|
||||
salt: STRING
|
||||
-- Cryptographic random number of 16 bytes.
|
||||
do
|
||||
Result := salt_with_size (16)
|
||||
end
|
||||
|
||||
password: STRING
|
||||
-- Cryptographic random password of 10 bytes.
|
||||
do
|
||||
Result := salt_with_size (10)
|
||||
-- Remove trailing equal signs
|
||||
Result.keep_head (Result.count - 2)
|
||||
end
|
||||
|
||||
password_hash (a_password, a_salt: STRING): STRING
|
||||
-- Password hash based on password `a_password' and salt value `a_salt'.
|
||||
do
|
||||
Result := sha1_string (a_password + a_salt )
|
||||
end
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
salt_with_size (a_val: INTEGER): STRING
|
||||
-- Return a salt with size `a_val'.
|
||||
local
|
||||
l_salt: SALT_XOR_SHIFT_64_GENERATOR
|
||||
l_array: ARRAY [INTEGER_8]
|
||||
i: INTEGER
|
||||
do
|
||||
create l_salt.make (a_val)
|
||||
create l_array.make_empty
|
||||
i := 1
|
||||
across
|
||||
l_salt.new_sequence as c
|
||||
loop
|
||||
l_array.force (c.item.as_integer_8, i)
|
||||
i := i + 1
|
||||
end
|
||||
Result := encode_base_64 (l_array)
|
||||
end
|
||||
|
||||
sha1_string (a_str: STRING): STRING
|
||||
-- SHA1 diggest of `a_str'.
|
||||
do
|
||||
sha1.update_from_string (a_str)
|
||||
Result := sha1.digest_as_string
|
||||
sha1.reset
|
||||
end
|
||||
|
||||
sha1: SHA1
|
||||
-- Create a SHA1 object.
|
||||
once
|
||||
create Result.make
|
||||
end
|
||||
|
||||
feature -- Encoding
|
||||
|
||||
|
||||
encode_base_64 (bytes: SPECIAL [INTEGER_8]): STRING_8
|
||||
-- Encodes a byte array into a STRING doing base64 encoding.
|
||||
local
|
||||
l_output: SPECIAL [INTEGER_8]
|
||||
l_remaining: INTEGER
|
||||
i, ptr: INTEGER
|
||||
char: CHARACTER
|
||||
do
|
||||
to_implement ("Check existing code to do that!!!.")
|
||||
create l_output.make_filled (0, ((bytes.count + 2) // 3) * 4)
|
||||
l_remaining := bytes.count
|
||||
from
|
||||
i := 0
|
||||
ptr := 0
|
||||
until
|
||||
l_remaining <= 3
|
||||
loop
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF))
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i + 1] & 0xF) |<< 2) | ((bytes [i + 2] |>> 6) & 0x3))
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (bytes [i + 2] & 0x3F)
|
||||
ptr := ptr + 1
|
||||
l_remaining := l_remaining - 3
|
||||
i := i + 3
|
||||
end
|
||||
-- encode when exactly 1 element (left) to encode
|
||||
char := '='
|
||||
if l_remaining = 1 then
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i]) & 0x3) |<< 4)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
end
|
||||
|
||||
-- encode when exactly 2 elements (left) to encode
|
||||
if l_remaining = 2 then
|
||||
l_output [ptr] := encode_value (bytes [i] |>> 2)
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value (((bytes [i] & 0x3) |<< 4) | ((bytes [i + 1] |>> 4) & 0xF));
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := encode_value ((bytes [i + 1] & 0xF) |<< 2);
|
||||
ptr := ptr + 1
|
||||
l_output [ptr] := char.code.as_integer_8
|
||||
ptr := ptr + 1
|
||||
end
|
||||
Result := ""
|
||||
across
|
||||
l_output as elem
|
||||
loop
|
||||
Result.append_character (elem.item.to_character_8)
|
||||
end
|
||||
end
|
||||
|
||||
base64_map: SPECIAL [CHARACTER_8]
|
||||
-- Table for Base64 encoding.
|
||||
once
|
||||
Result := ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").area
|
||||
end
|
||||
|
||||
encode_value (i: INTEGER_8): INTEGER_8
|
||||
-- Encode `i'.
|
||||
do
|
||||
Result := base64_map [i & 0x3F].code.as_integer_8
|
||||
end
|
||||
|
||||
end
|
||||
53
persistence/implementation/mysql/src/string_helper.e
Normal file
53
persistence/implementation/mysql/src/string_helper.e
Normal file
@@ -0,0 +1,53 @@
|
||||
note
|
||||
description: "Summary description for {STRING_HELPER}."
|
||||
date: "$Date: 2014-08-08 16:02:11 -0300 (vi., 08 ago. 2014) $"
|
||||
revision: "$Revision: 95593 $"
|
||||
|
||||
class
|
||||
STRING_HELPER
|
||||
|
||||
feature -- Access
|
||||
|
||||
is_blank (s: detachable READABLE_STRING_32): BOOLEAN
|
||||
local
|
||||
i,n: INTEGER
|
||||
do
|
||||
Result := True
|
||||
if s /= Void then
|
||||
from
|
||||
i := 1
|
||||
n := s.count
|
||||
until
|
||||
i > n or not Result
|
||||
loop
|
||||
Result := s[i].is_space
|
||||
i := i + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
indented_text (pre: READABLE_STRING_8; t: READABLE_STRING_8): READABLE_STRING_8
|
||||
-- Indendted text.
|
||||
local
|
||||
s8: STRING_8
|
||||
do
|
||||
s8 := t.string
|
||||
s8.prepend (pre)
|
||||
s8.replace_substring_all ("%N", "%N" + pre)
|
||||
Result := s8
|
||||
end
|
||||
|
||||
|
||||
json_encode (a_string: STRING): STRING
|
||||
-- json encode `a_string'.
|
||||
local
|
||||
encode: SHARED_JSON_ENCODER
|
||||
do
|
||||
create encode
|
||||
Result := encode.json_encoder.encoded_string (a_string)
|
||||
debug
|
||||
print ("%NResult" + Result)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
55
persistence/implementation/mysql/tests/application.e
Normal file
55
persistence/implementation/mysql/tests/application.e
Normal file
@@ -0,0 +1,55 @@
|
||||
note
|
||||
description : "tests application root class"
|
||||
date : "$Date: 2014-08-20 15:21:15 -0300 (mi., 20 ago. 2014) $"
|
||||
revision : "$Revision: 95678 $"
|
||||
|
||||
class
|
||||
APPLICATION
|
||||
|
||||
inherit
|
||||
ARGUMENTS
|
||||
|
||||
create
|
||||
make
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make
|
||||
-- Run application.
|
||||
local
|
||||
user: USER_DATA_PROVIDER
|
||||
node: NODE_DATA_PROVIDER
|
||||
l_security: SECURITY_PROVIDER
|
||||
do
|
||||
create connection.login_with_schema ("cms", "root", "")
|
||||
-- create user.make (connection)
|
||||
---- user.new_user ("jv", "test","test@test.com")
|
||||
|
||||
-- if attached user.user (3) as l_user then
|
||||
-- if attached user.user_salt ("jv") as l_salt then
|
||||
-- create l_security
|
||||
-- if attached l_user.password as l_password then
|
||||
-- print (l_password)
|
||||
-- io.put_new_line
|
||||
-- print (l_security.password_hash ("test", l_salt))
|
||||
|
||||
-- check same_string: l_security.password_hash ("test", l_salt).is_case_insensitive_equal (l_password) end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if attached user.user_by_name ("jv") as l_user then
|
||||
-- check l_user.id = 3 end
|
||||
-- end
|
||||
|
||||
create node.make (connection)
|
||||
across node.recent_nodes (0, 5) as c loop
|
||||
print (c.item)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
connection: DATABASE_CONNECTION_MYSQL
|
||||
|
||||
end
|
||||
26
persistence/implementation/mysql/tests/nodes/node_test_set.e
Normal file
26
persistence/implementation/mysql/tests/nodes/node_test_set.e
Normal file
@@ -0,0 +1,26 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
NODE_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
new_test_routine
|
||||
-- New test routine
|
||||
do
|
||||
assert ("not_implemented", False)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
22
persistence/implementation/mysql/tests/tests.ecf
Normal file
22
persistence/implementation/mysql/tests/tests.ecf
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="tests">
|
||||
<target name="tests">
|
||||
<root class="APPLICATION" feature="make"/>
|
||||
<option warning="true" void_safety="conformance">
|
||||
<assertions precondition="true" postcondition="true" check="true" invariant="true" loop="true" supplier_precondition="true"/>
|
||||
</option>
|
||||
<setting name="concurrency" value="thread"/>
|
||||
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
|
||||
<library name="crypto" location="$ISE_LIBRARY\unstable\library\text\encryption\crypto\crypto-safe.ecf"/>
|
||||
<library name="persitence_mysql" location="..\persistence_mysql.ecf" readonly="false"/>
|
||||
<library name="testing" location="$ISE_LIBRARY\library\testing\testing-safe.ecf"/>
|
||||
<library name="process" location="$ISE_LIBRARY\library\process\process-safe.ecf"/>
|
||||
<cluster name="tests" location=".\" recursive="true">
|
||||
<file_rule>
|
||||
<exclude>/EIFGENs$</exclude>
|
||||
<exclude>/CVS$</exclude>
|
||||
<exclude>/.svn$</exclude>
|
||||
</file_rule>
|
||||
</cluster>
|
||||
</target>
|
||||
</system>
|
||||
78
persistence/implementation/mysql/tests/users/user_test_set.e
Normal file
78
persistence/implementation/mysql/tests/users/user_test_set.e
Normal file
@@ -0,0 +1,78 @@
|
||||
note
|
||||
description: "[
|
||||
Eiffel tests that can be executed by testing tool.
|
||||
]"
|
||||
author: "EiffelStudio test wizard"
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
testing: "type/manual"
|
||||
|
||||
class
|
||||
USER_TEST_SET
|
||||
|
||||
inherit
|
||||
EQA_TEST_SET
|
||||
redefine
|
||||
on_prepare,
|
||||
on_clean
|
||||
select
|
||||
default_create
|
||||
end
|
||||
ABSTRACT_DB_TEST
|
||||
rename
|
||||
default_create as default_db_test
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Events
|
||||
|
||||
on_prepare
|
||||
-- <Precursor>
|
||||
do
|
||||
(create {CLEAN_DB}).clean_db(connection)
|
||||
user_provider.new_user ("admin", "admin","admin@admin.com")
|
||||
end
|
||||
|
||||
on_clean
|
||||
-- <Precursor>
|
||||
do
|
||||
end
|
||||
|
||||
feature -- Test routines
|
||||
|
||||
test_user_exist
|
||||
-- User admin exist
|
||||
do
|
||||
assert ("Not void", attached user_provider.user_by_email ("admin@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (1))
|
||||
assert ("Not void", attached user_provider.user_by_name ("admin"))
|
||||
end
|
||||
|
||||
test_user_not_exist
|
||||
-- Uset test does not exist.
|
||||
do
|
||||
assert ("Void", user_provider.user_by_email ("test@admin.com") = Void)
|
||||
assert ("Void", user_provider.user(2) = Void )
|
||||
assert ("Void", user_provider.user_by_name ("test") = Void)
|
||||
end
|
||||
|
||||
test_new_user
|
||||
do
|
||||
user_provider.new_user ("test", "test","test@admin.com")
|
||||
assert ("Not void", attached user_provider.user_by_email ("test@admin.com"))
|
||||
assert ("Not void", attached user_provider.user (2))
|
||||
assert ("Not void", attached user_provider.user (2) as l_user and then l_user.id = 2 and then l_user.name ~ "test")
|
||||
assert ("Not void", attached user_provider.user_by_name ("test"))
|
||||
end
|
||||
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
user_provider: USER_DATA_PROVIDER
|
||||
-- user provider.
|
||||
once
|
||||
create Result.make (connection)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
note
|
||||
description: "Summary description for {ABSTRACT_DB_TEST}."
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
|
||||
class
|
||||
ABSTRACT_DB_TEST
|
||||
|
||||
|
||||
feature -- Database connection
|
||||
|
||||
connection: DATABASE_CONNECTION_MYSQL
|
||||
-- MYSQL database connection
|
||||
once
|
||||
create Result.login_with_schema ("cms_dev", "root", "")
|
||||
end
|
||||
end
|
||||
66
persistence/implementation/mysql/tests/util/clean_db.e
Normal file
66
persistence/implementation/mysql/tests/util/clean_db.e
Normal file
@@ -0,0 +1,66 @@
|
||||
note
|
||||
description: "[
|
||||
Setting up database tests
|
||||
1. Put the database in a known state before running your test suite.
|
||||
2. Data reinitialization. For testing in developer sandboxes, something that you should do every time you rebuild the system, you may want to forgo dropping and rebuilding the database in favor of simply reinitializing the source data.
|
||||
You can do this either by erasing all existing data and then inserting the initial data vales back into the database, or you can simple run updates to reset the data values.
|
||||
The first approach is less risky and may even be faster for large amounts of data. - See more at: http://www.agiledata.org/essays/databaseTesting.html#sthash.6yVp35g8.dpuf
|
||||
]"
|
||||
|
||||
date: "$Date$"
|
||||
revision: "$Revision$"
|
||||
EIS: "name=Database Testing", "src=http://www.agiledata.org/essays/databaseTesting.html", "protocol=uri"
|
||||
|
||||
class
|
||||
CLEAN_DB
|
||||
|
||||
feature
|
||||
|
||||
clean_db (a_connection: DATABASE_CONNECTION)
|
||||
-- Clean db test.
|
||||
local
|
||||
l_parameters: STRING_TABLE[STRING]
|
||||
do
|
||||
create l_parameters.make (0)
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_nodes, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Clean Users
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Sql_delete_users, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
-- Reset Autoincremente
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_users_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
|
||||
db_handler(a_connection).set_query (create {DATABASE_QUERY}.data_reader (Rest_nodes_autoincrement, l_parameters))
|
||||
db_handler(a_connection).execute_change
|
||||
end
|
||||
|
||||
|
||||
|
||||
feature -- Database Hanlder
|
||||
|
||||
db_handler (a_connection: DATABASE_CONNECTION): DATABASE_HANDLER
|
||||
-- Db handler
|
||||
once
|
||||
create {DATABASE_HANDLER_IMPL} Result.make (a_connection)
|
||||
end
|
||||
|
||||
|
||||
feature -- Sql delete queries
|
||||
|
||||
Sql_delete_users: STRING = "delete from Users"
|
||||
-- Clean Users.
|
||||
|
||||
Sql_delete_nodes: STRING = "delete from Nodes"
|
||||
-- Clean Nodes.
|
||||
|
||||
Rest_users_autoincrement: STRING = "ALTER TABLE Users AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement
|
||||
|
||||
Rest_nodes_autoincrement: STRING = "ALTER TABLE Nodes AUTO_INCREMENT = 1"
|
||||
-- reset autoincrement.
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user