MULTIVALUE MIGRATION

Export your MultiValue data.

Choose your source system, review the configuration at the top of the program, and copy the complete exporter. Each version writes a portable Harbor Snapshot for RightMV.

01 / CHOOSE AND COPY

One format. Source-aware exporters.

The programs preserve item IDs and raw dynamic-array marks by encoding them as hexadecimal. Platform-specific account and file discovery stays in the exporter where it belongs.

Work on a consistent source. Use a quiesced system or supported snapshot, test with non-production data first, and protect the export as sensitive data.

Source systemjBASEGeneral jBASE accounts and files
* Program: ITERATE.ALL.EXPORT
* Description: Export all jBASE accounts, dictionaries, data files, and items
*              as a RightMV Harbor Snapshot v1 file.

    GOSUB INIT
    GOSUB PROCESS.ACCOUNTS
    GOSUB CLEANUP
    STOP

*-------------------------------------------------------------------------------
INIT:
*-------------------------------------------------------------------------------
    EXPORT.PATH = "c:\temp\my-export.mvoa"

    OPENSEQ EXPORT.PATH OVERWRITE TO F.EXPORT ELSE
        CREATE F.EXPORT ELSE
            CRT "ERROR: Cannot create output file at " : EXPORT.PATH
            STOP
        END
    END

    OPEN "SYSTEM" TO F.SYSTEM ELSE
        OPEN "SYSTEM.ACCOUNT" TO F.SYSTEM ELSE
            CRT "ERROR: Cannot open SYSTEM or SYSTEM.ACCOUNT."
            CLOSESEQ F.EXPORT
            STOP
        END
    END

    EXPORT.LINE = "MVOA 1"
    GOSUB WRITE.EXPORT.LINE
    EXPORT.LINE = "SOURCE-PRODUCT JBASE"
    GOSUB WRITE.EXPORT.LINE
    EXPORT.LINE = "SOURCE-CHARSET UNKNOWN"
    GOSUB WRITE.EXPORT.LINE
    EXPORT.LINE = "PAYLOAD-ENCODING HEX-BYTES"
    GOSUB WRITE.EXPORT.LINE
    RETURN

*-------------------------------------------------------------------------------
PROCESS.ACCOUNTS:
*-------------------------------------------------------------------------------
    SELECT F.SYSTEM TO ACCOUNT.LIST
    LOOP
        READNEXT ACCOUNT.NAME FROM ACCOUNT.LIST ELSE EXIT

        READ R.ACCOUNT FROM F.SYSTEM, ACCOUNT.NAME THEN
            ACCOUNT.PATH = R.ACCOUNT<2>
            IF ACCOUNT.PATH # "" THEN
                VOC.PATH = ACCOUNT.PATH : "/VOC"
                OPEN VOC.PATH TO F.VOC THEN
                    CRT "Processing Account: " : ACCOUNT.NAME

                    ACCOUNT.HEX = OCONV(ACCOUNT.NAME, "MX")
                    EXPORT.LINE = "ACCOUNT " : ACCOUNT.HEX
                    GOSUB WRITE.EXPORT.LINE

                    * Export the account VOC itself before following its file
                    * pointers. IMPORT-ALL uses this as ordinary DATA content.
                    FILE.NAME = "VOC"
                    FILE.NAME.HEX = OCONV(FILE.NAME, "MX")
                    EXPORT.LINE = "FILE DATA " : FILE.NAME.HEX
                    GOSUB WRITE.EXPORT.LINE
                    OPEN VOC.PATH TO F.HANDLE THEN
                        GOSUB PROCESS.ITEMS
                        CLOSE F.HANDLE
                    END

                    GOSUB PROCESS.FILES
                    CLOSE F.VOC
                END ELSE
                    CRT "WARNING: Cannot open VOC for account " : ACCOUNT.NAME
                END
            END
        END
    REPEAT
    RETURN

*-------------------------------------------------------------------------------
PROCESS.FILES:
*-------------------------------------------------------------------------------
    SELECT F.VOC TO VOC.LIST
    LOOP
        READNEXT VOC.ID FROM VOC.LIST ELSE EXIT

        READ R.VOC FROM F.VOC, VOC.ID THEN
            VOC.TYPE = R.VOC<1>

            * A ]D companion is exported through its owning file.
            IS.DICT.POINTER = 0
            IF LEN(VOC.ID) >= 2 THEN
                IF VOC.ID[LEN(VOC.ID)-1, 2] = "]D" THEN IS.DICT.POINTER = 1
            END

            IF (VOC.TYPE = "F" OR VOC.TYPE = "F4") AND NOT(IS.DICT.POINTER) THEN
                FILE.NAME = VOC.ID
                FILE.NAME.HEX = OCONV(FILE.NAME, "MX")

                PHYSICAL.FILE = R.VOC<2>
                IF PHYSICAL.FILE = "" THEN PHYSICAL.FILE = FILE.NAME

                * Resolve relative paths beneath the account directory while
                * retaining Unix, UNC, and drive-letter absolute paths.
                IS.ABSOLUTE = 0
                IF PHYSICAL.FILE[1, 1] = "/" THEN IS.ABSOLUTE = 1
                IF PHYSICAL.FILE[1, 1] = "\" THEN IS.ABSOLUTE = 1
                IF LEN(PHYSICAL.FILE) >= 2 THEN
                    IF PHYSICAL.FILE[2, 1] = ":" THEN IS.ABSOLUTE = 1
                END
                IF NOT(IS.ABSOLUTE) THEN
                    PHYSICAL.FILE = ACCOUNT.PATH : "/" : PHYSICAL.FILE
                END

                OPEN "DICT", PHYSICAL.FILE TO F.HANDLE THEN
                    CRT "  Exporting DICT " : FILE.NAME
                    EXPORT.LINE = "FILE DICT " : FILE.NAME.HEX
                    GOSUB WRITE.EXPORT.LINE
                    GOSUB PROCESS.ITEMS
                    CLOSE F.HANDLE
                END

                OPEN PHYSICAL.FILE TO F.HANDLE THEN
                    CRT "  Exporting DATA " : FILE.NAME
                    EXPORT.LINE = "FILE DATA " : FILE.NAME.HEX
                    GOSUB WRITE.EXPORT.LINE
                    GOSUB PROCESS.ITEMS
                    CLOSE F.HANDLE
                END ELSE
                    CRT "WARNING: Cannot open data file " : PHYSICAL.FILE
                END
            END
        END
    REPEAT
    RETURN

*-------------------------------------------------------------------------------
PROCESS.ITEMS:
*-------------------------------------------------------------------------------
    SELECT F.HANDLE TO ITEM.LIST
    LOOP
        READNEXT ITEM.ID FROM ITEM.LIST ELSE EXIT

        READ R.ITEM FROM F.HANDLE, ITEM.ID THEN
            ITEM.ID.HEX = OCONV(ITEM.ID, "MX")
            ITEM.DATA.HEX = OCONV(R.ITEM, "MX")
            ITEM.SIZE = LEN(R.ITEM)

            * ITEM <hex-id> <decoded-byte-count> <hex-payload>
            EXPORT.LINE = "ITEM " : ITEM.ID.HEX : " " : ITEM.SIZE
            IF ITEM.SIZE > 0 THEN
                EXPORT.LINE = EXPORT.LINE : " " : ITEM.DATA.HEX
            END
            GOSUB WRITE.EXPORT.LINE
        END
    REPEAT
    RETURN

*-------------------------------------------------------------------------------
WRITE.EXPORT.LINE:
*-------------------------------------------------------------------------------
    WRITESEQ EXPORT.LINE APPEND TO F.EXPORT ELSE
        CRT "ERROR: Snapshot write failed. Output is incomplete."
        CLOSESEQ F.EXPORT
        STOP
    END
    RETURN

*-------------------------------------------------------------------------------
CLEANUP:
*-------------------------------------------------------------------------------
    EXPORT.LINE = "END"
    GOSUB WRITE.EXPORT.LINE
    CLOSE F.SYSTEM
    CLOSESEQ F.EXPORT
    CRT "Export completed successfully to " : EXPORT.PATH
    RETURN

02 / IMPORT

Load the snapshot into RightMV.

Move the generated .mvoa file to the RightMV host, then run:

IMPORT-ALL /path/to/export.mvoa

BEFORE PRODUCTION

Verify, reconcile, then migrate.

Compare account, file and item counts; sample empty and multivalued records; validate dictionaries and business totals; and keep the source system unchanged until acceptance is complete.

Download RightMV →