1

I'm working on a project where we are to convert some Oracle stored procedures into python via sqlalchemy. The issue is that we are also to use sqlite (We are unable to change this as those above us have made the decision for this structure) for testing and that causes issues with certain functions (in particular instr/position). I started off attempting to just do everything in the where clause with func.substr and func.strpos but strpos causes a failure in sqlite as it doesn't exist.

I then attempted to work it with a filter statement using python slicing and find to get what I needed but this returns an error that "getItem is not supported in this expression". I'm not quite sure what is causing that issue, and I'm starting to hit a wall as to how I should work these statements out so that they work both in prod and testing.

This is the original plsql statement:

UPDATE MC.SFCOBS SFC
SET SFC.WINDDIRECTION = NULL,
    SFC.WINDSPEED = NULL,
    SFC.WINDCONDITIONS = NULL,
    SFC.WINDCONDITIONSQUALITYCODE = '5',
    SFC.WINDSPEEDQUALITYCODE = CASE WHEN SFC.WINDSPEED = 0 THEN '5' ELSE NULL END
WHERE SFC.WINDCONDITIONS = 'C'
AND (SFC.WINDSPEED = 0 OR SFC.WINDSPEED IS NULL)
AND EXISTS (
    SELECT 'X'
    FROM MC.JOBS OBS
    WHERE OBS.OBSERVATIONID = SFC.OBSERVATIONID
    AND OBS.REPORTTYPECODE IN ('FM-12', 'FM-13', 'FM-14')
    AND OBS.INSERTIONTIME >= startdatetime
    AND OBS.INSERTIONTIME < enddatetime
    AND OBS.OBSERVATIONID = SFC.OBSERVATIONID)
    AND SFC.OBSERVATIONID = (
        SELECT MSG.OBSERVATIONID
        FROM MC.JMO_MESSAGE MSG
        WHERE MSG.OBSERVATIONID = SFC.OBSERVATIONID
        AND (
            SUBSTR(MSG.ORIGINALMESSAGE, 16, 4) = '// 1'
            OR SUBSTR(MSG.ORIGINALMESSAGE, 14, 5) = '//// '
            OR SUBSTR(MSG.ORIGINALMESSAGE, INSTR (MSG.ORIGINALMESSAGE, ' 26/// ') + 10, 3) = '// '
            AND INSTR(MSG.ORIGINALMESSAGE, ' 26/// ') > 3
            OR SUBSTR(MSG.ORIGINALMESSAGE, INSTR (MSG.ORIGINALMESSAGE, ' 99') + 22, 3) = '// '
            AND INSTR(MSG.ORIGINALMESSAGE, ' 99') BETWEEN 11 AND 20
            OR SUBSTR (MSG.ORIGINALMESSAGE, 7, 6) IN ('45/// ', '46/// ')
            AND SUBSTR (MSG.ORIGINALMESSAGE, 16, 3) = '// ')
);

the issue is in the very end where all of the substr and isntr are.

Here is the original where clause

.where(
                JmoMessageTable.observationid == sfc.observationid
                or_(
                    func.substr(JmoMessageTable.originalmessage, 16, 4) == "// 1",
                    func.substr(JmoMessageTable.originalmessage, 14, 5) == "//// ",
                    func.substr(JmoMessageTable.originalmessage, func.strpos(JmoMessageTable.originalmessage, " 26/// ") + 10, 3) == "// "
                ),
                or_(
                    func.substr(JmoMessageTable.originalmessage, 16, 4) == "// 1",
                    func.substr(JmoMessageTable.originalmessage, func.strpos(JmoMessageTable.originalmessage, " 99") + 22, 3) == "// "
                ),
                or_(
                    func.strpos(JmoMessageTable.originalmessage, " 99").between(11, 20),
                    func.substr(JmoMessageTable.originalmessage, 7, 6).in_(("45/// ", "46/// "))
                ),
                func.substr(JmoMessageTable.originalmessage, 16, 3) == "// "
            )

Here is the filter I attempted after

.filter(
                or_(
                    JmoMessageTable.originalmessage[16:20] == "// 1",
                    JmoMessageTable.originalmessage[14:19] == "//// ",
                    JmoMessageTable.originalmessage[(JmoMessageTable.originalmessage.find(" 26/// ") + 10):((JmoMessageTable.originalmessage.find(" 26/// ") + 10) + 3)] == "// "
                ),
                or_(
                    JmoMessageTable.originalmessage[16:20] == "// 1",
                    JmoMessageTable.originalmessage[(JmoMessageTable.originalmessage.find(" 99") + 22):((JmoMessageTable.originalmessage.find(" 99") + 22) + 3)] == "// ",
                ),
                or_(
                    (JmoMessageTable.originalmessage.find(" 99") >= 11 & JmoMessageTable.originalmessage.find(" 99") <= 20),
                    (JmoMessageTable.originalmessage[7:13] == "45/// " | JmoMessageTable.originalmessage[7:13] == "46/// ")
                ),
                JmoMessageTable.originalmessage[16:19] == "// "
            )

Is there a way to work this as I have it? Or am I going to be stuck using ORM to attempt to pull and filter everything based on these parameters? Any help or input would be helpful! Thanks

2
  • 1) Test against the database you will deploy to otherwise you will be dealing with this sort of bugs constantly. In other words you will be testing you test process not the underlying code. 2) I like Sqlite, but it a particularly bad choice for this situation, it an embedded database with permissive typing. Your code is being written for a client/server database with strict typing, not a good combination. Commented May 20 at 17:32
  • I do absolutely agree with what you are saying, I would much rather spin up a container with a postgres instance inside for testing but it is out of my hands and this is all we are allowed to use. They told us we needed to use an in memory DB for testing and they landed on Sqlite. We are unable to change how this aspect and so I'm in a bind trying to figure out how to work this out even if it is not a great option and could cause issues Commented May 20 at 17:43

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.