451 lines
10 KiB
Plaintext
451 lines
10 KiB
Plaintext
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,
|
|
sql_read_string_32
|
|
end
|
|
|
|
CMS_CORE_STORAGE_SQL_I
|
|
redefine
|
|
sql_read_date_time, sql_read_integer_32,
|
|
sql_read_string_32
|
|
end
|
|
|
|
CMS_USER_STORAGE_SQL_I
|
|
redefine
|
|
sql_read_date_time, sql_read_integer_32,
|
|
sql_read_string_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
|
|
debug ("roc_storage")
|
|
print ("# sql_begin_transaction (depth="+ transaction_depth.out +").%N")
|
|
end
|
|
end
|
|
|
|
sql_rollback_transaction
|
|
-- Rollback updates in the database.
|
|
do
|
|
if sqlite.is_in_transaction then
|
|
sqlite.rollback
|
|
end
|
|
transaction_depth := transaction_depth - 1
|
|
debug ("roc_storage")
|
|
print ("# sql_rollback_transaction (depth="+ transaction_depth.out +").%N")
|
|
end
|
|
end
|
|
|
|
sql_commit_transaction
|
|
-- Commit updates in the database.
|
|
do
|
|
if sqlite.is_in_transaction then
|
|
sqlite.commit
|
|
end
|
|
transaction_depth := transaction_depth - 1
|
|
debug ("roc_storage")
|
|
print ("# sql_commit_transaction (depth="+ transaction_depth.out +").%N")
|
|
end
|
|
end
|
|
|
|
sql_post_execution
|
|
-- Post database execution.
|
|
-- note: execute after each `sql_query' and `sql_change'.
|
|
do
|
|
debug ("roc_storage")
|
|
print ("# sql_post_execution.%N")
|
|
end
|
|
-- 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])
|
|
-- <Precursor>
|
|
local
|
|
st: SQLITE_QUERY_STATEMENT
|
|
do
|
|
debug ("roc_storage")
|
|
print ("> sql_query (" +a_sql_statement + ").%N")
|
|
end
|
|
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
|
|
debug ("roc_storage")
|
|
print ("< sql_query (" +a_sql_statement + ").%N")
|
|
end
|
|
end
|
|
|
|
sql_finalize
|
|
-- Finalize sql query (i.e destroy previous query statement.
|
|
do
|
|
debug ("roc_storage")
|
|
print ("> sql_finalize.%N")
|
|
end
|
|
if attached last_statement as st then
|
|
st.cleanup
|
|
end
|
|
if attached last_sqlite_result_cursor as cur then
|
|
if cur.statement /= last_statement then
|
|
check should_not_occurs: False end
|
|
cur.statement.cleanup
|
|
end
|
|
last_sqlite_result_cursor := Void
|
|
end
|
|
last_statement := Void
|
|
debug ("roc_storage")
|
|
print ("< sql_finalize.%N")
|
|
end
|
|
end
|
|
|
|
sql_insert (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
|
|
-- <Precursor>
|
|
local
|
|
st: SQLITE_INSERT_STATEMENT
|
|
do
|
|
debug ("roc_storage")
|
|
print ("> sql_insert (" +a_sql_statement + ").%N")
|
|
end
|
|
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
|
|
debug ("roc_storage")
|
|
print ("< sql_insert (" +a_sql_statement + ").%N")
|
|
end
|
|
end
|
|
|
|
sql_modify (a_sql_statement: STRING; a_params: detachable STRING_TABLE [detachable ANY])
|
|
-- <Precursor>
|
|
local
|
|
st: SQLITE_MODIFY_STATEMENT
|
|
do
|
|
debug ("roc_storage")
|
|
print ("> sql_modify (" +a_sql_statement + ").%N")
|
|
end
|
|
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
|
|
debug ("roc_storage")
|
|
print ("< sql_modify (" +a_sql_statement + ").%N")
|
|
end
|
|
end
|
|
|
|
sqlite_arguments (a_params: STRING_TABLE [detachable ANY]): ARRAYED_LIST [SQLITE_BIND_ARG [ANY]]
|
|
local
|
|
k: READABLE_STRING_GENERAL
|
|
k8: STRING
|
|
utf: UTF_CONVERTER
|
|
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 := utf.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))
|
|
elseif attached {READABLE_STRING_32} ic.item as s32 then
|
|
Result.force (new_binding_argument (utf.utf_32_string_to_utf_8_string_8 (s32), ":" + 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_start
|
|
-- <Precursor>.
|
|
do
|
|
-- sqlite cursor `last_sqlite_result_cursor', already at first position if any.
|
|
end
|
|
|
|
sql_after: BOOLEAN
|
|
-- <Precursor>.
|
|
do
|
|
if attached last_sqlite_result_cursor as l_cursor then
|
|
Result := l_cursor.after
|
|
end
|
|
end
|
|
|
|
sql_forth
|
|
-- <Precursor>.
|
|
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_string_32 (a_index: INTEGER): detachable STRING_32
|
|
-- <Precursor>
|
|
local
|
|
utf: UTF_CONVERTER
|
|
do
|
|
Result := Precursor (a_index)
|
|
if Result = Void then
|
|
if attached sql_read_string (a_index) as s8 then
|
|
Result := utf.utf_8_string_8_to_string_32 (s8)
|
|
end
|
|
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
|
|
-- <Precursor>.
|
|
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
|