Skip to content

Fix MySQL search_RMTObject and search_RMCObject end-to-end#5

Open
patrickoshaughnessey wants to merge 9 commits into
MetaversalCorp:mainfrom
PatchedReality:fix/search-procs-missing-out-param
Open

Fix MySQL search_RMTObject and search_RMCObject end-to-end#5
patrickoshaughnessey wants to merge 9 commits into
MetaversalCorp:mainfrom
PatchedReality:fix/search-procs-missing-out-param

Conversation

@patrickoshaughnessey

Copy link
Copy Markdown
Contributor

Summary

Four related bugs prevented every RMTObject:search and RMCObject:search
call from succeeding on MySQL deployments. This PR fixes all four at the
source level so neither proc requires special sql_mode or session
collation at deploy time. SQL_Server versions are unchanged — their
T-SQL equivalents already work correctly.

The four bugs (in order of when they surface)

1. Param-count mismatch — caught at protocol parse

The framework calls every proc as:

CALL <proc>(sIPAddress, twRPersonaIx, ...aData..., @result);
SELECT @result AS result;

That is 2 + len(aData) + 1 = 8 args for these search procs. Both procs
were declared with 7 IN params and 0 OUT params, so MySQL rejected every
call with:

Incorrect number of arguments for PROCEDURE <schema>.search_RMTObject;
expected 7, got 8
(mysql2 errno 1318, sqlState 42000)

Fix: add OUT nResult BIGINT to both procs (matches the convention
used by every other MySQL get_* / set_* proc in this repo) and assign
nResult at the end with the canonical formula

SET nResult = bCommit - 1 - nError;

(same as get_RMTObject_Update, get_RMRoot_Update, set_RMTObject_Type,
etc.). In search_RMCObject, replace the dead
SET nError = bCommit - bError - 1; line — assigned to a local that
nothing reads, clearly meant to be the missing OUT assignment — with the
canonical nResult assignment.

2. bError NULL init — would prevent success branch even after #1

Both procs declared bError INT without a DEFAULT, so bError started
as NULL. The expression IF bError = 0 then evaluated to NULL (falsy
in MySQL), making the success branch unreachable on the happy path:
every call would have fallen through to call_Error
('twRMTObjectIx is invalid' / 'twRMCObjectIx is invalid') even with
valid input. SQL_Server versions already declared @bError INT = 0, so
this was MySQL-only.

Fix: add DEFAULT 0 to bError declaration in both procs, matching
the adjacent bCommit / nError declarations and the SQL_Server
convention. Also added DEFAULT 0 to nError in search_RMTObject for
consistency (search_RMCObject already had it).

3. TRIM ( with space requires IGNORE_SPACE in sql_mode

The proc body had TRIM (IFNULL (sText, '')) (note the space after
TRIM). Without IGNORE_SPACE in the routine's stored sql_mode,
MySQL parses TRIM ( as a user-defined function call, and the call
fails at runtime with:

ERROR 1630: FUNCTION <schema>.TRIM does not exist

This made deployment of the procs sql_mode-dependent (works only when
the session that runs CREATE PROCEDURE happens to have IGNORE_SPACE
set).

Fix: remove the space in TRIM and IFNULL: TRIM(IFNULL(sText, '')).
Now the proc parses correctly under any sql_mode. (Other functions
like POW (, IF (, ArcLength ( do not have this issue and were left
unchanged for minimal diff — TRIM is one of the specific built-ins for
which MySQL's parser distinguishes a user-defined call from the built-in
based on whitespace, when IGNORE_SPACE is off.)

4. Collation mismatch on LIKE — would prevent body execution

The proc body did:

WHERE o.Name_wsRMTObjectId LIKE CONCAT(sText, '%')

The column Name_wsRMTObjectId carries utf8mb4_unicode_ci (declared
on the table) while parameter sText inherits the database's
DEFAULT_COLLATION (typically utf8mb4_0900_ai_ci on MySQL 8). Mixing
two IMPLICIT collations of different names raises:

ERROR 1267: Illegal mix of collations
(utf8mb4_unicode_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT)
for operation 'like'

Fix: add explicit COLLATE utf8mb4_unicode_ci on the LIKE expression
to force the comparison to the column's collation. EXPLICIT collation
trumps any IMPLICIT operand, so the LIKE works regardless of the database
default collation.

Verification

End-to-end CALL on a MySQL 8 instance with the default session
sql_mode (no IGNORE_SPACE) and default database collation
(utf8mb4_0900_ai_ci), against a table whose name column is
utf8mb4_unicode_ci, completes with @r = 0 (success).

Bug fixed up to Failure mode
(none) expected 7, got 8 (errno 1318)
#1, #2 FUNCTION <schema>.TRIM does not exist (errno 1630)
#1, #2, #3 Illegal mix of collations ... for operation 'like' (errno 1267)
#1#4 (this PR) clean: nResult = 0, results returned

- call_RMRoot_Event_RMCObject_Close: fix undefined variable twRMCObjectIx_Close (should be twRMCObjectIx), which caused all celestial scene deletion to fail
- set_RMCObject_RMTObject_Open: remove DECLARE nResult that shadows OUT parameter, causing NULL return on terrestrial object creation under celestial parents
- set_RMRoot_RMTObject_Open: same OUT parameter shadowing fix
- set_RMTObject_RMTObject_Open: same OUT parameter shadowing fix
- set_RMTObject_Transform: same OUT parameter shadowing fix
Brings the fork current through upstream's 11 commits since Feb 2026:
- SA reference updates, version bumps, doc additions
- Schema rename tmStart -> tmOrigin plus migration 002
- Upstream 'Bug fix' commits touching Delete_Descendants procs and Database.sql

Preserves fork-only fix c3b5458 (stored proc bugs blocking object
create/delete) since its four files have no overlap with upstream
changes. Pending fork PR MetaversalCorp#2 (fix/rmtsubsurface-delete-wipe) remains
on its own branch and is not affected.
Complete the fix described in c3b5458's commit message, which listed
this file but didn't include its changes. Applies the same nMatrixResult
treatment used in the sibling RMTObject_Open / Transform procs so matrix
subcall return codes don't stomp the outer procedure's OUT parameter.
…n changes

Reverts the nMatrixResult additions in the four _Open/Transform procs
(c3b5458 + a260654) — those were surgical against the pre-79c33e5
shadowing-DECLARE state; upstream dropped the shadow DECLARE directly
in 79c33e5 and rerouting matrix subcalls through a second local
variable no longer addresses any bug.

Reverts the c3b5458 line 60 change in call_RMRoot_Event_RMCObject_Close
(which upstream's 79c33e5 made valid by renaming the IN param).

Applies the actual remaining bug: line 82 of the same proc still
referenced the pre-rename identifier twRMCObjectIx, which is undefined
in the current scope. Changes it to the post-rename IN parameter
twRMCObjectIx_Close. Mirrors the SQL Server version of the same proc,
which uses @twRMCObjectIx_Close at the equivalent position.
… merge)

Absorbs upstream 6692689 + 09f637b — our PR's merged state, which
delivers the line 82 fix via a different commit path than fork main's
own 5195b24. Net content is unchanged.
The ELSE branch (taken when the parent is not an RMTObject — i.e. for
sectors directly under root) used a `SELECT ... INTO ...` pattern with
`mr.d23` and `mr.d22` listed in the wrong order against the
`d20, d21, d22, d23` INTO list.

In MySQL, `SELECT ... INTO ...` is positional, so this silently assigned
local `d22 := mr.d23` and `d23 := mr.d22`. The matrix-to-transform
extraction then computed `Transform_Scale_dZ = SQRT(... d22²) = 0` and
`Transform_Position_dZ = d23` from the wrong column, persisting
`scale.z = 0` and `position.z = <translation z>` to the RMTObject row
even though the underlying matrix was correct. Reads from the row
returned the corrupt values; subscriptions propagated them to clients.

The SQL Server version had the same out-of-order textual layout but the
syntax there is `@var = column` (assignment by name, not position), so
it was cosmetic only. Fix both for consistency so the parallel MySQL
bug isn't reintroduced by copying the SQL Server pattern.

Verified on a live database: a sector whose row had been corrupted
self-healed to the correct values on the next transform update after
the procedure was reloaded.
Pass parent context (ObjectHead_Parent_*) to call_RMTObject_Validate_Type
from set_RMTObject_Type. Without parent args, validation could not check
the parent class/index context.

Fixes set_RMTObject_Type validation context bug.
Fix swapped d22/d23 in call_RMTMatrix_Relative ELSE branch.

This fix has been hot-patched on production (spatial2) since 2026-05-05;
this merge brings it into the official line.
Four related bugs prevented every RMTObject:search and RMCObject:search
call from succeeding on MySQL deployments. This commit fixes all four
at the source level so neither proc requires special sql_mode or
session collation at deploy time.

1. PARAM-COUNT MISMATCH (caught at protocol layer)

The MSF node framework calls every proc with the form:
    CALL <proc>(sIPAddress, twRPersonaIx, ...aData..., @Result);
    SELECT @Result AS result;

That's 2 + len(aData) + 1 = 8 args for these search procs. Both procs
were declared with 7 IN params and 0 OUT params, so MySQL rejected
every CALL: 'Incorrect number of arguments for PROCEDURE
<schema>.search_RMTObject; expected 7, got 8' (mysql2 errno 1050,
sqlState 42S01).

Fix: add OUT nResult BIGINT to both procs (matches the convention used
by every other MySQL get_*/set_* proc in this repo) and set nResult at
the end with the canonical formula 'SET nResult = bCommit - 1 - nError;'
In search_RMCObject, replace the dead 'SET nError = bCommit - bError - 1;'
line (assigned to a local nothing reads, clearly meant to be the
missing OUT assignment) with the canonical nResult assignment.

2. bError NULL INIT (would prevent success path even after MetaversalCorp#1)

Both procs declared 'bError INT' without a DEFAULT, so bError started
as NULL. The expression 'IF bError = 0' then evaluated to NULL (falsy
in MySQL), which means the success branch was unreachable on the happy
path: every call would have fallen through to call_Error
('twRMTObjectIx is invalid' / 'twRMCObjectIx is invalid') even with
valid input. SQL_Server versions already declared @Berror with
'INT = 0', so this was MySQL-only.

Fix: add 'DEFAULT 0' to bError declaration in both procs, matching the
adjacent bCommit / nError declarations and the SQL_Server convention.
Also added DEFAULT 0 to nError in search_RMTObject for consistency
(search_RMCObject already had it).

3. TRIM ( with space requires IGNORE_SPACE in sql_mode (would prevent
   body execution after MetaversalCorp#1 and MetaversalCorp#2 unless deploy-time sql_mode set)

The proc body had 'TRIM (IFNULL (sText, ''))' (note the space after
TRIM). Without IGNORE_SPACE in the routine's stored sql_mode, MySQL
parses 'TRIM (' as a user-defined function call, and the CALL fails
at runtime with 'ERROR 1630: FUNCTION <schema>.TRIM does not exist'.
This made deployment of the procs sql_mode-dependent.

Fix: remove the space in TRIM and IFNULL: 'TRIM(IFNULL(sText, ''))'.
Now the proc parses correctly under any sql_mode. (Other functions
like POW (, IF (, CONCAT(, ArcLength ( do not have this issue and
were left unchanged for minimal diff.)

4. COLLATION MISMATCH ON LIKE (would prevent body execution after
   MetaversalCorp#1 MetaversalCorp#2 MetaversalCorp#3 unless DB default collation matches column collation)

The proc body did
   'WHERE o.Name_wsRMTObjectId LIKE CONCAT(sText, '%')'.
The column's collation is utf8mb4_unicode_ci (declared on the table)
while the parameter sText inherits the database's DEFAULT_COLLATION
(typically utf8mb4_0900_ai_ci on MySQL 8). Mixing two IMPLICIT
collations of different names raises 'ERROR 1267: Illegal mix of
collations (utf8mb4_unicode_ci,IMPLICIT) and
(utf8mb4_0900_ai_ci,IMPLICIT) for operation like'.

Fix: add explicit 'COLLATE utf8mb4_unicode_ci' on the LIKE expression
to force the comparison to the column's collation. EXPLICIT collation
trumps any IMPLICIT operand, so the LIKE works regardless of the
database default collation.

VERIFICATION

End-to-end CALL on a MySQL 8 instance with the default session
sql_mode (no IGNORE_SPACE) and database default collation
utf8mb4_0900_ai_ci, against a table whose name column is
utf8mb4_unicode_ci, completes with @r=0 (success) and produces
result rows. Pre-fix, the same CALL failed at the protocol layer
with 'expected 7, got 8'. After fixing only MetaversalCorp#1 and MetaversalCorp#2, it failed
with 'FUNCTION TRIM does not exist'. After also fixing MetaversalCorp#3, it
failed with 'Illegal mix of collations'. After all four, search
runs end-to-end.

SQL_Server versions are intentionally untouched (they already work
correctly via T-SQL syntax).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant