From 5cb26f0b24fdee9ff5d38b4fbe55632fce6d226a Mon Sep 17 00:00:00 2001 From: jvelilla Date: Fri, 17 Oct 2014 08:53:02 -0300 Subject: [PATCH] Updated Peristance layer to use the new error_hanler based on EWF error library. Remove once use from DATABASE_ERROR_HANDLER. Initial support transaction handling. --- .../implementation/common/cms_storage_null.e | 14 + .../common/database/database_connection.e | 162 ++------ .../database/database_connection_null.e | 1 + .../common/database/database_handler.e | 29 +- .../common/database/database_handler_impl.e | 7 +- .../common/database/database_query.e | 4 +- .../database/database_storage_manager.e | 371 ------------------ .../{ => error}/database_no_change_error.e | 0 .../database/error/shared_error_handler.e | 39 -- .../mysql/src/cms_storage_mysql.e | 54 +-- .../src/database/database_connection_mysql.e | 9 +- .../mysql/src/provider/node_data_provider.e | 38 +- .../mysql/src/provider/user_data_provider.e | 26 +- .../tests/handler/database_handler_test.e | 81 ++++ .../mysql/tests/nodes/node_test_set.e | 14 +- .../implementation/mysql/tests/tests.ecf | 1 + .../tests/transactions/transaction_test_set.e | 71 ---- persistence/interface/cms_storage.e | 7 +- 18 files changed, 254 insertions(+), 674 deletions(-) delete mode 100644 persistence/implementation/common/database/database_storage_manager.e rename persistence/implementation/common/database/{ => error}/database_no_change_error.e (100%) delete mode 100644 persistence/implementation/common/database/error/shared_error_handler.e create mode 100644 persistence/implementation/mysql/tests/handler/database_handler_test.e diff --git a/persistence/implementation/common/cms_storage_null.e b/persistence/implementation/common/cms_storage_null.e index c82e9b6..89eb3df 100644 --- a/persistence/implementation/common/cms_storage_null.e +++ b/persistence/implementation/common/cms_storage_null.e @@ -9,8 +9,22 @@ class inherit CMS_STORAGE + redefine + default_create + select + default_create + end REFACTORING_HELPER + rename + default_create as default_create_rh + end +feature -- Initialization + + default_create + do + create error_handler.make + end feature -- Access: user diff --git a/persistence/implementation/common/database/database_connection.e b/persistence/implementation/common/database/database_connection.e index a6c2d2c..5f0e9f7 100644 --- a/persistence/implementation/common/database/database_connection.e +++ b/persistence/implementation/common/database/database_connection.e @@ -10,8 +10,6 @@ inherit DATABASE_CONFIG - SHARED_ERROR_HANDLER - feature {NONE} -- Initialization make_common @@ -131,142 +129,6 @@ feature -- Transactions retry end - -feature -- - - is_connected_to_storage: BOOLEAN - -- Is connected to the database - do - Result := db_control.is_connected - end - -feature -- Transaction Status - - in_transaction_session: BOOLEAN - -- Is session started? - - transaction_session_depth: INTEGER - -- Depth in the transaction session - -feature -- Transaction Operation - - begin_transaction2 - -- Start session - -- if already started, increase the `transaction_session_depth' - require - in_transaction_session implies transaction_session_depth > 0 - not in_transaction_session implies transaction_session_depth = 0 - local - l_session_control: like db_control - l_retried: INTEGER - do - if l_retried = 0 then - if not in_transaction_session then - database_error_handler.reset - - check transaction_session_depth = 0 end - - debug ("database_session") - print ("..Start session%N") - end - connect -- connect the DB - if is_connected_to_storage then - in_transaction_session := True - db_control.begin -- start transaction - else - l_session_control := db_control - if not l_session_control.is_ok then - database_error_handler.add_database_error (l_session_control.error_message_32, l_session_control.error_code) - else - database_error_handler.add_database_error ("Session_not_started_error_message", 0) - end - l_session_control.reset - end - end - transaction_session_depth := transaction_session_depth + 1 - else - if l_retried = 1 then - transaction_session_depth := transaction_session_depth + 1 - if attached (create {EXCEPTION_MANAGER}).last_exception as e then - if attached {ASSERTION_VIOLATION} e then - --| Ignore for now with MYSQL ... - else - exception_as_error (e) - end - end - - in_transaction_session := False - db_control.reset - else - in_transaction_session := False - end - end - ensure - transaction_session_depth = (old transaction_session_depth) + 1 - rescue - l_retried := l_retried + 1 - retry - end - - commit2 - -- End session - local - l_retried: BOOLEAN - do - if not l_retried then - transaction_session_depth := transaction_session_depth - 1 - if transaction_session_depth = 0 then - debug ("database_session") - print ("..End session%N") - end - if is_connected_to_storage then - if not database_error_handler.has_error then - db_control.commit -- Commit transaction - else - db_control.rollback -- Rollback transaction - end - end - in_transaction_session := False - end - else - exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) - in_transaction_session := False - transaction_session_depth := transaction_session_depth - 1 - db_control.reset - end - rescue - l_retried := True - retry - end - - - - rollback2 - -- End session - local - l_retried: BOOLEAN - do - if not l_retried then - transaction_session_depth := transaction_session_depth - 1 - if transaction_session_depth = 0 then - debug ("database_session") - print ("..End session%N") - end - if is_connected_to_storage then - db_control.rollback -- Rollback transaction - end - in_transaction_session := False - end - else - exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) - in_transaction_session := False - transaction_session_depth := transaction_session_depth - 1 - db_control.reset - end - rescue - l_retried := True - retry - end feature -- Change Element not_keep_connection @@ -302,4 +164,28 @@ feature -- Conection Result := db_control.is_connected end +feature -- Error Handling + + database_error_handler: DATABASE_ERROR_HANDLER + -- Error handler. + +feature -- Status Report + + has_error: BOOLEAN + -- Has error? + do + Result := database_error_handler.has_error + end + +feature -- Helper + + exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) + -- Record exception as an error. + do + if attached a_e as l_e and then attached l_e.trace as l_trace then + database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) + end + end + + end diff --git a/persistence/implementation/common/database/database_connection_null.e b/persistence/implementation/common/database/database_connection_null.e index d9257b3..ec54d13 100644 --- a/persistence/implementation/common/database/database_connection_null.e +++ b/persistence/implementation/common/database/database_connection_null.e @@ -22,6 +22,7 @@ feature -- Initialization make_common -- Create a database handler for ODBC with common settings. do + create database_error_handler.make create db_application.login (username, password) db_application.set_hostname (hostname) db_application.set_data_source (database_name) diff --git a/persistence/implementation/common/database/database_handler.e b/persistence/implementation/common/database/database_handler.e index 875b7a7..3517ff3 100644 --- a/persistence/implementation/common/database/database_handler.e +++ b/persistence/implementation/common/database/database_handler.e @@ -8,7 +8,7 @@ deferred class inherit - SHARED_ERROR_HANDLER + SHARED_LOGGER feature -- Access @@ -178,6 +178,7 @@ feature -- Error handling if attached db_change as l_change and then not l_change.is_ok then database_error_handler.add_database_error (l_change.error_message_32, l_change.error_code) log.write_error (generator + ".check_database_change_error: " + l_change.error_message_32) + l_change.reset end end @@ -187,10 +188,34 @@ feature -- Error handling if attached db_selection as l_selection and then not l_selection.is_ok then database_error_handler.add_database_error (l_selection.error_message_32, l_selection.error_code) log.write_error (generator + ".check_database_selection_error: " + l_selection.error_message_32) + l_selection.reset end end -feature {NODE_DATA_PROVIDER}-- Implementation +feature -- Error Handling + + database_error_handler: DATABASE_ERROR_HANDLER + -- Error handler. + +feature -- Status Report + + has_error: BOOLEAN + -- Has error? + do + Result := database_error_handler.has_error + end + +feature -- Helper + + exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) + -- Record exception as an error. + do + if attached a_e as l_e and then attached l_e.trace as l_trace then + database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) + end + end + +feature -- Connection Handling connect -- Connect to the database. diff --git a/persistence/implementation/common/database/database_handler_impl.e b/persistence/implementation/common/database/database_handler_impl.e index 55bde06..1de28a1 100644 --- a/persistence/implementation/common/database/database_handler_impl.e +++ b/persistence/implementation/common/database/database_handler_impl.e @@ -21,9 +21,11 @@ feature {NONE} -- Initialization do connection := a_connection create last_query.make_now + create database_error_handler.make ensure connection_not_void: connection /= Void last_query_not_void: last_query /= Void + database_error_handler_set: attached database_error_handler end feature -- Functionality @@ -35,6 +37,7 @@ feature -- Functionality l_retried: BOOLEAN do if not l_retried then + database_error_handler.reset if attached store as l_store then create l_db_selection.make db_selection := l_db_selection @@ -59,7 +62,7 @@ feature -- Functionality l_retried : BOOLEAN do if not l_retried then - + database_error_handler.reset if attached store as l_store then create l_db_change.make db_change := l_db_change @@ -86,6 +89,7 @@ feature -- SQL Queries l_retried: BOOLEAN do if not l_retried then + database_error_handler.reset if attached query as l_query then create l_db_selection.make db_selection := l_db_selection @@ -110,6 +114,7 @@ feature -- SQL Queries l_retried : BOOLEAN do if not l_retried then + database_error_handler.reset if attached query as l_query then create l_db_change.make db_change := l_db_change diff --git a/persistence/implementation/common/database/database_query.e b/persistence/implementation/common/database/database_query.e index 4acec0c..25088b3 100644 --- a/persistence/implementation/common/database/database_query.e +++ b/persistence/implementation/common/database/database_query.e @@ -8,10 +8,10 @@ class inherit - SHARED_ERROR_HANDLER - REFACTORING_HELPER + SHARED_LOGGER + create data_reader diff --git a/persistence/implementation/common/database/database_storage_manager.e b/persistence/implementation/common/database/database_storage_manager.e deleted file mode 100644 index e59ef5a..0000000 --- a/persistence/implementation/common/database/database_storage_manager.e +++ /dev/null @@ -1,371 +0,0 @@ -note - description: "[ - Manager to initialize data api for database access, - create database connection and so on - ]" - date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $" - revision: "$Revision: 195 $" - -class - DATABASE_STORAGE_MANAGER - -inherit - GLOBAL_SETTINGS - - REFACTORING_HELPER - - SHARED_ERROR_HANDLER - -create - make - -feature -- Initialization - - make (a_data_app: like data_app; a_database_name: like database_name; a_name: like name; a_password: like password; - a_host_name: like host_name; a_role_id: like role_id; a_role_password: like role_password - a_data_source: like data_source; a_group: like group) - -- Initialize with login info. - -- - -- `a_database_name' is used for MySQL - -- `a_name', the login user name - -- `a_password', the login user password, unencrypted. - local - l_storage: STRING_8 - do - create l_storage.make (64) - storage_url := l_storage - l_storage.append (a_data_app.db_spec.database_handle_name.as_lower) - l_storage.append ("://") - - data_app := a_data_app - database_name := a_database_name - name := a_name - password := a_password - host_name := a_host_name - role_id := a_role_id - role_password := a_role_password - data_source := a_data_source - group := a_group - - set_use_extended_types (True) - set_map_zero_null_value (False) - - l_storage.append (a_name.as_string_8) - l_storage.append (":********@") - if a_host_name /= Void then - a_data_app.set_hostname (a_host_name) - l_storage.append (a_host_name) - end - - if a_database_name /= Void then - a_data_app.set_application (a_database_name.as_string_8) - l_storage.append ("/" + a_database_name.as_string_8) - end - - if a_data_source /= Void then - a_data_app.set_data_source (a_data_source) - end - if a_role_id /= Void and then a_role_password /= Void then - a_data_app.set_role (a_role_id, a_role_password) - end - if a_group /= Void then - a_data_app.set_group (a_group) - end - - a_data_app.login (a_name.as_string_8, a_password.as_string_8) - a_data_app.set_base - - create session_control.make - - end - - report_database_schema_incompatibility (a_output: BOOLEAN) - -- Report the application code is not compatible with database schema version - -- if `a_output' is True, write error in io.error as well - require --- incompatible_database_schema_version: not is_database_schema_version_compatible - local - db_v: READABLE_STRING_8 - do --- if attached database_schema_version as v then --- db_v := v.version --- else --- db_v := "?.?.?.?" --- end --- database_error_handler.add_error_details (0, "MISC Error", "Schema version incompatible (application=" --- + database_storage_version.version + " database=" + db_v + ")." --- ) - if a_output then - io.error.put_string (database_error_handler.as_string_representation) - io.error.put_new_line - end - end - -feature -- System Update - - update_system - do --- if is_database_schema_version_compatible then --- misc_manager.initialize_reference_types --- history_manager.initialize_data --- user_role_permission_manager.initialize_built_in_user_role_permission --- user_role_permission_manager.initialize_extra_user_role_permission --- task_manager.initialize_data --- else --- -- If schema incompatible, report it and exit --- report_database_schema_incompatibility (True) --- (create {EXCEPTIONS}).die (-1) --- end - --- [2012-Mars-21] Idea about update system implementation --- if update_version < 01.00.0012 then --- if update_version < 01.00.0005 then --- update_version_01_00_0005 --- end --- update_version_01_00_0012 --- end - end - - reset_storage_manager - do --- initialize_managers (Current) - end - -feature -- Storage - - storage_url: READABLE_STRING_8 - -- Associated storage URL - - storage_connection_kept_alive: BOOLEAN - -- Keep storage connection alive? - -- i.e: never disconnect between 2 transactions. - - keep_storage_connection_alive (b: BOOLEAN) - do - storage_connection_kept_alive := b - end - - connect_storage - -- Connect the database - do - if not session_control.is_connected then - session_control.connect - end - end - - disconnect_from_storage - -- Disconnect from the storage - require - is_connected_to_storage: is_connected_to_storage - do - if not storage_connection_kept_alive then - session_control.disconnect - end - end - - force_disconnect_from_storage - -- Force disconnection from the storage - -- i.e ignore any `storage_connection_kept_alive' - do - if session_control.is_connected then - session_control.disconnect - end - end - - is_connected_to_storage: BOOLEAN - -- Is connected to the database - do - Result := session_control.is_connected - end - -feature -- Transaction Status - - in_transaction_session: BOOLEAN - -- Is session started? - - transaction_session_depth: INTEGER - -- Depth in the transaction session - -feature -- Transaction Operation - - start_transaction_session - -- Start session - -- if already started, increase the `transaction_session_depth' - require - in_transaction_session implies transaction_session_depth > 0 - not in_transaction_session implies transaction_session_depth = 0 - local - l_session_control: like session_control - l_retried: INTEGER - do - if l_retried = 0 then - if not in_transaction_session then - database_error_handler.reset - - check transaction_session_depth = 0 end - - debug ("database_session") - print ("..Start session%N") - end - connect_storage -- connect the DB - if is_connected_to_storage then - in_transaction_session := True - session_control.begin -- start transaction - else - l_session_control := session_control - if not l_session_control.is_ok then - database_error_handler.add_database_error (l_session_control.error_message_32, l_session_control.error_code) - else - database_error_handler.add_database_error (Session_not_started_error_message, 0) - end - l_session_control.reset - end - end - transaction_session_depth := transaction_session_depth + 1 - else - if l_retried = 1 then - transaction_session_depth := transaction_session_depth + 1 - if attached (create {EXCEPTION_MANAGER}).last_exception as e then - if attached {ASSERTION_VIOLATION} e then - --| Ignore for now with MYSQL ... - else - exception_as_error (e) - end - end - - in_transaction_session := False - session_control.reset - else - in_transaction_session := False - end - end - ensure - transaction_session_depth = (old transaction_session_depth) + 1 - rescue - l_retried := l_retried + 1 - retry - end - - end_transaction_session - -- End session - local - l_retried: BOOLEAN - do - if not l_retried then - transaction_session_depth := transaction_session_depth - 1 - if transaction_session_depth = 0 then - debug ("database_session") - print ("..End session%N") - end - if is_connected_to_storage then - if not database_error_handler.has_error then - session_control.commit -- Commit transaction - else - session_control.rollback -- Rollback transaction - end - disconnect_from_storage - end - in_transaction_session := False - end - else - exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) - in_transaction_session := False - transaction_session_depth := transaction_session_depth - 1 - session_control.reset - end - rescue - l_retried := True - retry - end - - execute_query (a_query: STRING_32) - -- Execute `a_q' - require - is_session_started: in_transaction_session - local - rescued: BOOLEAN - l_change: like new_database_change - do - if not rescued then - session_control.reset - l_change := new_database_change - l_change.set_query (a_query) - l_change.execute_query - else - database_error_handler.add_error_details (0, "Unexpected Error", "Unexpected Error when executing query") - end - rescue - rescued := True - retry - end - -feature -- Element Change - - set_last_inserted_id_function (a_f: like last_inserted_id_function) - -- Set `last_inserted_id_function' with `a_f' - do - last_inserted_id_function := a_f - ensure - last_inserted_id_function_set: last_inserted_id_function = a_f - end - -feature -- Access - - database_name: detachable READABLE_STRING_GENERAL - -- Database to access - - name: READABLE_STRING_GENERAL - -- Login user name - - password: READABLE_STRING_8 - -- Password - - host_name: detachable READABLE_STRING_8 - -- Host name, and port if needed - - role_id: detachable READABLE_STRING_8 - -- Role id - - role_password: detachable READABLE_STRING_8 - -- Role password - - data_source: detachable READABLE_STRING_8 - -- Data source - - group: detachable READABLE_STRING_8 - -- Group - - data_app: DATABASE_APPL [DATABASE] - -- Database application - - last_inserted_id_function: detachable FUNCTION [ANY, TUPLE, NATURAL_64] - -- Function to get last inserted id. - -feature -- Factory - - new_database_change: DB_CHANGE - -- Database change - do - create Result.make - end - - new_database_selection: DB_SELECTION - -- Database selection - do - create Result.make - end - - new_procedure (a_name: like {DB_PROC}.name): DB_PROC - -- Database procedure - do - create Result.make (a_name) - end - -feature {NONE} -- Implementation - - session_not_started_error_message: STRING_32 = "Session could not be started for unknown reason" - - session_control: DB_CONTROL - -- Session - -end diff --git a/persistence/implementation/common/database/database_no_change_error.e b/persistence/implementation/common/database/error/database_no_change_error.e similarity index 100% rename from persistence/implementation/common/database/database_no_change_error.e rename to persistence/implementation/common/database/error/database_no_change_error.e diff --git a/persistence/implementation/common/database/error/shared_error_handler.e b/persistence/implementation/common/database/error/shared_error_handler.e deleted file mode 100644 index f5a80ca..0000000 --- a/persistence/implementation/common/database/error/shared_error_handler.e +++ /dev/null @@ -1,39 +0,0 @@ -note - description: "Shared error handler for database" - date: "$Date: 2013-08-08 16:39:49 -0300 (ju. 08 de ago. de 2013) $" - revision: "$Revision: 195 $" - -class - SHARED_ERROR_HANDLER - -inherit - - SHARED_LOGGER - -feature -- Access - - database_error_handler: DATABASE_ERROR_HANDLER - -- Error handler. - once - create Result.make - end - -feature -- Status Report - - has_error: BOOLEAN - -- Has error? - do - Result := database_error_handler.has_error - end - -feature -- Helper - - exception_as_error (a_e: like {EXCEPTION_MANAGER}.last_exception) - -- Record exception as an error. - do - if attached a_e as l_e and then attached l_e.trace as l_trace then - database_error_handler.add_error_details (l_e.code, once "Exception", l_trace.as_string_32) - end - end - -end diff --git a/persistence/implementation/mysql/src/cms_storage_mysql.e b/persistence/implementation/mysql/src/cms_storage_mysql.e index 47b74ca..62422aa 100644 --- a/persistence/implementation/mysql/src/cms_storage_mysql.e +++ b/persistence/implementation/mysql/src/cms_storage_mysql.e @@ -25,8 +25,7 @@ feature {NONE} -- Initialization 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 + create error_handler.make end @@ -36,7 +35,6 @@ feature -- Access: user -- Has any user? do Result := user_provider.has_user - post_user_provider_execution end all_users: LIST [CMS_USER] @@ -48,19 +46,19 @@ feature -- Access: user 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 @@ -82,7 +80,7 @@ feature -- Access: user log.write_information (generator + ".login_valid User:" + l_auth_login + "does not exist" ) end end - post_user_provider_execution + end feature -- User Nodes @@ -135,7 +133,6 @@ feature -- Change: user user_provider.new_user (a_user.name, l_password, l_email) connection.commit else - set_last_error ("User or Password not attached", generator + ".save_user") end end @@ -148,7 +145,7 @@ feature -- Access: node 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] @@ -158,21 +155,21 @@ feature -- Access: node 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 node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER -- do Result := node_provider.node_author (a_id) - post_node_provider_execution + end node_collaborators (a_id: like {CMS_NODE}.id): LIST [CMS_USER] @@ -188,21 +185,21 @@ feature -- Node -- do node_provider.new_node (a_node) - post_node_provider_execution + end delete_node (a_id: INTEGER_64) do node_provider.delete_from_user_nodes(a_id) node_provider.delete_node (a_id) - post_node_provider_execution + end update_node (a_id: like {CMS_USER}.id; a_node: CMS_NODE) -- do node_provider.update_node (a_id, a_node) - post_node_provider_execution + end update_node_title (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_title: READABLE_STRING_32) @@ -210,7 +207,7 @@ feature -- Node do node_provider.update_node_title (a_node_id, a_title) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end update_node_summary (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_summary: READABLE_STRING_32) @@ -218,7 +215,7 @@ feature -- Node do node_provider.update_node_summary (a_node_id, a_summary) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end update_node_content (a_id: like {CMS_USER}.id; a_node_id: like {CMS_NODE}.id; a_content: READABLE_STRING_32) @@ -226,7 +223,7 @@ feature -- Node do node_provider.update_node_content (a_node_id, a_content) internal_node_update (a_id, a_node_id) - post_node_provider_execution + end feature {NONE} -- NODE Implemenation @@ -258,27 +255,6 @@ feature -- User 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. diff --git a/persistence/implementation/mysql/src/database/database_connection_mysql.e b/persistence/implementation/mysql/src/database/database_connection_mysql.e index b9d173f..05776f6 100644 --- a/persistence/implementation/mysql/src/database/database_connection_mysql.e +++ b/persistence/implementation/mysql/src/database/database_connection_mysql.e @@ -23,6 +23,7 @@ feature -- Initialization local l_retried: BOOLEAN do + create database_error_handler.make create db_application.login (username, password) if not l_retried then @@ -38,6 +39,7 @@ feature -- Initialization create db_control.make end rescue + create database_error_handler.make exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) l_retried := True retry @@ -49,6 +51,7 @@ feature -- Initialization local l_retried: BOOLEAN do + create database_error_handler.make create db_application.login (username, password) if not l_retried then @@ -64,6 +67,7 @@ feature -- Initialization create db_control.make end rescue + create database_error_handler.make exception_as_error ((create {EXCEPTION_MANAGER}).last_exception) l_retried := True retry @@ -76,6 +80,7 @@ feature -- Initialization -- `database_name' to `a_database_name' -- `connection' to `a_connection' do + create database_error_handler.make create db_application.login (a_username, a_password) db_application.set_hostname (a_hostname) db_application.set_data_source (a_database_name) @@ -97,6 +102,8 @@ feature -- Initialization l_user: STRING l_password: STRING do + create database_error_handler.make + l_string := a_string.split (';') l_server := l_string.at (2).split ('=').at (2) l_port := l_string.at (3).split ('=').at (2) @@ -111,12 +118,12 @@ feature -- Initialization db_application.set_base create db_control.make keep_connection := is_keep_connection - 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 database_error_handler.make create db_application db_application.set_application (a_schema) db_application.login_and_connect (a_username, a_password) diff --git a/persistence/implementation/mysql/src/provider/node_data_provider.e b/persistence/implementation/mysql/src/provider/node_data_provider.e index 59c9bae..5951cc5 100644 --- a/persistence/implementation/mysql/src/provider/node_data_provider.e +++ b/persistence/implementation/mysql/src/provider/node_data_provider.e @@ -10,10 +10,10 @@ inherit PARAMETER_NAME_HELPER - SHARED_ERROR - REFACTORING_HELPER + SHARED_LOGGER + create make @@ -23,6 +23,7 @@ feature -- Initialization -- Create a data provider. do create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection) + create error_handler.make post_execution end @@ -34,8 +35,13 @@ feature -- Status Report is_successful: BOOLEAN -- Is the last execution sucessful? do + Result := not error_handler.has_error end +feature -- Error Handler + + error_handler: ERROR_HANDLER + feature -- Access nodes: DATABASE_ITERATION_CURSOR [CMS_NODE] @@ -43,6 +49,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".nodes") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (Select_nodes, l_parameters)) @@ -57,6 +64,7 @@ feature -- Access l_parameters: STRING_TABLE [ANY] l_query: STRING do + error_handler.reset log.write_information (generator + ".recent_nodes") create l_parameters.make (2) l_parameters.put (a_rows, "rows") @@ -73,6 +81,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node") create l_parameters.make (1) l_parameters.put (a_id,"id") @@ -89,6 +98,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".count") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters)) @@ -105,6 +115,7 @@ feature -- Access local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".last_inserted_node_id") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (Sql_last_insert_node_id, l_parameters)) @@ -122,6 +133,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".new_node") create l_parameters.make (7) l_parameters.put (a_node.title, "title") @@ -140,10 +152,7 @@ feature -- Basic operations db_handler.execute_change a_node.set_id (last_inserted_node_id) - post_execution - - end update_node_title (a_id: INTEGER_64; a_title: READABLE_STRING_32) @@ -151,6 +160,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_title") create l_parameters.make (3) l_parameters.put (a_title, "title") @@ -166,6 +176,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_summary") create l_parameters.make (3) l_parameters.put (a_summary, "summary") @@ -181,6 +192,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node_content") create l_parameters.make (3) l_parameters.put (a_content, "content") @@ -196,6 +208,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".update_node") create l_parameters.make (7) l_parameters.put (a_node.title, "title") @@ -215,6 +228,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".delete_node") create l_parameters.make (1) l_parameters.put (a_id, "id") @@ -227,6 +241,7 @@ feature -- Basic operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".delete_from_user_nodes") create l_parameters.make (1) l_parameters.put (a_id, "id") @@ -242,6 +257,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_author") create l_parameters.make (2) l_parameters.put (a_user_id,"user_id") @@ -256,6 +272,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_collaborator") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -270,6 +287,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_collaborator") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -285,6 +303,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".author_nodes") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -299,6 +318,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".collaborator_nodes") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -314,6 +334,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_author") create l_parameters.make (1) l_parameters.put (a_id, "node_id") @@ -330,6 +351,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_collaborators") create l_parameters.make (1) l_parameters.put (a_id, "node_id") @@ -344,6 +366,7 @@ feature -- Basic Operations: User_Nodes local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".node_collaborators") create l_parameters.make (2) l_parameters.put (a_user_id, "user_id") @@ -353,7 +376,6 @@ feature -- Basic Operations: User_Nodes if db_handler.count = 1 then Result := db_handler.read_integer_32 (1) = 1 end - post_execution end @@ -480,6 +502,10 @@ feature {NONE} -- Implementation post_execution -- Post database execution. do + error_handler.add_synchronization (db_handler.database_error_handler) + if error_handler.has_error then + log.write_critical (generator + ".post_execution " + error_handler.as_string_representation) + end end end diff --git a/persistence/implementation/mysql/src/provider/user_data_provider.e b/persistence/implementation/mysql/src/provider/user_data_provider.e index 0d9b0bf..8660b8e 100644 --- a/persistence/implementation/mysql/src/provider/user_data_provider.e +++ b/persistence/implementation/mysql/src/provider/user_data_provider.e @@ -10,10 +10,10 @@ inherit PARAMETER_NAME_HELPER - SHARED_ERROR - REFACTORING_HELPER + SHARED_LOGGER + create make @@ -23,17 +23,24 @@ feature -- Initialization -- Create a data provider. do create {DATABASE_HANDLER_IMPL} db_handler.make (a_connection) + create error_handler.make post_execution end db_handler: DATABASE_HANDLER -- Db handler. +feature -- Error Handler + + error_handler: ERROR_HANDLER + + feature -- Status Report is_successful: BOOLEAN -- Is the last execution sucessful? do + Result := not error_handler.has_error end has_user: BOOLEAN @@ -51,6 +58,7 @@ feature -- Basic Operations l_password_salt, l_password_hash: STRING l_security: SECURITY_PROVIDER do + error_handler.reset create l_security l_password_salt := l_security.salt l_password_hash := l_security.password_hash (a_password, l_password_salt) @@ -71,6 +79,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user") create l_parameters.make (1) l_parameters.put (a_id,"id") @@ -87,6 +96,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_by_name") create l_parameters.make (1) l_parameters.put (a_name,"name") @@ -104,6 +114,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".user_by_email") create l_parameters.make (1) l_parameters.put (a_email,"email") @@ -120,6 +131,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_salt") create l_parameters.make (1) l_parameters.put (a_username,"name") @@ -138,6 +150,7 @@ feature -- Basic Operations local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".count") create l_parameters.make (0) db_handler.set_query (create {DATABASE_QUERY}.data_reader (select_count, l_parameters)) @@ -155,6 +168,7 @@ feature -- Basic operations: User Roles local l_parameters: STRING_TABLE [detachable ANY] do + error_handler.reset log.write_information (generator + ".add_role") create l_parameters.make (2) l_parameters.put (a_user_id,"users_id") @@ -169,6 +183,7 @@ feature -- Basic operations: User Roles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_roles") create l_parameters.make (1) l_parameters.put (a_id, "user_id") @@ -186,6 +201,7 @@ feature -- Basic operations: User Profiles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".save_profile_item") create l_parameters.make (3) l_parameters.put (a_key, "key") @@ -201,6 +217,7 @@ feature -- Basic operations: User Profiles local l_cursor: TABLE_ITERATION_CURSOR [READABLE_STRING_8, READABLE_STRING_8] do + error_handler.reset log.write_information (generator + ".save_profile") from l_cursor := a_user_profile.new_cursor @@ -219,6 +236,7 @@ feature -- Basic operations: User Profiles local l_parameters: STRING_TABLE [ANY] do + error_handler.reset log.write_information (generator + ".user_profile") create l_parameters.make (1) l_parameters.put (a_user_id, "users_id") @@ -310,6 +328,10 @@ feature {NONE} -- Implementation post_execution -- Post database execution. do + error_handler.add_synchronization (db_handler.database_error_handler) + if error_handler.has_error then + log.write_critical (generator + ".post_execution " + error_handler.as_string_representation) + end end end diff --git a/persistence/implementation/mysql/tests/handler/database_handler_test.e b/persistence/implementation/mysql/tests/handler/database_handler_test.e new file mode 100644 index 0000000..6ae64b4 --- /dev/null +++ b/persistence/implementation/mysql/tests/handler/database_handler_test.e @@ -0,0 +1,81 @@ +note + description: "[ + Eiffel tests that can be executed by testing tool. + ]" + author: "EiffelStudio test wizard" + date: "$Date$" + revision: "$Revision$" + testing: "type/manual" + +class + DATABASE_HANDLER_TEST + +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 + -- + do + (create {CLEAN_DB}).clean_db(connection) + end + + on_clean + -- + do + end + + +feature -- Test routines + + test_wrong_database_query + -- New test routine + local + l_parameters: STRING_TABLE[detachable ANY] + do + create l_parameters.make (0) + handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users", l_parameters)) + handler.execute_query + assert ("Has error:", handler.has_error) + end + + + + test_sequences_of_wrong_and_correct_queries + -- New test routine + local + l_parameters: STRING_TABLE[detachable ANY] + do + create l_parameters.make (0) + handler.set_query (create {DATABASE_QUERY}.data_reader ("Sellect from users;", l_parameters)) + handler.execute_query + assert ("Has error:", handler.has_error) + + handler.set_query (create {DATABASE_QUERY}.data_reader ("Select * from users;", l_parameters)) + handler.execute_query + assert ("Not Has error:",not handler.has_error) + end + + +feature -- Handler + + handler: DATABASE_HANDLER + once + create {DATABASE_HANDLER_IMPL} Result.make (connection ) + end + +end + + diff --git a/persistence/implementation/mysql/tests/nodes/node_test_set.e b/persistence/implementation/mysql/tests/nodes/node_test_set.e index 7993a72..9b3b442 100644 --- a/persistence/implementation/mysql/tests/nodes/node_test_set.e +++ b/persistence/implementation/mysql/tests/nodes/node_test_set.e @@ -41,7 +41,9 @@ feature {NONE} -- Events feature -- Test routines test_new_node - do + note + testing: "execution/isolated" + do assert ("Empty Nodes", node_provider.nodes.after) node_provider.new_node (default_node) assert ("Not empty Nodes after new_node", not node_provider.nodes.after) @@ -53,6 +55,8 @@ feature -- Test routines test_update_node + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -85,6 +89,8 @@ feature -- Test routines end test_update_title + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -104,6 +110,8 @@ feature -- Test routines end test_update_summary + note + testing: "execution/isolated" local l_node: CMS_NODE do @@ -123,11 +131,14 @@ feature -- Test routines end test_update_content + note + testing: "execution/isolated" local l_node: CMS_NODE do assert ("Empty Nodes", node_provider.nodes.after) l_node := custom_node ("

test node udpate

", "Update node", "Test case update") + connection.begin_transaction node_provider.new_node (l_node) assert ("Not empty Nodes after new_node", not node_provider.nodes.after) -- Exist node with id 1 @@ -139,6 +150,7 @@ feature -- Test routines node_provider.update_node_content (l_un.id,"New Content") assert ("Exist node with id 1", attached {CMS_NODE} node_provider.node (1) as ll_node and then not (ll_node.content ~ l_un.content) and then ll_node.content ~ "New Content" and then ll_node.summary ~ l_un.summary and then ll_node.title ~ l_un.title) end + connection.commit end diff --git a/persistence/implementation/mysql/tests/tests.ecf b/persistence/implementation/mysql/tests/tests.ecf index 363c33c..abe2c75 100644 --- a/persistence/implementation/mysql/tests/tests.ecf +++ b/persistence/implementation/mysql/tests/tests.ecf @@ -7,6 +7,7 @@ + diff --git a/persistence/implementation/mysql/tests/transactions/transaction_test_set.e b/persistence/implementation/mysql/tests/transactions/transaction_test_set.e index 3199f71..4abdd8c 100644 --- a/persistence/implementation/mysql/tests/transactions/transaction_test_set.e +++ b/persistence/implementation/mysql/tests/transactions/transaction_test_set.e @@ -66,77 +66,6 @@ feature -- Test routines assert ("Not has nodes:", node_provider.count = 0) end - - - test_user_node_nested_transaction_with_rollback_not_supported - note - testing: "execution/isolated" - do - connection.begin_transaction2 - user_provider.new_user ("test", "test","test@admin.com") - assert ("Has user:", user_provider.has_user) - node_provider.new_node (default_node) - assert ("Has one node:", node_provider.count = 1) - - connection.begin_transaction2 - user_provider.new_user ("test1", "test1","test1@admin.com") - assert ("Has user: test1", attached user_provider.user_by_name ("test1")) - connection.rollback2 - - connection.commit2 - assert ("Has user test:", attached user_provider.user_by_name ("test")) - assert ("Has nodes:", node_provider.count = 1) - assert ("Not has user: test1", user_provider.user_by_name ("test1") = Void) - end - - - test_user_node_nested_transaction_with_commit - note - testing: "execution/isolated" - do - connection.begin_transaction2 - user_provider.new_user ("test", "test","test@admin.com") - assert ("Has user:", user_provider.has_user) - node_provider.new_node (default_node) - assert ("Has one node:", node_provider.count = 1) - - connection.begin_transaction2 - user_provider.new_user ("test1", "test1","test1@admin.com") - assert ("Has user: test1", attached user_provider.user_by_name ("test1")) - connection.commit2 - - connection.commit2 - assert ("Has user test:", attached user_provider.user_by_name ("test")) - assert ("Has user test1:", attached user_provider.user_by_name ("test1")) - assert ("Has nodes:", node_provider.count = 1) - end - - - test_user_node_nested_transaction_with_rollback - note - testing: "execution/isolated" - do - connection.begin_transaction2 - user_provider.new_user ("test", "test","test@admin.com") - assert ("Has user:", user_provider.has_user) - node_provider.new_node (default_node) - assert ("Has one node:", node_provider.count = 1) - - connection.begin_transaction2 - user_provider.new_user ("test1", "test1","test1@admin.com") - assert ("Has user: test1", attached user_provider.user_by_name ("test1")) - connection.commit2 - - connection.rollback2 - assert ("Not Has user test:", user_provider.user_by_name ("test") = void) - assert ("Not Has user test1:", user_provider.user_by_name ("test1") = void) - assert ("Has 0 nodes:", node_provider.count = 0) - end - - - - - feature {NONE} -- Implementation node_provider: NODE_DATA_PROVIDER diff --git a/persistence/interface/cms_storage.e b/persistence/interface/cms_storage.e index eb5a44a..234613d 100644 --- a/persistence/interface/cms_storage.e +++ b/persistence/interface/cms_storage.e @@ -11,7 +11,7 @@ deferred class inherit - SHARED_ERROR + SHARED_LOGGER feature {NONE} -- Initialization @@ -19,6 +19,11 @@ feature {NONE} -- Initialization do end +feature -- Error Handling + + error_handler: ERROR_HANDLER + -- Error handler. + feature -- Access: user has_user: BOOLEAN