diff --git a/examples/demo/demo-safe.ecf b/examples/demo/demo-safe.ecf index 8f28c4b..522d166 100644 --- a/examples/demo/demo-safe.ecf +++ b/examples/demo/demo-safe.ecf @@ -26,6 +26,7 @@ + + + + /EIFGENs$ + /CVS$ + /.svn$ + /old$ + + + + diff --git a/library/persistence/sqlite3/src/cms_storage_sqlite3.e b/library/persistence/sqlite3/src/cms_storage_sqlite3.e new file mode 100644 index 0000000..27e81f2 --- /dev/null +++ b/library/persistence/sqlite3/src/cms_storage_sqlite3.e @@ -0,0 +1,408 @@ +note + description: "Summary description for {CMS_STORAGE_MYSQL}." + date: "$Date: 2015-02-09 22:29:56 +0100 (lun., 09 févr. 2015) $" + revision: "$Revision: 96596 $" + +class + CMS_STORAGE_SQLITE3 + +inherit + CMS_STORAGE_SQL + redefine + sql_read_date_time, sql_read_integer_32 + end + + CMS_CORE_STORAGE_SQL_I + redefine + sql_read_date_time, sql_read_integer_32 + end + + CMS_USER_STORAGE_SQL_I + redefine + sql_read_date_time, sql_read_integer_32 + end + + SQLITE_BIND_ARG_MARSHALLER + + REFACTORING_HELPER + +create + make + +feature {NONE} -- Initialization + + make (db: SQLITE_DATABASE) + do + sqlite := db + create error_handler.make + end + + sqlite: SQLITE_DATABASE + -- Associated SQLite database. + +feature -- Status report + + is_initialized: BOOLEAN + -- Is storage initialized? + do + Result := has_user + end + +feature -- Status report + + is_available: BOOLEAN + -- Is storage available? + do + Result := sqlite.is_interface_usable + end + +feature -- Basic operation + + close + -- Close/disconnect current storage. + do + sqlite.close + end + +feature -- Execution + + transaction_depth: INTEGER + + sql_begin_transaction + -- Start a database transtaction. + do + if transaction_depth = 0 then + sqlite.begin_transaction (False) + end + transaction_depth := transaction_depth + 1 + end + + sql_rollback_transaction + -- Rollback updates in the database. + do + if sqlite.is_in_transaction then + sqlite.rollback + end + transaction_depth := transaction_depth - 1 + end + + sql_commit_transaction + -- Commit updates in the database. + do + if sqlite.is_in_transaction then + sqlite.commit + end + transaction_depth := transaction_depth - 1 + end + + sql_post_execution + -- Post database execution. + -- note: execute after each `sql_query' and `sql_change'. + do + -- FIXME + if sqlite.has_error then + write_critical_log (generator + ".post_execution Error occurred!") + end + end + +feature -- Operation + + last_statement: detachable SQLITE_STATEMENT + + last_sqlite_result_cursor: detachable SQLITE_STATEMENT_ITERATION_CURSOR + + sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + -- + local + st: SQLITE_QUERY_STATEMENT + do + last_sqlite_result_cursor := Void + create st.make (a_sql_statement, sqlite) + last_statement := st + if st.is_compiled then + if a_params /= Void then + check st.has_arguments end + last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params)) + else + last_sqlite_result_cursor := st.execute_new + end + else + error_handler.add_custom_error (1, "invalid query", "query compilation failed!") + end + end + + sql_finalize + -- Finalize sql query (i.e destroy previous query statement. + do + if attached last_statement as st then + st.dispose + end + last_sqlite_result_cursor := Void + last_statement := Void + end + + sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + -- + local + st: SQLITE_INSERT_STATEMENT + do + last_sqlite_result_cursor := Void + create st.make (a_sql_statement, sqlite) + last_statement := st + if st.is_compiled then + if a_params /= Void then + check st.has_arguments end + last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params)) + else + last_sqlite_result_cursor := st.execute_new + end + else + error_handler.add_custom_error (1, "invalid query", "query compilation failed!") + end + end + + sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + -- + local + st: SQLITE_MODIFY_STATEMENT + do + last_sqlite_result_cursor := Void + create st.make (a_sql_statement, sqlite) + last_statement := st + if st.is_compiled then + if a_params /= Void then + check st.has_arguments end + last_sqlite_result_cursor := st.execute_new_with_arguments (sqlite_arguments (a_params)) + else + last_sqlite_result_cursor := st.execute_new + end + else + error_handler.add_custom_error (1, "invalid query", "query compilation failed!") + end + end + + sqlite_arguments (a_params: STRING_TABLE [detachable ANY]): ARRAYED_LIST [SQLITE_BIND_ARG [ANY]] + local + k: READABLE_STRING_GENERAL + k8: STRING + do + create Result.make (a_params.count) + across + a_params as ic + loop + k := ic.key + if k.is_valid_as_string_8 then + k8 := k.as_string_8 + else + k8 := (create {UTF_CONVERTER}).utf_32_string_to_utf_8_string_8 (k) + end + if attached {DATE_TIME} ic.item as dt then + + Result.force (new_binding_argument (date_time_to_string (dt), ":" + k8)) + else + Result.force (new_binding_argument (ic.item, ":" + k8)) + end + end + end + + date_time_to_string (dt: DATE_TIME): STRING + do + create Result.make (16) + Result.append_integer (dt.year) + Result.append_character ('-') + if dt.month <= 9 then + Result.append_character ('0') + end + Result.append_integer (dt.month) + Result.append_character ('-') + if dt.day <= 9 then + Result.append_character ('0') + end + Result.append_integer (dt.day) + Result.append_character (' ') + if dt.hour <= 9 then + Result.append_character ('0') + end + Result.append_integer (dt.hour) + Result.append_character (':') + if dt.minute <= 9 then + Result.append_character ('0') + end + Result.append_integer (dt.minute) + Result.append_character (':') + if dt.second <= 9 then + Result.append_character ('0') + end + Result.append_integer (dt.second) + end + + string_to_date_time (a_string: READABLE_STRING_GENERAL): DATE_TIME + local + y,m,d: INTEGER + h,min,sec: INTEGER + s: detachable READABLE_STRING_GENERAL + i,j: INTEGER + do + i := 1 + -- YYYY + j := a_string.index_of ('-', i) + s := a_string.substring (i, j - 1) + y := s.to_integer + i := j + 1 + -- /MM + j := a_string.index_of ('-', i) + s := a_string.substring (i, j - 1) + m := s.to_integer + i := j + 1 + -- /DD + j := a_string.index_of (' ', i) + s := a_string.substring (i, j - 1) + d := s.to_integer + i := j + 1 + -- %THour + j := a_string.index_of (':', i) + s := a_string.substring (i, j - 1) + h := s.to_integer + i := j + 1 + -- :Min + j := a_string.index_of (':', i) + s := a_string.substring (i, j - 1) + min := s.to_integer + i := j + 1 + -- :Sec + j := a_string.count + 1 + s := a_string.substring (i, j - 1) + sec := s.to_integer + + create Result.make (y,m,d,h,min,sec) + end + +feature -- Access + +-- sql_rows_count: INTEGER +-- -- Number of rows for last sql execution. +-- do +-- if attached last_sqlite_result_cursor as l_cursor then +-- -- FIXME: find better solution! +-- from +-- Result := 1 +-- until +-- not l_cursor.after +-- loop +-- Result := Result + 1 +-- end +-- end +-- end + + sql_start + -- Set the cursor on first element. + do + -- Already at first position if any ? + if attached last_sqlite_result_cursor as l_cursor then +-- l_cursor.start + end + end + + sql_after: BOOLEAN + -- Are there no more items to iterate over? + do + if attached last_sqlite_result_cursor as l_cursor then + Result := l_cursor.after + end + end + + sql_forth + -- Fetch next row from last sql execution, if any. + do + if attached last_sqlite_result_cursor as l_cursor then + l_cursor.forth + end + end + + sql_valid_item_index (a_index: INTEGER): BOOLEAN + local + l_row: SQLITE_RESULT_ROW + do + if attached last_sqlite_result_cursor as l_cursor then + l_row := l_cursor.item + Result := a_index > 0 and a_index.to_natural_32 <= l_row.count + end + end + + sql_item (a_index: INTEGER): detachable ANY + local + l_row: SQLITE_RESULT_ROW + do + if attached last_sqlite_result_cursor as l_cursor then + l_row := l_cursor.item + Result := l_row.value (a_index.to_natural_32) + end + end + + sql_read_integer_32 (a_index: INTEGER): INTEGER_32 + -- Retrieved value at `a_index' position in `item'. + local + l_item: like sql_item + i64: INTEGER_64 + do + l_item := sql_item (a_index) + if attached {INTEGER_32} l_item as i then + Result := i + elseif attached {INTEGER_32_REF} l_item as l_value then + Result := l_value.item + else + if attached {INTEGER_64} l_item as i then + i64 := i + elseif attached {INTEGER_64_REF} l_item as l_value then + i64 := l_value.item + else + check is_integer_32: False end + end + if i64 <= {INTEGER_32}.max_value then + Result := i64.to_integer_32 + else + check is_integer_32: False end + end + end + end + + sql_read_date_time (a_index: INTEGER): detachable DATE_TIME + -- Retrieved value at `a_index' position in `item'. + local + l_item: like sql_item + do + l_item := sql_item (a_index) + if attached {DATE_TIME} l_item as dt then + Result := dt + elseif attached {READABLE_STRING_GENERAL} l_item as s then + Result := string_to_date_time (s) + else + check is_date_time_nor_null: l_item = Void end + end + end + +feature -- Conversion + + sql_statement (a_statement: STRING): STRING + -- . + local + i: INTEGER + do + Result := a_statement + from + i := 1 + until + i = 0 + loop + i := a_statement.substring_index ("AUTO_INCREMENT", i) + if i > 0 then + if Result = a_statement then + create Result.make_from_string (a_statement) + end + Result.remove (i + 4) + i := i + 14 + end + end + end + +end diff --git a/library/persistence/sqlite3/src/cms_storage_sqlite3_builder.e b/library/persistence/sqlite3/src/cms_storage_sqlite3_builder.e new file mode 100644 index 0000000..ce5c267 --- /dev/null +++ b/library/persistence/sqlite3/src/cms_storage_sqlite3_builder.e @@ -0,0 +1,90 @@ +note + description: "[ + Objects that ... + ]" + author: "$Author: jfiat $" + date: "$Date: 2015-02-13 13:08:13 +0100 (ven., 13 févr. 2015) $" + revision: "$Revision: 96616 $" + +class + CMS_STORAGE_SQLITE3_BUILDER + +inherit + CMS_STORAGE_SQL_BUILDER + +create + make + +feature {NONE} -- Initialization + + make + -- Initialize `Current'. + do + end + +feature -- Factory + + storage (a_setup: CMS_SETUP; a_error_handler: ERROR_HANDLER): detachable CMS_STORAGE_SQLITE3 + local + s: detachable READABLE_STRING_32 + p: PATH + db: detachable SQLITE_DATABASE + l_source: SQLITE_FILE_SOURCE + i,j: INTEGER + do + if + attached (create {APPLICATION_JSON_CONFIGURATION_HELPER}).new_database_configuration (a_setup.environment.application_config_path) as l_database_config + then + if l_database_config.driver.is_case_insensitive_equal ("sqlite3") then + s := l_database_config.database_string + i := s.substring_index ("Database=", 1) + if i > 0 then + i := s.index_of ('=', i) + 1 + j := s.index_of (';', i) + if j = 0 then + j := s.count + 1 + end + create p.make_from_string (s.substring (i, j - 1)) + else + create p.make_from_string (s) + end + + if attached reuseable_connection.item as d then + if p.same_as (d.path) then + db := d.database + end + end + if db = Void or else db.is_closed then + create l_source.make (p.name) + create db.make (l_source) + if l_source.exists then + db.open_read_write + else + db.open_create_read_write + end + end + if not db.is_closed then + db.set_busy_timeout (1_000) -- FIXME + create Result.make (db) +-- set_map_zero_null_value (False) --| This way we map 0 to 0, instead of Null as default. + if Result.is_available then + if not Result.is_initialized then + initialize (a_setup, Result) + end + end + else + a_error_handler.add_custom_error (0, "Could not connect to the ODBC storage", Void) + end + else + -- Wrong mapping between storage name and storage builder! + end + end + end + + reuseable_connection: CELL [detachable TUPLE [path: PATH; database: SQLITE_DATABASE]] + once + create Result.put (Void) + end + + +end diff --git a/modules/blog/cms_node_storage_sql_blog_extension.e b/modules/blog/cms_node_storage_sql_blog_extension.e index 24d6844..fefff15 100644 --- a/modules/blog/cms_node_storage_sql_blog_extension.e +++ b/modules/blog/cms_node_storage_sql_blog_extension.e @@ -83,11 +83,11 @@ feature -- Persistence if l_update then if l_has_modif then - sql_change (sql_update_node_data, l_parameters) + sql_modify (sql_update_node_data, l_parameters) end else if l_has_modif then - sql_change (sql_insert_node_data, l_parameters) + sql_insert (sql_insert_node_data, l_parameters) else -- no page data, means everything is empty. -- FOR NOW: always record row @@ -116,7 +116,7 @@ feature -- Persistence if a_node.has_id then create l_parameters.make (1) l_parameters.put (a_node.id, "nid") - sql_change (sql_delete_node_data, l_parameters) + sql_modify (sql_delete_node_data, l_parameters) end end @@ -136,18 +136,21 @@ feature {NONE} -- Implementation l_parameters.put (a_node.revision, "revision") sql_query (sql_select_node_data, l_parameters) if not has_error then - n := sql_rows_count - if n = 1 then + if not sql_after then -- nid, revision, tags l_rev := sql_read_integer_64 (2) l_tags := sql_read_string_32 (3) if l_tags /= Void then Result := [l_rev, l_tags] end - else - check unique_data: n = 0 end + sql_forth + if not sql_after then + check unique_data: n = 0 end + Result := Void + end end end + sql_finalize ensure accepted_revision: Result /= Void implies Result.revision <= a_node.revision end diff --git a/modules/blog/persistence/cms_blog_storage_sql.e b/modules/blog/persistence/cms_blog_storage_sql.e index 0ac754a..0644b48 100644 --- a/modules/blog/persistence/cms_blog_storage_sql.e +++ b/modules/blog/persistence/cms_blog_storage_sql.e @@ -23,9 +23,10 @@ feature -- Access error_handler.reset write_information_log (generator + ".blogs_count") sql_query (sql_select_blog_count, Void) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := sql_read_integer_64 (1) end + sql_finalize end blogs_count_from_user (a_user: CMS_USER) : INTEGER_64 @@ -38,9 +39,10 @@ feature -- Access create l_parameters.make (2) l_parameters.put (a_user.id, "user") sql_query (sql_select_blog_count_from_user, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := sql_read_integer_64 (1) end + sql_finalize end blogs: LIST [CMS_NODE] diff --git a/modules/node/persistence/cms_node_storage_sql.e b/modules/node/persistence/cms_node_storage_sql.e index 6305ca1..33707cb 100644 --- a/modules/node/persistence/cms_node_storage_sql.e +++ b/modules/node/persistence/cms_node_storage_sql.e @@ -28,9 +28,10 @@ feature -- Access error_handler.reset write_information_log (generator + ".nodes_count") sql_query (sql_select_nodes_count, Void) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := sql_read_natural_64 (1) end + sql_finalize end @@ -175,9 +176,10 @@ feature -- Access create l_parameters.make (1) l_parameters.put (a_id, "nid") sql_query (sql_select_node_by_id, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_node end + sql_finalize end node_by_id_and_revision (a_node_id, a_revision: INTEGER_64): detachable CMS_NODE @@ -191,9 +193,10 @@ feature -- Access l_parameters.put (a_node_id, "nid") l_parameters.put (a_revision, "revision") sql_query (sql_select_node_by_id_and_revision, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_node end + sql_finalize end node_author (a_node: CMS_NODE): detachable CMS_USER @@ -207,9 +210,10 @@ feature -- Access l_parameters.put (a_node.id, "nid") l_parameters.put (a_node.revision, "revision") sql_query (Select_user_author, l_parameters) - if sql_rows_count >= 1 then + if not has_error and not sql_after then Result := fetch_author end + sql_finalize end last_inserted_node_id: INTEGER_64 @@ -218,9 +222,10 @@ feature -- Access error_handler.reset write_information_log (generator + ".last_inserted_node_id") sql_query (Sql_last_insert_node_id, Void) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := sql_read_integer_64 (1) end + sql_finalize end last_inserted_node_revision (a_node: detachable CMS_NODE): INTEGER_64 @@ -234,11 +239,16 @@ feature -- Access create l_parameters.make (1) l_parameters.force (a_node.id, "nid") sql_query (Sql_last_insert_node_revision_for_nid, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then if sql_item (1) /= Void then Result := sql_read_integer_64 (1) end + sql_forth + if not sql_after then + check no_more_than_one: False end + end end + sql_finalize end -- if Result = 0 and not has_error then --| include the case a_node = Void -- sql_query (Sql_last_insert_node_revision, Void) @@ -328,7 +338,7 @@ feature -- Change: Node l_parameters.put (create {DATE_TIME}.make_now_utc, "changed") l_parameters.put ({CMS_NODE_API}.trashed, "status") l_parameters.put (a_id, "nid") - sql_change (sql_trash_node, l_parameters) + sql_modify (sql_trash_node, l_parameters) end delete_node_base (a_node: CMS_NODE) @@ -343,11 +353,11 @@ feature -- Change: Node error_handler.reset create l_parameters.make (1) l_parameters.put (a_node.id, "nid") - sql_change (sql_delete_node, l_parameters) + sql_modify (sql_delete_node, l_parameters) -- we remove node_revisions and pages. -- Check: maybe we need a transaction. - sql_change (sql_delete_node_revisions, l_parameters) + sql_modify (sql_delete_node_revisions, l_parameters) if not error_handler.has_error then extended_delete (a_node) @@ -368,7 +378,7 @@ feature -- Change: Node l_parameters.put (l_time, "changed") l_parameters.put ({CMS_NODE_API}.not_published, "status") l_parameters.put (a_id, "nid") - sql_change (sql_restore_node, l_parameters) + sql_modify (sql_restore_node, l_parameters) end @@ -412,7 +422,7 @@ feature {NONE} -- Implementation create l_copy_parameters.make (2) l_copy_parameters.force (a_node.id, "nid") -- l_copy_parameters.force (l_rev - 1, "revision") - sql_change (sql_copy_node_to_revision, l_copy_parameters) + sql_insert (sql_copy_node_to_revision, l_copy_parameters) if not has_error then a_node.set_revision (l_rev) @@ -420,7 +430,7 @@ feature {NONE} -- Implementation -- Update l_parameters.put (a_node.id, "nid") l_parameters.put (a_node.revision, "revision") - sql_change (sql_update_node, l_parameters) + sql_modify (sql_update_node, l_parameters) if not error_handler.has_error then a_node.set_modification_date (now) @@ -431,7 +441,7 @@ feature {NONE} -- Implementation l_parameters.put (a_node.creation_date, "created") l_parameters.put (l_rev, "revision") - sql_change (sql_insert_node, l_parameters) + sql_insert (sql_insert_node, l_parameters) if not error_handler.has_error then a_node.set_modification_date (now) a_node.set_id (last_inserted_node_id) diff --git a/modules/node/persistence/cms_node_storage_sql_page_extension.e b/modules/node/persistence/cms_node_storage_sql_page_extension.e index cdffa57..380ade8 100644 --- a/modules/node/persistence/cms_node_storage_sql_page_extension.e +++ b/modules/node/persistence/cms_node_storage_sql_page_extension.e @@ -73,15 +73,15 @@ feature -- Persistence if l_update then if l_has_modif then - sql_change (sql_update_node_data, l_parameters) + sql_modify (sql_update_node_data, l_parameters) end else if l_has_modif then - sql_change (sql_insert_node_data, l_parameters) + sql_insert (sql_insert_node_data, l_parameters) else -- no page data, means everything is empty. -- FOR NOW: always record row - sql_change (sql_insert_node_data, l_parameters) + sql_insert (sql_insert_node_data, l_parameters) end end end @@ -121,7 +121,7 @@ feature -- Persistence if a_node.has_id then create l_parameters.make (1) l_parameters.put (a_node.id, "nid") - sql_change (sql_delete_node_data, l_parameters) + sql_modify (sql_delete_node_data, l_parameters) end end @@ -139,10 +139,14 @@ feature {NONE} -- Implementation l_parameters.put (a_node.revision, "revision") sql_query (sql_select_node_data, l_parameters) if not has_error then - n := sql_rows_count - if n = 1 then + if not sql_after then -- nid, revision, parent Result := [sql_read_integer_64 (2), sql_read_integer_64 (3)] + sql_forth + if not sql_after then + check unique_data: n = 0 end + Result := Void + end else check unique_data: n = 0 end end diff --git a/modules/oauth20/persistence/cms_oauth_20_storage_sql.e b/modules/oauth20/persistence/cms_oauth_20_storage_sql.e index 24f1273..610268c 100644 --- a/modules/oauth20/persistence/cms_oauth_20_storage_sql.e +++ b/modules/oauth20/persistence/cms_oauth_20_storage_sql.e @@ -53,11 +53,15 @@ feature -- Access User Outh create l_string.make_from_string (select_user_oauth2_template_by_id) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) sql_query (l_string, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end user_oauth2_by_email (a_email: like {CMS_USER}.email; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER @@ -73,11 +77,15 @@ feature -- Access User Outh create l_string.make_from_string (select_user_oauth2_template_by_email) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) sql_query (l_string, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end user_oauth2_by_token (a_token: READABLE_STRING_GENERAL; a_consumer: READABLE_STRING_GENERAL): detachable CMS_USER @@ -93,11 +101,15 @@ feature -- Access User Outh create l_string.make_from_string (select_user_by_oauth2_template_token) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) sql_query (l_string, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end @@ -134,11 +146,15 @@ feature --Access: Consumers create l_parameters.make (1) l_parameters.put (a_name, "name") sql_query (sql_oauth_consumer_name, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_consumer - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end oauth_consumer_by_callback (a_callback: READABLE_STRING_8): detachable CMS_OAUTH_20_CONSUMER @@ -151,11 +167,15 @@ feature --Access: Consumers create l_parameters.make (1) l_parameters.put (a_callback, "name") sql_query (sql_oauth_consumer_callback, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_consumer - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end feature -- Change: User OAuth @@ -181,7 +201,7 @@ feature -- Change: User OAuth create l_string.make_from_string (sql_insert_oauth2_template) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) - sql_change (l_string, l_parameters) + sql_insert (l_string, l_parameters) sql_commit_transaction end @@ -202,7 +222,7 @@ feature -- Change: User OAuth create l_string.make_from_string (sql_update_oauth2_template) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) - sql_change (l_string, l_parameters) + sql_modify (l_string, l_parameters) sql_commit_transaction end @@ -221,7 +241,7 @@ feature -- Change: User OAuth create l_string.make_from_string (sql_remove_oauth2_template) l_string.replace_substring_all ("$table_name", oauth2_sql_table_name (a_consumer)) - sql_change (l_string, l_parameters) + sql_modify (l_string, l_parameters) sql_commit_transaction end @@ -342,7 +362,7 @@ feature {NONE} -- User OAuth2 Sql_remove_oauth2_template: STRING = "DELETE FROM $table_name WHERE uid =:uid;" - Sql_oauth_consumers: STRING = "SELECT name FROM oauth2_consumers"; + Sql_oauth_consumers: STRING = "SELECT name FROM oauth2_consumers;" Sql_oauth2_table_prefix: STRING = "oauth2_" diff --git a/modules/openid/persitence/cms_openid_storage_sql.e b/modules/openid/persitence/cms_openid_storage_sql.e index ab85c2d..05714f7 100644 --- a/modules/openid/persitence/cms_openid_storage_sql.e +++ b/modules/openid/persitence/cms_openid_storage_sql.e @@ -33,11 +33,15 @@ feature -- Access User Outh l_parameters.put (a_uid, "uid") l_parameters.put (a_identity, "identity") sql_query (Select_user_openid_by_id, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end end + sql_finalize end user_openid_by_identity (a_identity: READABLE_STRING_GENERAL): detachable CMS_USER @@ -50,10 +54,15 @@ feature -- Access User Outh create l_parameters.make (1) l_parameters.put (a_identity, "identity") sql_query (Select_user_by_openid_identity, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user + sql_forth + if not sql_after then + check no_more_than_one: False end + Result := Void + end else - check no_more_than_one: sql_rows_count = 0 end + check no_more_than_one: False end end end @@ -91,11 +100,14 @@ feature --Access: Consumers create l_parameters.make (1) l_parameters.put (a_name, "name") sql_query (sql_openid_consumer_name, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_consumer - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + if not sql_after then + check no_more_than_one: False end + end end + sql_finalize end feature -- Change: User OAuth @@ -114,7 +126,7 @@ feature -- Change: User OAuth l_parameters.put (a_user.id, "uid") l_parameters.put (a_identity, "identity") l_parameters.put (create {DATE_TIME}.make_now_utc, "utc_date") - sql_change (Sql_insert_openid, l_parameters) + sql_insert (Sql_insert_openid, l_parameters) sql_commit_transaction end diff --git a/src/persistence/core/cms_core_storage_sql_i.e b/src/persistence/core/cms_core_storage_sql_i.e index c21305f..8a27dee 100644 --- a/src/persistence/core/cms_core_storage_sql_i.e +++ b/src/persistence/core/cms_core_storage_sql_i.e @@ -37,7 +37,7 @@ feature -- URL aliases error_handler.add_custom_error (0, "alias exists", "Path alias %"" + a_alias + "%" already exists!") end else - sql_change (sql_insert_path_alias, l_parameters) + sql_insert (sql_insert_path_alias, l_parameters) end end @@ -63,7 +63,7 @@ feature -- URL aliases l_parameters.put (l_previous_alias, "old") l_parameters.put (a_alias, "alias") - sql_change (sql_update_path_alias, l_parameters) + sql_modify (sql_update_path_alias, l_parameters) end end @@ -79,7 +79,7 @@ feature -- URL aliases -- Found create l_parameters.make (1) l_parameters.put (a_alias, "alias") - sql_change (sql_delete_path_alias, l_parameters) + sql_modify (sql_delete_path_alias, l_parameters) else error_handler.add_custom_error (0, "alias mismatch", "Path alias %"" + a_alias + "%" is not related to source %"" + a_source + "%"!") end @@ -97,11 +97,12 @@ feature -- URL aliases create l_parameters.make (1) l_parameters.put (a_source, "source") sql_query (sql_select_path_source, l_parameters) - if not has_error then - if sql_rows_count = 1 then - Result := sql_read_string (1) - end + if not has_error and not sql_after then + Result := sql_read_string (1) + sql_forth + check one_row: sql_after end end + sql_finalize end source_of_path_alias (a_alias: READABLE_STRING_8): detachable READABLE_STRING_8 @@ -114,10 +115,13 @@ feature -- URL aliases l_parameters.put (a_alias, "alias") sql_query (sql_select_path_alias, l_parameters) if not has_error then - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := sql_read_string (1) + sql_forth + check one_row: sql_after end end end + sql_finalize end sql_select_path_alias: STRING = "SELECT source FROM path_aliases WHERE alias=:alias ;" @@ -166,7 +170,7 @@ feature -- Logs l_parameters.put (Void, "link") end l_parameters.put (now, "date") - sql_change (sql_insert_log, l_parameters) + sql_insert (sql_insert_log, l_parameters) end sql_insert_log: STRING = "INSERT INTO logs (category, level, uid, message, info, link, date) VALUES (:category, :level, :uid, :message, :info, :link, :date);" @@ -193,10 +197,10 @@ feature -- Misc if a_value.same_string (l_value) then -- already up to date else - sql_change (sql_update_custom_value, l_parameters) + sql_modify (sql_update_custom_value, l_parameters) end else - sql_change (sql_insert_custom_value, l_parameters) + sql_insert (sql_insert_custom_value, l_parameters) end end @@ -214,7 +218,7 @@ feature -- Misc l_parameters.put (a_type, "default") end l_parameters.put (a_name, "name") - sql_change (sql_delete_custom_value, l_parameters) + sql_modify (sql_delete_custom_value, l_parameters) end custom_value (a_name: READABLE_STRING_GENERAL; a_type: detachable READABLE_STRING_8): detachable READABLE_STRING_32 @@ -232,11 +236,12 @@ feature -- Misc end l_parameters.put (a_name, "name") sql_query (sql_select_custom_value, l_parameters) - if not has_error then - if sql_rows_count = 1 then - Result := sql_read_string_32 (1) - end + if not has_error and not sql_after then + Result := sql_read_string_32 (1) + sql_forth + check one_row: sql_after end end + sql_finalize end sql_select_custom_value: STRING = "SELECT value FROM custom_values WHERE type=:type AND name=:name;" @@ -252,4 +257,7 @@ feature -- Misc -- SQL delete custom value; +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" end diff --git a/src/persistence/sql/cms_proxy_storage_sql.e b/src/persistence/sql/cms_proxy_storage_sql.e index 10a37b2..694f542 100644 --- a/src/persistence/sql/cms_proxy_storage_sql.e +++ b/src/persistence/sql/cms_proxy_storage_sql.e @@ -68,19 +68,24 @@ feature -- Operation sql_storage.sql_query (a_sql_statement, a_params) end - sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + sql_finalize + -- Finalize sql query (i.e destroy previous query statement. do - sql_storage.sql_change (a_sql_statement, a_params) + sql_storage.sql_finalize + end + + sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + do + sql_storage.sql_insert (a_sql_statement, a_params) + end + + sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + do + sql_storage.sql_modify (a_sql_statement, a_params) end feature -- Access - sql_rows_count: INTEGER - -- Number of rows for last sql execution. - do - Result := sql_storage.sql_rows_count - end - sql_start -- Set the cursor on first element. do @@ -109,6 +114,16 @@ feature -- Access Result:= sql_storage.sql_item (a_index) end + sql_read_integer_32 (a_index: INTEGER_32): INTEGER_32 + do + Result := sql_storage.sql_read_integer_32 (a_index) + end + + sql_read_date_time (a_index: INTEGER_32): detachable DATE_TIME + do + Result := sql_storage.sql_read_date_time (a_index) + end + feature -- Conversion sql_statement (a_statement: STRING): STRING @@ -117,4 +132,7 @@ feature -- Conversion Result := sql_storage.sql_statement (a_statement) end +note + copyright: "2011-2015, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" + license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" end diff --git a/src/persistence/sql/cms_storage_sql_i.e b/src/persistence/sql/cms_storage_sql_i.e index 2a73152..c183c4d 100644 --- a/src/persistence/sql/cms_storage_sql_i.e +++ b/src/persistence/sql/cms_storage_sql_i.e @@ -119,12 +119,22 @@ feature -- Operation end sql_query (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) - -- + -- Execute sql query `a_sql_statement' with optional parameters `a_params'. deferred end - sql_change (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) - -- + sql_finalize + -- Finalize sql query (i.e destroy previous query statement. + deferred + end + + sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + -- Execute sql insert `a_sql_statement' with optional parameters `a_params'. + deferred + end + + sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY]) + -- Execute sql modify `a_sql_statement' with optional parameters `a_params'. deferred end @@ -179,7 +189,11 @@ feature -- Helper loop if attached next_sql_statement (a_sql_script, i, cl) as s then if not s.is_whitespace then - sql_change (sql_statement (s), a_params) + if s.starts_with ("INSERT") then + sql_insert (sql_statement (s), a_params) + else + sql_modify (sql_statement (s), a_params) + end err := err or has_error reset_error end @@ -217,11 +231,6 @@ feature -- Helper feature -- Access - sql_rows_count: INTEGER - -- Number of rows for last sql execution. - deferred - end - sql_start -- Set the cursor on first element. deferred @@ -279,17 +288,7 @@ feature -- Access sql_read_integer_32 (a_index: INTEGER): INTEGER_32 -- Retrieved value at `a_index' position in `item'. - local - l_item: like sql_item - do - l_item := sql_item (a_index) - if attached {INTEGER_32} l_item as i then - Result := i - elseif attached {INTEGER_32_REF} l_item as l_value then - Result := l_value.item - else - check is_integer_32: False end - end + deferred end sql_read_string (a_index: INTEGER): detachable STRING @@ -329,15 +328,7 @@ feature -- Access sql_read_date_time (a_index: INTEGER): detachable DATE_TIME -- Retrieved value at `a_index' position in `item'. - local - l_item: like sql_item - do - l_item := sql_item (a_index) - if attached {DATE_TIME} l_item as dt then - Result := dt - else - check is_date_time_nor_null: l_item = Void end - end + deferred end sql_read_boolean (a_index: INTEGER): detachable BOOLEAN diff --git a/src/persistence/user/cms_user_storage_sql_i.e b/src/persistence/user/cms_user_storage_sql_i.e index 1434d14..34304da 100644 --- a/src/persistence/user/cms_user_storage_sql_i.e +++ b/src/persistence/user/cms_user_storage_sql_i.e @@ -30,10 +30,12 @@ feature -- Access: user write_information_log (generator + ".user_count") sql_query (select_users_count, Void) - if sql_rows_count = 1 then - Result := sql_read_integer_32 (1) + if not has_error and then not sql_after then + Result := sql_read_integer_64 (1).to_integer_32 + sql_forth + check one_row: sql_after end end - error_handler.reset + sql_finalize end users: LIST [CMS_USER] @@ -47,13 +49,14 @@ feature -- Access: user sql_query (select_users, Void) sql_start until - sql_after + sql_after or has_error loop if attached fetch_user as l_user then Result.force (l_user) end sql_forth end + sql_finalize end user_by_id (a_id: like {CMS_USER}.id): detachable CMS_USER @@ -66,11 +69,12 @@ feature -- Access: user create l_parameters.make (1) l_parameters.put (a_id, "uid") sql_query (select_user_by_id, l_parameters) - if sql_rows_count = 1 then + if not has_error and not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + check one_row: sql_after end end + sql_finalize end user_by_name (a_name: like {CMS_USER}.name): detachable CMS_USER @@ -83,11 +87,12 @@ feature -- Access: user create l_parameters.make (1) l_parameters.put (a_name, "name") sql_query (select_user_by_name, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + check one_row: sql_after end end + sql_finalize end user_by_email (a_email: like {CMS_USER}.email): detachable CMS_USER @@ -100,11 +105,12 @@ feature -- Access: user create l_parameters.make (1) l_parameters.put (a_email, "email") sql_query (select_user_by_email, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + check one_row: sql_after end end + sql_finalize end user_by_activation_token (a_token: READABLE_STRING_32): detachable CMS_USER @@ -117,11 +123,12 @@ feature -- Access: user create l_parameters.make (1) l_parameters.put (a_token, "token") sql_query (select_user_by_activation_token, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + check one_row: sql_after end end + sql_finalize end user_by_password_token (a_token: READABLE_STRING_32): detachable CMS_USER @@ -134,11 +141,12 @@ feature -- Access: user create l_parameters.make (1) l_parameters.put (a_token, "token") sql_query (select_user_by_password_token, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user - else - check no_more_than_one: sql_rows_count = 0 end + sql_forth + check one_row: sql_after end end + sql_finalize end is_valid_credential (l_auth_login, l_auth_password: READABLE_STRING_32): BOOLEAN @@ -160,7 +168,6 @@ feature -- Access: user write_information_log (generator + ".is_valid_credential User:" + l_auth_login + "does not exist" ) end end - end recent_users (a_lower: INTEGER; a_count: INTEGER): LIST [CMS_USER] @@ -187,6 +194,7 @@ feature -- Access: user end sql_forth end + sql_finalize end feature -- Change: user @@ -216,7 +224,7 @@ feature -- Change: user l_parameters.put (create {DATE_TIME}.make_now_utc, "created") l_parameters.put (a_user.status, "status") - sql_change (sql_insert_user, l_parameters) + sql_insert (sql_insert_user, l_parameters) if not error_handler.has_error then a_user.set_id (last_inserted_user_id) update_user_roles (a_user) @@ -226,6 +234,7 @@ feature -- Change: user else sql_rollback_transaction end + sql_finalize else -- set error error_handler.add_custom_error (-1, "bad request" , "Missing password or email") @@ -265,7 +274,7 @@ feature -- Change: user l_parameters.put (l_email, "email") l_parameters.put (a_user.status, "status") - sql_change (sql_update_user, l_parameters) + sql_modify (sql_update_user, l_parameters) if not error_handler.has_error then update_user_roles (a_user) end @@ -274,6 +283,7 @@ feature -- Change: user else sql_rollback_transaction end + sql_finalize else -- set error error_handler.add_custom_error (-1, "bad request" , "Missing password or email") @@ -290,8 +300,9 @@ feature -- Change: user write_information_log (generator + ".delete_user") create l_parameters.make (1) l_parameters.put (a_user.id, "uid") - sql_change (sql_delete_user, l_parameters) + sql_modify (sql_delete_user, l_parameters) sql_commit_transaction + sql_finalize end update_user_roles (a_user: CMS_USER) @@ -347,6 +358,7 @@ feature -- Change: user else sql_rollback_transaction end + sql_finalize end assign_role_to_user (a_role: CMS_USER_ROLE; a_user: CMS_USER) @@ -356,7 +368,8 @@ feature -- Change: user create l_parameters.make (2) l_parameters.put (a_user.id, "uid") l_parameters.put (a_role.id, "rid") - sql_change (sql_insert_role_to_user, l_parameters) + sql_insert (sql_insert_role_to_user, l_parameters) + sql_finalize end unassign_role_from_user (a_role: CMS_USER_ROLE; a_user: CMS_USER) @@ -366,7 +379,8 @@ feature -- Change: user create l_parameters.make (2) l_parameters.put (a_user.id, "uid") l_parameters.put (a_role.id, "rid") - sql_change (sql_delete_role_from_user, l_parameters) + sql_modify (sql_delete_role_from_user, l_parameters) + sql_finalize end feature -- Access: roles and permissions @@ -380,13 +394,16 @@ feature -- Access: roles and permissions create l_parameters.make (1) l_parameters.put (a_id, "rid") sql_query (select_user_role_by_id, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user_role + sql_forth + check one_row: sql_after end + sql_finalize if Result /= Void and not has_error then fill_user_role (Result) end else - check no_more_than_one: sql_rows_count = 0 end + sql_finalize end end @@ -400,13 +417,16 @@ feature -- Access: roles and permissions create l_parameters.make (1) l_parameters.put (a_name, "name") sql_query (select_user_role_by_name, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := fetch_user_role + sql_forth + check one_row: sql_after end + sql_finalize if Result /= Void and not has_error then fill_user_role (Result) end else - check no_more_than_one: sql_rows_count = 0 end + sql_finalize end end @@ -431,6 +451,7 @@ feature -- Access: roles and permissions end sql_forth end + sql_finalize if not has_error then across Result as ic loop fill_user_role (ic.item) @@ -458,6 +479,7 @@ feature -- Access: roles and permissions end sql_forth end + sql_finalize if not has_error then across Result as ic loop fill_user_role (ic.item) @@ -501,6 +523,7 @@ feature -- Access: roles and permissions -- end sql_forth end + sql_finalize end role_permissions: LIST [READABLE_STRING_8] @@ -522,6 +545,7 @@ feature -- Access: roles and permissions end sql_forth end + sql_finalize end feature -- Change: roles and permissions @@ -550,7 +574,7 @@ feature -- Change: roles and permissions create l_parameters.make (2) l_parameters.put (a_user_role.id, "rid") l_parameters.put (a_user_role.name, "name") - sql_change (sql_update_user_role, l_parameters) + sql_modify (sql_update_user_role, l_parameters) end if not a_user_role.permissions.is_empty then -- FIXME: check if this is non set permissions,or none ... @@ -596,14 +620,17 @@ feature -- Change: roles and permissions else create l_parameters.make (1) l_parameters.put (a_user_role.name, "name") - sql_change (sql_insert_user_role, l_parameters) + sql_insert (sql_insert_user_role, l_parameters) if not error_handler.has_error then a_user_role.set_id (last_inserted_user_role_id) + sql_finalize across a_user_role.permissions as ic loop set_permission_for_role_id (ic.item, a_user_role.id) end + else + sql_finalize end end end @@ -619,7 +646,8 @@ feature -- Change: roles and permissions l_parameters.put (a_role_id, "rid") l_parameters.put (a_permission, "permission") l_parameters.put (Void, "module") -- FIXME: unsupported for now! - sql_change (sql_insert_user_role_permission, l_parameters) + sql_insert (sql_insert_user_role_permission, l_parameters) + sql_finalize end unset_permission_for_role_id (a_permission: READABLE_STRING_8; a_role_id: INTEGER) @@ -633,7 +661,8 @@ feature -- Change: roles and permissions create l_parameters.make (2) l_parameters.put (a_role_id, "rid") l_parameters.put (a_permission, "permission") - sql_change (sql_delete_user_role_permission, l_parameters) + sql_modify (sql_delete_user_role_permission, l_parameters) + sql_finalize end last_inserted_user_role_id: INTEGER_32 @@ -642,9 +671,12 @@ feature -- Change: roles and permissions error_handler.reset write_information_log (generator + ".last_inserted_user_role_id") sql_query (Sql_last_insert_user_role_id, Void) - if sql_rows_count = 1 then - Result := sql_read_integer_32 (1) + if not sql_after then + Result := sql_read_integer_64 (1).to_integer_32 + sql_forth + check one_row: sql_after end end + sql_finalize end @@ -658,9 +690,10 @@ feature -- Change: roles and permissions write_information_log (generator + ".delete_role") create l_parameters.make (1) l_parameters.put (a_role.id, "rid") - sql_change (sql_delete_role_permissions_by_role_id, l_parameters) - sql_change (sql_delete_role_by_id, l_parameters) + sql_modify (sql_delete_role_permissions_by_role_id, l_parameters) + sql_modify (sql_delete_role_by_id, l_parameters) sql_commit_transaction + sql_finalize end @@ -676,9 +709,12 @@ feature -- Access: User activation create l_parameters.make (1) l_parameters.put (a_token, "token") sql_query (sql_select_activation_expiration, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := sql_read_integer_32 (1) + sql_forth + check one_row: sql_after end end + sql_finalize end user_id_by_activation (a_token: READABLE_STRING_32): INTEGER_64 @@ -691,9 +727,12 @@ feature -- Access: User activation create l_parameters.make (1) l_parameters.put (a_token, "token") sql_query (sql_select_userid_activation, l_parameters) - if sql_rows_count = 1 then + if not sql_after then Result := sql_read_integer_32 (1) + sql_forth + check one_row: sql_after end end + sql_finalize end feature -- Change: User activation @@ -712,8 +751,9 @@ feature -- Change: User activation l_parameters.put (a_token, "token") l_parameters.put (a_id, "uid") l_parameters.put (l_utc_date, "utc_date") - sql_change (sql_insert_activation, l_parameters) + sql_insert (sql_insert_activation, l_parameters) sql_commit_transaction + sql_finalize end remove_activation (a_token: READABLE_STRING_32) @@ -726,8 +766,9 @@ feature -- Change: User activation write_information_log (generator + ".remove_activation") create l_parameters.make (1) l_parameters.put (a_token, "token") - sql_change (sql_remove_activation, l_parameters) + sql_modify (sql_remove_activation, l_parameters) sql_commit_transaction + sql_finalize end feature -- Change: User password recovery @@ -746,8 +787,9 @@ feature -- Change: User password recovery l_parameters.put (a_token, "token") l_parameters.put (a_id, "uid") l_parameters.put (l_utc_date, "utc_date") - sql_change (sql_insert_password, l_parameters) + sql_insert (sql_insert_password, l_parameters) sql_commit_transaction + sql_finalize end remove_password (a_token: READABLE_STRING_32) @@ -760,8 +802,9 @@ feature -- Change: User password recovery write_information_log (generator + ".remove_password") create l_parameters.make (1) l_parameters.put (a_token, "token") - sql_change (sql_remove_password, l_parameters) + sql_modify (sql_remove_password, l_parameters) sql_commit_transaction + sql_finalize end feature {NONE} -- Implementation: User @@ -776,11 +819,14 @@ feature {NONE} -- Implementation: User create l_parameters.make (1) l_parameters.put (a_username, "name") sql_query (select_salt_by_username, l_parameters) - if sql_rows_count = 1 then + if not sql_after then if attached sql_read_string (1) as l_salt then Result := l_salt end + sql_forth + check one_row: sql_after end end + sql_finalize end fetch_user: detachable CMS_USER @@ -826,9 +872,12 @@ feature {NONE} -- Implementation: User error_handler.reset write_information_log (generator + ".last_inserted_user_id") sql_query (Sql_last_insert_user_id, Void) - if sql_rows_count = 1 then + if not sql_after then Result := sql_read_integer_64 (1) + sql_forth + check one_row: sql_after end end + sql_finalize end feature {NONE} -- Implementation: User role