Added revisions support to node management.
Updated node extension implementation. Updated known permissions for node module. Improved code for node storage extension , in preparation to code factorization. Ensured that author is updated when saved.
This commit is contained in:
@@ -6,8 +6,17 @@ note
|
||||
deferred class
|
||||
CMS_NODE_STORAGE_EXTENSION [G -> CMS_NODE]
|
||||
|
||||
feature -- Change
|
||||
|
||||
set_node_api (a_node_api: CMS_NODE_API)
|
||||
do
|
||||
node_api := a_node_api
|
||||
end
|
||||
|
||||
feature -- Access
|
||||
|
||||
node_api: CMS_NODE_API
|
||||
|
||||
content_type: READABLE_STRING_8
|
||||
deferred
|
||||
end
|
||||
|
||||
@@ -73,6 +73,11 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
node_revisions (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- Revisions of node `a_node'.
|
||||
deferred
|
||||
end
|
||||
|
||||
trashed_nodes (a_user: detachable CMS_USER): LIST [CMS_NODE]
|
||||
-- List of nodes by user `a_user' if set, or any.
|
||||
require
|
||||
@@ -92,10 +97,18 @@ feature -- Access
|
||||
deferred
|
||||
end
|
||||
|
||||
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
|
||||
node_by_id_and_revision (a_node_id, a_revision: INTEGER_64): detachable CMS_NODE
|
||||
-- Retrieve node by node id `a_node_id' and revision `a_revision', if any.
|
||||
require
|
||||
has_node_id: a_node_id > 0
|
||||
has_revision: a_revision > 0
|
||||
deferred
|
||||
end
|
||||
|
||||
node_author (a_node: CMS_NODE): detachable CMS_USER
|
||||
-- Node's author. if any.
|
||||
require
|
||||
valid_node: a_id > 0
|
||||
valid_node: a_node.has_id
|
||||
deferred
|
||||
end
|
||||
|
||||
|
||||
@@ -35,12 +35,18 @@ feature -- Access: node
|
||||
do
|
||||
end
|
||||
|
||||
nodes: LIST[CMS_NODE]
|
||||
nodes: LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
node_revisions (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- Revisions of node `a_node'.
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
end
|
||||
|
||||
trashed_nodes (a_user: detachable CMS_USER): LIST [CMS_NODE]
|
||||
-- <Precursor>.
|
||||
do
|
||||
@@ -58,7 +64,12 @@ feature -- Access: node
|
||||
do
|
||||
end
|
||||
|
||||
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
|
||||
node_by_id_and_revision (a_node_id, a_revision: INTEGER_64): detachable CMS_NODE
|
||||
-- <Precuror>
|
||||
do
|
||||
end
|
||||
|
||||
node_author (a_node: CMS_NODE): detachable CMS_USER
|
||||
-- Node's author. if any.
|
||||
do
|
||||
end
|
||||
|
||||
@@ -60,6 +60,33 @@ feature -- Access
|
||||
-- end
|
||||
end
|
||||
|
||||
node_revisions (a_node: CMS_NODE): LIST [CMS_NODE]
|
||||
-- Revisions of node `a_node'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
do
|
||||
create {ARRAYED_LIST [CMS_NODE]} Result.make (0)
|
||||
Result.force (a_node)
|
||||
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".node_revisions")
|
||||
|
||||
from
|
||||
create l_parameters.make (1)
|
||||
l_parameters.force (a_node.id, "nid")
|
||||
l_parameters.force (a_node.revision, "revision")
|
||||
sql_query (sql_select_node_revisions, l_parameters)
|
||||
sql_start
|
||||
until
|
||||
sql_after
|
||||
loop
|
||||
if attached fetch_node as l_node then
|
||||
Result.force (l_node)
|
||||
end
|
||||
sql_forth
|
||||
end
|
||||
end
|
||||
|
||||
trashed_nodes (a_user: detachable CMS_USER): LIST [CMS_NODE]
|
||||
-- List of nodes.
|
||||
local
|
||||
@@ -130,15 +157,32 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
|
||||
node_author (a_id: like {CMS_NODE}.id): detachable CMS_USER
|
||||
node_by_id_and_revision (a_node_id, a_revision: INTEGER_64): detachable CMS_NODE
|
||||
-- Retrieve node by id `a_id', if any.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".node")
|
||||
create l_parameters.make (1)
|
||||
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
|
||||
Result := fetch_node
|
||||
end
|
||||
end
|
||||
|
||||
node_author (a_node: CMS_NODE): detachable CMS_USER
|
||||
-- Node's author for the given node id.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".node_author")
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (a_id, "nid")
|
||||
create l_parameters.make (2)
|
||||
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
|
||||
Result := fetch_author
|
||||
@@ -156,6 +200,33 @@ feature -- Access
|
||||
end
|
||||
end
|
||||
|
||||
last_inserted_node_revision (a_node: detachable CMS_NODE): INTEGER_64
|
||||
-- Last insert revision for node of id `nid'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".last_inserted_node_revision")
|
||||
if a_node /= Void and then a_node.has_id then
|
||||
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 sql_item (1) /= Void then
|
||||
Result := sql_read_integer_64 (1)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- if Result = 0 and not has_error then --| include the case a_node = Void
|
||||
-- sql_query (Sql_last_insert_node_revision, Void)
|
||||
-- if sql_rows_count = 1 then
|
||||
-- if sql_item (1) /= Void then
|
||||
-- Result := sql_read_integer_64 (1)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
end
|
||||
|
||||
feature -- Change: Node
|
||||
|
||||
new_node (a_node: CMS_NODE)
|
||||
@@ -174,20 +245,17 @@ feature -- Change: Node
|
||||
-- Remove node by id `a_id'.
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_time: DATE_TIME
|
||||
do
|
||||
create l_time.make_now_utc
|
||||
write_information_log (generator + ".delete_node {" + a_id.out + "}")
|
||||
|
||||
error_handler.reset
|
||||
create l_parameters.make (1)
|
||||
l_parameters.put (l_time, "changed")
|
||||
create l_parameters.make (3)
|
||||
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_delete_node, l_parameters)
|
||||
end
|
||||
|
||||
|
||||
trash_node_by_id (a_id: INTEGER_64)
|
||||
-- <Precursor>
|
||||
local
|
||||
@@ -225,7 +293,9 @@ feature {NONE} -- Implementation
|
||||
|
||||
store_node (a_node: CMS_NODE)
|
||||
local
|
||||
l_copy_parameters: STRING_TABLE [detachable ANY]
|
||||
l_parameters: STRING_TABLE [detachable ANY]
|
||||
l_rev: like last_inserted_node_revision
|
||||
now: DATE_TIME
|
||||
do
|
||||
create now.make_now_utc
|
||||
@@ -248,27 +318,46 @@ feature {NONE} -- Implementation
|
||||
l_parameters.put (0, "author")
|
||||
end
|
||||
sql_begin_transaction
|
||||
|
||||
if a_node.has_id then
|
||||
-- Update
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
sql_change (sql_update_node, l_parameters)
|
||||
if not error_handler.has_error then
|
||||
-- FIXED: FOR NOW no revision
|
||||
-- a_node.set_revision (a_node.revision + 1) -- FIXME: Should be incremented by one, in same transaction...but check!
|
||||
a_node.set_modification_date (now)
|
||||
l_rev := a_node.revision.max (last_inserted_node_revision (a_node)) + 1 --| starts at (nid, 1)
|
||||
else
|
||||
l_rev := last_inserted_node_revision (a_node) + 1 --| starts at (nid, 1)
|
||||
end
|
||||
if a_node.has_id then
|
||||
-- Copy existing node data to node_revisions table.
|
||||
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)
|
||||
|
||||
if not has_error then
|
||||
a_node.set_revision (l_rev)
|
||||
|
||||
-- Update
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
l_parameters.put (a_node.revision, "revision")
|
||||
sql_change (sql_update_node, l_parameters)
|
||||
|
||||
if not error_handler.has_error then
|
||||
a_node.set_modification_date (now)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Store new node
|
||||
l_parameters.put (a_node.creation_date, "created")
|
||||
l_parameters.put (l_rev, "revision")
|
||||
|
||||
sql_change (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)
|
||||
a_node.set_revision (1) -- New object.
|
||||
a_node.set_revision (l_rev) -- New object.
|
||||
-- check a_node.revision = last_inserted_node_revision (a_node) end
|
||||
end
|
||||
end
|
||||
if not error_handler.has_error then
|
||||
extended_store (a_node)
|
||||
extended_store (a_node) -- Note, `a_node.revision' is updated.
|
||||
end
|
||||
if error_handler.has_error then
|
||||
sql_rollback_transaction
|
||||
@@ -298,6 +387,9 @@ feature {NONE} -- Queries
|
||||
-- SQL Query to retrieve all nodes.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
|
||||
sql_select_node_revisions: STRING = "SELECT nodes.nid, node_revisions.revision, nodes.type, node_revisions.title, node_revisions.summary, node_revisions.content, node_revisions.format, node_revisions.author, nodes.publish, nodes.created, node_revisions.changed, node_revisions.status FROM nodes INNER JOIN node_revisions ON nodes.nid = node_revisions.nid WHERE nodes.nid = :nid AND node_revisions.revision < :revision ORDER BY node_revisions.revision DESC;"
|
||||
-- SQL query to get node revisions (missing the latest one).
|
||||
|
||||
sql_select_trash_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE status = -1 ;"
|
||||
-- SQL Query to retrieve all trahsed nodes.
|
||||
--| note: {CMS_NODE_API}.trashed = -1
|
||||
@@ -308,15 +400,15 @@ feature {NONE} -- Queries
|
||||
|
||||
sql_select_node_by_id: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes WHERE nid =:nid ORDER BY revision DESC, publish DESC LIMIT 1;"
|
||||
|
||||
sql_select_node_by_id_and_revision: STRING = "SELECT nodes.nid, node_revisions.revision, nodes.type, node_revisions.title, node_revisions.summary, node_revisions.content, node_revisions.format, node_revisions.author, nodes.publish, nodes.created, node_revisions.changed, node_revisions.status FROM nodes INNER JOIN node_revisions ON nodes.nid = node_revisions.nid WHERE nodes.nid = :nid AND node_revisions.revision = :revision ORDER BY node_revisions.revision DESC;"
|
||||
|
||||
sql_select_recent_nodes: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed, status FROM nodes ORDER BY nid DESC, publish DESC LIMIT :rows OFFSET :offset ;"
|
||||
|
||||
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, status, author) VALUES (1, :type, :title, :summary, :content, :format, :publish, :created, :changed, :status, :author);"
|
||||
sql_insert_node: STRING = "INSERT INTO nodes (revision, type, title, summary, content, format, publish, created, changed, status, author) VALUES (:revision, :type, :title, :summary, :content, :format, :publish, :created, :changed, :status, :author);"
|
||||
-- SQL Insert to add a new node.
|
||||
|
||||
sql_update_node : STRING = "UPDATE nodes SET revision = revision, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, status=:status, author=:author WHERE nid=:nid;"
|
||||
-- FIXME: for now no revision inc.!
|
||||
-- sql_update_node : STRING = "UPDATE nodes SET revision = revision + 1, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, revision = revision + 1, author=:author WHERE nid=:nid;"
|
||||
-- SQL node.
|
||||
sql_update_node : STRING = "UPDATE nodes SET revision=:revision, type=:type, title=:title, summary=:summary, content=:content, format=:format, publish=:publish, changed=:changed, status=:status, author=:author WHERE nid=:nid;"
|
||||
-- SQL update node.
|
||||
|
||||
sql_delete_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid"
|
||||
-- Soft deletion with free metadata.
|
||||
@@ -327,24 +419,18 @@ feature {NONE} -- Queries
|
||||
sql_restore_node: STRING = "UPDATE nodes SET changed=:changed, status =:status WHERE nid=:nid"
|
||||
-- Restore node to {CMS_NODE_API}.not_publised.
|
||||
|
||||
-- sql_update_node_author: STRING = "UPDATE nodes SET author=:author WHERE nid=:nid;"
|
||||
|
||||
-- sql_update_node_title: STRING ="UPDATE nodes SET title=:title, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
|
||||
-- -- SQL update node title.
|
||||
|
||||
-- sql_update_node_summary: STRING ="UPDATE nodes SET summary=:summary, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
|
||||
-- -- SQL update node summary.
|
||||
|
||||
-- sql_update_node_content: STRING ="UPDATE nodes SET content=:content, changed=:changed, revision = revision + 1 WHERE nid=:nid;"
|
||||
-- -- SQL node content.
|
||||
|
||||
sql_last_insert_node_id: STRING = "SELECT MAX(nid) FROM nodes;"
|
||||
|
||||
sql_copy_node_to_revision: STRING = "INSERT INTO node_revisions (nid, revision, title, summary, content, format, author, changed, status) SELECT nid, revision, title, summary, content, format, author, changed, status FROM nodes WHERE nid=:nid;"
|
||||
|
||||
Sql_last_insert_node_revision: STRING = "SELECT MAX(revision) FROM node_revisions;"
|
||||
Sql_last_insert_node_revision_for_nid: STRING = "SELECT MAX(revision) FROM node_revisions WHERE nid=:nid;"
|
||||
|
||||
feature {NONE} -- Sql Queries: USER_ROLES collaborators, author
|
||||
|
||||
Select_user_author: STRING = "SELECT uid, name, password, salt, email, users.status, users.created, signed FROM nodes INNER JOIN users ON nodes.author=users.uid AND nodes.nid = :nid;"
|
||||
Select_user_author: STRING = "SELECT uid, name, password, salt, email, users.status, users.created, signed FROM nodes INNER JOIN users ON nodes.author=users.uid AND nodes.nid = :nid AND nodes.revision = :revision;"
|
||||
|
||||
Select_node_author: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed FROM users INNER JOIN nodes ON nodes.author=users.uid AND nodes.nid =:nid;"
|
||||
-- Select_node_author: STRING = "SELECT nid, revision, type, title, summary, content, format, author, publish, created, changed FROM users INNER JOIN nodes ON nodes.author=users.uid AND nodes.nid =:nid;"
|
||||
|
||||
feature {NONE} -- Implementation
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ inherit
|
||||
|
||||
CMS_PROXY_STORAGE_SQL
|
||||
rename
|
||||
make as make_proxy,
|
||||
sql_storage as node_storage
|
||||
redefine
|
||||
node_storage
|
||||
@@ -21,6 +22,12 @@ create
|
||||
|
||||
feature {NONE} -- Initialization
|
||||
|
||||
make (a_node_api: CMS_NODE_API; a_sql_storage: CMS_NODE_STORAGE_SQL)
|
||||
do
|
||||
set_node_api (a_node_api)
|
||||
make_proxy (a_sql_storage)
|
||||
end
|
||||
|
||||
node_storage: CMS_NODE_STORAGE_SQL
|
||||
-- <Precursor>
|
||||
|
||||
@@ -38,62 +45,86 @@ feature -- Persistence
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
l_new_parent_id, l_previous_parent_id: INTEGER_64
|
||||
l_update: BOOLEAN
|
||||
l_has_modif: BOOLEAN
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".store_page_data")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
l_parameters.put (a_node.revision, "revision")
|
||||
if attached api as l_api then
|
||||
l_api.logger.put_information (generator + ".store", Void)
|
||||
end
|
||||
|
||||
sql_query (sql_select_page_data, l_parameters)
|
||||
error_handler.reset
|
||||
-- Check existing record, if any.
|
||||
if attached node_data (a_node) as d then
|
||||
l_update := True
|
||||
l_previous_parent_id := d.parent_id
|
||||
end
|
||||
if not has_error then
|
||||
if sql_rows_count = 1 then
|
||||
l_previous_parent_id := sql_read_integer_64 (3)
|
||||
l_update := True
|
||||
end
|
||||
if attached a_node.parent as l_parent then
|
||||
l_new_parent_id := l_parent.id
|
||||
else
|
||||
l_new_parent_id := 0
|
||||
end
|
||||
l_parameters.put (l_new_parent_id, "parent")
|
||||
if l_update and l_new_parent_id /= l_previous_parent_id then
|
||||
sql_change (sql_update_page_data, l_parameters)
|
||||
elseif l_new_parent_id > 0 then
|
||||
sql_change (sql_insert_page_data, l_parameters)
|
||||
l_has_modif := l_has_modif or (l_new_parent_id /= l_previous_parent_id)
|
||||
|
||||
create l_parameters.make (3)
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
l_parameters.put (a_node.revision, "revision")
|
||||
l_parameters.force (l_new_parent_id, "parent")
|
||||
|
||||
if l_update then
|
||||
if l_has_modif then
|
||||
sql_change (sql_update_node_data, l_parameters)
|
||||
end
|
||||
else
|
||||
-- no page data, means everything is empty.
|
||||
if l_has_modif then
|
||||
sql_change (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)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
load (a_node: CMS_PAGE)
|
||||
local
|
||||
ct: CMS_PAGE_NODE_TYPE
|
||||
l_parent_id: INTEGER_64
|
||||
do
|
||||
if attached node_data (a_node) as d then
|
||||
l_parent_id := d.parent_id
|
||||
if
|
||||
l_parent_id > 0 and then
|
||||
l_parent_id /= a_node.id and then
|
||||
attached node_storage.node_by_id (l_parent_id) as l_parent
|
||||
then
|
||||
if attached {CMS_PAGE_NODE_TYPE} node_api.content_type (l_parent.content_type) as l_parent_ct then
|
||||
ct := l_parent_ct
|
||||
else
|
||||
create ct
|
||||
end
|
||||
a_node.set_parent (ct.new_node (l_parent))
|
||||
else
|
||||
write_debug_log ("Invalid parent node id!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
node_data (a_node: CMS_NODE): detachable TUPLE [parent_id: INTEGER_64]
|
||||
local
|
||||
l_parameters: STRING_TABLE [ANY]
|
||||
n: INTEGER
|
||||
ct: CMS_PAGE_NODE_TYPE
|
||||
do
|
||||
error_handler.reset
|
||||
write_information_log (generator + ".fill_page")
|
||||
create l_parameters.make (2)
|
||||
l_parameters.put (a_node.id, "nid")
|
||||
l_parameters.put (a_node.revision, "revision")
|
||||
sql_query (sql_select_page_data, l_parameters)
|
||||
sql_query (sql_select_node_data, l_parameters)
|
||||
if not has_error then
|
||||
n := sql_rows_count
|
||||
if n = 1 then
|
||||
-- nid, revision, parent
|
||||
if
|
||||
attached sql_read_integer_64 (3) as l_parent_id and then
|
||||
l_parent_id /= a_node.id and then
|
||||
attached node_storage.node_by_id (l_parent_id) as l_parent
|
||||
then
|
||||
-- FIXME: find a simple way to access the declared content types.
|
||||
create ct
|
||||
a_node.set_parent (ct.new_node (l_parent))
|
||||
else
|
||||
write_debug_log ("Invalid parent node id!")
|
||||
end
|
||||
Result := [sql_read_integer_64 (3)]
|
||||
else
|
||||
check unique_data: n = 0 end
|
||||
end
|
||||
@@ -102,9 +133,8 @@ feature -- Persistence
|
||||
|
||||
feature -- SQL
|
||||
|
||||
sql_select_page_data: STRING = "SELECT nid, revision, parent FROM page_nodes WHERE nid =:nid AND revision=:revision;"
|
||||
sql_insert_page_data: STRING = "INSERT INTO page_nodes (nid, revision, parent) VALUES (:nid, :revision, :parent);"
|
||||
sql_update_page_data: STRING = "UPDATE page_nodes SET nid=:nid, revision=:revision, parent=:parent WHERE nid=:nid AND revision=:revision;"
|
||||
|
||||
sql_select_node_data: STRING = "SELECT nid, revision, parent FROM page_nodes WHERE nid =:nid AND revision<=:revision ORDER BY revision DESC LIMIT 1;"
|
||||
sql_insert_node_data: STRING = "INSERT INTO page_nodes (nid, revision, parent) VALUES (:nid, :revision, :parent);"
|
||||
sql_update_node_data: STRING = "UPDATE page_nodes SET nid=:nid, revision=:revision, parent=:parent WHERE nid=:nid AND revision=:revision;"
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user