SQLite Forum

Building SQLIte3 wiuth debug options fails on UBUNTU
Login

Building SQLIte3 wiuth debug options fails on UBUNTU

(1) By anonymous on 2020-06-23 06:18:08 [link]

Dear forum member,

I a script to build a debug option of SQLITE3 so I can use .selecttrace and .wheretrace.

The result is:
 .selecttrace will result in a segment fault when I use Linux Mint.
  UBUNTU will NOT compile a DEBUG version and .selecttrace or .whjeretrace WILL NOT WORK.

P.S. is there a method to reset my password to allow me to login???

Here is the script with all the options I am using. Feel free to modify it so other users can build a custom SQLite3 version.
#! /bin/bash
usage="Usage : '$0 ' [-hbd]"

if [[ $1 =~ (-[bdh]) ]]; then
        echo "--------------"
else
        echo "Not a valid option is given!"
        echo $Usage
        exit 1
fi

while getopts "bdh" opt; do
  case ${opt} in
    h )
        echo $usage
        echo "Options:"
        echo "    -b            Compile without debug options"
        echo "    -d            Compile with debug options"
        echo "    -h            This menu for help"
        exit 0
      ;;
    b )
        echo "Building SQLite3 without debug options"
        export CFLAGS="-fPIC \
                -DSQLITE_ENABLE_FTS3  \
                -DSQLITE_ENABLE_FTS3_PARENTHESIS  \
                -DSQLITE_ENABLE_FTS4 \
                -DSQLITE_ENABLE_FTS5 \
                -DSQLITE_ENABLE_JSON1 \
                -DSQLITE_ENABLE_LOAD_EXTENSION \
                -DSQLITE_ENABLE_RTREE \
                -DSQLITE_ENABLE_STAT4 \
                -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT \
                -DSQLITE_TEMP_STORE3 \
                -DSQLITE_USE_URI \
                -O2 "
        ;;
    d )
        echo "Bulding SQLite3 with debug options"
        export SQLITE3_CFLAGS="-fPIC \
                -DSQLITE_ENABLE_FTS3 \
                -DSQLITE_ENABLE_FTS3_PARENTHESIS  \
                -DSQLITE_ENABLE_FTS4 \
                -DSQLITE_ENABLE_FTS5 \
                -DSQLITE_ENABLE_JSON1 \
                -DSQLITE_ENABLE_LOAD_EXTENSION \
                -DSQLITE_ENABLE_RTREE \
                -DSQLITE_ENABLE_STAT4 \
                -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT \
                -DSQLITE_TEMP_STORE3 \
                -DSQLITE_USE_URI \
                -DSQLITE_DEBUG \
                -DSQLITE_ENABLE_EXPLAIN_COMMENTS \
                -DSQLITE_ENABLE_SELECTTRACE \
                -DSQLITE_ENABLE_WHERETRACE \
                -O2"
        ;;
    * )
        echo "Invalid Option: -$OPTARG" 
        echo $usage >&2
        exit 1
      ;;
  esac
done

LIBS="-lm" ./configure --enable-shared --prefix="$PREFIX"

make

sudo make install

(2) By Richard Hipp (drh) on 2020-06-23 10:03:32 in reply to 1 [link]

Wouldn't it be easier to just do the following (which is known to work):

>     ./configure --enable-debug --enable-all && make

I don't know why your build is segfaulting.  Perhaps you could run it
in "gdb" and report a stack on this mailing list.

(3) By anonymous on 2020-06-24 09:37:08 in reply to 2 [link]

And here is the result when I use the mentioned option
(Note that is the last part!)
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... no
checking for gcc option to produce PIC... -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works... yes
checking if gcc static flag -static works... yes
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... GNU/Linux ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... yes
checking for fdatasync... yes
checking for usleep... yes
checking for fullfsync... no
checking for localtime_r... yes
checking for gmtime_r... yes
checking whether strerror_r is declared... yes
checking for strerror_r... yes
checking whether strerror_r returns char *... no
checking editline/readline.h usability... no
checking editline/readline.h presence... no
checking for editline/readline.h... no
checking readline/readline.h usability... yes
checking readline/readline.h presence... yes
checking for readline/readline.h... yes
checking for library containing tgetent... -ltermcap
checking for library containing readline... -lreadline
checking for library containing pthread_create... -lpthread
checking for library containing pthread_mutexattr_init... none required
checking for library containing dlopen... -ldl
checking for whether to support dynamic extensions... yes
checking for library containing log... -lm
checking for posix_fallocate... yes
checking zlib.h usability... yes
checking zlib.h presence... yes
checking for zlib.h... yes
checking for library containing deflate... -lz
checking for library containing system... none required
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating sqlite3.pc
config.status: executing depfiles commands
config.status: executing libtool commands
configure: WARNING: unrecognized options: --enable-all
make: Nothing to be done for 'all'.

So I removed the directory, unpacked and I compiled source.
I am able to reproduce the error I had on the Linux Mint system when I execute .selecttrace. Here is the message:
fish: “./sqlite3” terminated by signal SIGSEGV (Address boundary error)

(4) By anonymous on 2020-06-24 10:06:02 in reply to 2 [link]

Here is the GDB info
fish: “./sqlite3” terminated by signal SIGSEGV (Address boundary error)
Program received signal SIGSEGV, Segmentation fault.
0x000055555556888c in integerValue (zArg=0x0) at shell.c:762
762       if( zArg[0]=='-' ){
-- more source lines
755         { "GB",  1000000000 },
756         { "K",   1000 },
757         { "M",   1000000 },
758         { "G",   1000000000 },
759       };
760       int i;
761       int isNeg = 0;
762       if( zArg[0]=='-' ){
763         isNeg = 1;
764         zArg++;
p
v = 0
aMult = {{zSuffix = 0x55555570e695 "KiB", iMult = 1024}, {zSuffix = 0x55555570e699 "MiB", iMult = 1048576}, {zSuffix = 0x55555570e69d "GiB", iMult = 1073741824}, {zSuffix = 0x55555570e6a1 "KB", iMult = 1000}, {zSuffix = 0x55555570e6a4 "MB", iMult = 1000000}, {zSuffix = 0x55555570e6a7 "GB", iMult = 1000000000}, {
    zSuffix = 0x55555570e6aa "K", iMult = 1000}, {zSuffix = 0x55555570e6ac "M", iMult = 1000000}, {zSuffix = 0x55555570e6ae "G", iMult = 1000000000}}
i = 21845
isNeg = 0
l
Is tthis a problem? → zArg = 0x0
bt
#0  integerValue (zArg=0x0) at shell.c:762
#1  0x000055555558f7c9 in do_meta_command (zLine=0x5555557d9440 ".selecttrace", p=0x7fffffffc8f0) at shell.c:17488
#2  0x0000555555593094 in process_input (p=0x7fffffffc8f0) at shell.c:18718
#3  0x0000555555594ef6 in main (argc=1, argv=0x7fffffffdef8) at shell.c:19521

(5) By Richard Hipp (drh) on 2020-06-24 12:00:46 in reply to 4 [link]

Please try again using the latest [Prerelease Snapshot][1] and report back
if you continue to have problems.

[1]: https://www.sqlite.org/download.html

(6) By anonymous on 2020-06-24 12:37:53 in reply to 5 [link]

Problem solved on Ubuntu! Thx.
I will check Mint later today…

(7) By anonymous on 2020-06-24 19:27:35 in reply to 5 [link]

Problem is also solved for the Mint platform! Thx
Is there documentation how to interpret the .selecttrace log

(8) By Richard Hipp (drh) on 2020-06-24 20:19:16 in reply to 7 [link]

> Is there documentation how to interpret the .selecttrace log

No.  The ".selecttrace" command is designed for use by the developers
when debugging the code generator.  The flags that ".selecttrace" accepts
and the output from ".selecttrace" changes from one release to the next.
We can, and often do, change the behavior of ".selecttrace" depending on
what problem we are working on and the data structure visualization needs
associated with that problem.

The general idea remains the same, however.  The sqlite3Select() routine
is invoked with a pointer to a Select object.  A Select object is the head
of a tree that describes a single SELECT statement.  This Select object
will be processed and transformed in order to generate byte-code to implement
the SELECT statement.  The ".selecttrace" command outputs snapshots of the
Select object and all of its substructure as the object is processed.

Usually we invoke ".selecttrace 0xffff".  That turns on all of the tracing
capabilities.  When we run a query.  The first graph shows the raw parse
tree straight out of the parser.  The first transformation is to walk the
graph and resolve all of the identifiers and expand "*" operators in the
result set.  After this name resolution, the graph is redrawn.  Then
various optimizations are applied, which typically transform the graph
further.

Note that when there are subqueries, the sqlite3Select() routine is invoked
recursively.  Each entry and exit from sqlite3Select() is announced.

It is usually necessary to be looking at the source code in order to understand
the details of what the .selecttrace output means.

(9) By anonymous on 2020-06-25 12:20:27 in reply to 8 [link]

Its the bytre code I want to read.
Try this example:
-- character encoding
PRAGMA encoding = 'UTF-16le';

-- Journalling mode
PRAGMA journal_mode=WAL;

-- Automatic ANALYZE
PRAGMA optimize;

CREATE TABLE IF NOT EXISTS A1 (
    A1_INDEX VARCHAR(20),
    A1_CAT VARCHAR(1) DEFAULT 'W',
    A1_STOCK_MIN INTEGER,
    A1_STOCK_LEVEL INTEGER,
    A1_PRODUCT TEXT,
    A1_STATUS NUMBER
        CHECK (A1_STATUS IN (1, 2, 4, 8, 16, 32, 64, 128)) DEFAULT 1,
    A1_REF VARCHAR(20) CHECK (A1_REF != A1_INDEX),
    A1_DTS_CREATED TEXT NOT NULL DEFAULT (DATETIME('NOW', 'UTC')),
    A1_DTS_UPDATED TEXT NOT NULL DEFAULT (DATETIME('NOW', 'UTC')),
    CONSTRAINT LOCATION_PK PRIMARY KEY (
        A1_INDEX,
        A1_CAT
    )   
--    UNIQUE (
--      A1_INDEX,
--        A1_CAT,
--    ) ON CONFLICT ROLLBACK
);

INSERT INTO A1 (A1_INDEX, A1_STOCK_MIN, A1_STOCK_LEVEL, A1_PRODUCT, A1_REF)
VALUES 
        (12, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Drei im Weggla', NULL),
        ( 7, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Blaue Zipfel mit Brezel', NULL),
        (17, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Nürnberger Rostbratwurst', NULL),
        (14, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Brätwurst', 17),
        (19, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Brühwürste', NULL);
    
CREATE TRIGGER IF NOT EXISTS A1_STOCK_UPDATE BEFORE UPDATE ON A1
WHEN (A1_STATUS = 2) AND (A1_REF ISNULL)
BEGIN
        SELECT CASE 1
                WHEN (NEW.A1_STATUS == 2)
                        THEN CASE 1
                                WHEN (NOT (OLD.A1_STATUS IN (1, 8, 32, 64))) OR (((OLD.A1_REF NOT NULL)) AND (NOT (OLD.A1_STATUS == 4)))
                                        THEN RAISE (ABORT, 'Error: someone goofed')
                                END
                        END
                END;

END;
~                                                                                                                                                                                                                                                                                                                           
~                       
It will not work and result in all sorts of erros

(10) By TripeHound on 2020-06-25 13:28:55 in reply to 9 [link]

I've just pasted that into an sqlite3 prompt and tried:

```
update a1 set a1_stock_min=222 where a1_index=12 ;
```

which gives:

```
Error: no such column: A1_STATUS
```

leading me to suspect:

```
WHEN (A1_STATUS = 2) AND (A1_REF ISNULL)
```

should have `OLD.` or `NEW.` added to `A1_STATUS` and `A1_REF`. Adding either allows the update to work (though I've no idea whether the trigger is doing what it's meant to do).

I don't know what "all sorts of errors" you're seeing, but a good starting point if there are lot (whether it's SQL or compiler errors) is to ignore everything except the first one. Fix that then try again.

(11) By anonymous on 2020-06-25 18:12:52 in reply to 10

Which is correct. I should have issued a NEW in front of the variables.

However:
The missing NEW isn't detected when I build the database. I think that this is an error in the build function.

But it gets a little stranger when you execute this trigger with the  .selecttrace option. Notice that SQLite has detected that A1_STATUS is available at the start!

I get the impression that the 'sudden death' of the optimizer function that halts the execution.

Here is the result:
SQLite version 3.33.0 2020-06-24 11:45:35
Enter ".help" for usage hints.
sqlite> .selecttrace 0xffff
sqlite> update a1 set
   ...> a1_status = 2
   ...> where a1_index == 17;
1/0/563925A66748: begin processing:
'-- SELECT (1/563925A66748) selFlags=0x0 nSelectRow=0
    |-- result-set
    |   '-- op=177
    |-- FROM
    |   '-- {-1:*} main.sqlite_master
    '-- ORDERBY
        '-- ID "rowid"
1/0/563925A66748: after name resolution:
'-- SELECT (1/563925A66748) selFlags=0xc4 nSelectRow=0
    |-- result-set
    |   |-- AS type
    |   |   '-- {0:0} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS name
    |   |   '-- {0:1} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS tbl_name
    |   |   '-- {0:2} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS rootpage
    |   |   '-- {0:3} pTab=563925AC8BB8 fg.af=800000.n
    |   '-- AS sql
    |       '-- {0:4} pTab=563925AC8BB8 fg.af=800000.n
    |-- FROM
    |   '-- {0:*} main.sqlite_master tab='sqlite_master' nCol=5 ptr=563925AC8BB8 used=1f
    '-- ORDERBY
        '-- {0:-1} pTab=563925AC8BB8 fg.af=800000.D
1/0/563925A66748: generating column names
1/0/563925A66748: Constant propagation not helpful
1/0/563925A66748: After all FROM-clause analysis:
'-- SELECT (1/563925A66748) selFlags=0xc4 nSelectRow=0
    |-- result-set
    |   |-- AS type
    |   |   '-- {0:0} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS name
    |   |   '-- {0:1} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS tbl_name
    |   |   '-- {0:2} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS rootpage
    |   |   '-- {0:3} pTab=563925AC8BB8 fg.af=800000.n
    |   '-- AS sql
    |       '-- {0:4} pTab=563925AC8BB8 fg.af=800000.n
    |-- FROM
    |   '-- {0:*} main.sqlite_master tab='sqlite_master' nCol=5 ptr=563925AC8BB8 used=1f
    '-- ORDERBY
        '-- {0:-1} pTab=563925AC8BB8 fg.af=800000.D
1/0/563925A66748: WhereBegin
1/0/563925A66748: end processing
'-- SELECT (1/563925A66748) selFlags=0xc4 nSelectRow=200
    |-- result-set
    |   |-- AS type
    |   |   '-- {0:0} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS name
    |   |   '-- {0:1} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS tbl_name
    |   |   '-- {0:2} pTab=563925AC8BB8 fg.af=800000.n
    |   |-- AS rootpage
    |   |   '-- {0:3} pTab=563925AC8BB8 fg.af=800000.n
    |   '-- AS sql
    |       '-- {0:4} pTab=563925AC8BB8 fg.af=800000.n
    |-- FROM
    |   '-- {0:*} main.sqlite_master tab='sqlite_master' nCol=5 ptr=563925AC8BB8 used=1f
    '-- ORDERBY
        '-- {0:-1} pTab=563925AC8BB8 fg.af=800000.D
Error: no such column: A1_STATUS

SQLite suddenly kills the transaction while it tries to optimize the code.

I will add the NEW tomorrow and rerun the test. I am expecting that it will fail executing the condition.

(12) By anonymous on 2020-06-26 06:14:52 in reply to 11 [link]

Here is the test with the corrected code:
-- character encoding
PRAGMA encoding = 'UTF-16le';

-- Journalling mode
PRAGMA journal_mode=WAL;

-- Automatic ANALYZE
PRAGMA optimize;

CREATE TABLE IF NOT EXISTS A1 (
    A1_INDEX VARCHAR(20),
    A1_CAT VARCHAR(1) DEFAULT 'W',
    A1_STOCK_MIN INTEGER,
    A1_STOCK_LEVEL INTEGER,
    A1_PRODUCT TEXT,
    A1_STATUS NUMBER
        CHECK (A1_STATUS IN (1, 2, 4, 8, 16, 32, 64, 128)) DEFAULT 1,
    A1_REF VARCHAR(20) CHECK (A1_REF != A1_INDEX),
    A1_DTS_CREATED TEXT NOT NULL DEFAULT (DATETIME('NOW', 'UTC')),
    A1_DTS_UPDATED TEXT NOT NULL DEFAULT (DATETIME('NOW', 'UTC')),
    CONSTRAINT LOCATION_PK PRIMARY KEY (
        A1_INDEX,
        A1_CAT
    )
--    UNIQUE (
--      A1_INDEX,
--        A1_CAT,
--    ) ON CONFLICT ROLLBACK
);

INSERT INTO A1 (A1_INDEX, A1_STOCK_MIN, A1_STOCK_LEVEL, A1_PRODUCT, A1_REF)
VALUES
        (12, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Drei im Weggla', NULL),
        ( 7, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Blaue Zipfel mit Brezel', NULL),
        (17, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Nürnberger Rostbratwurst', NULL),
        (14, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Brätwurst', 17),
        (19, cast(abs((0.0661 * random()) % 997 +1) as integer), ABS(RANDOM() % 14731) + 1, 'Brühwürste', NULL);

CREATE TRIGGER IF NOT EXISTS A1_STOCK_UPDATE BEFORE UPDATE ON A1
WHEN (NEW.A1_STATUS = 2) AND (NEW.A1_REF ISNULL)
BEGIN
        SELECT CASE 1
                WHEN (NEW.A1_STATUS == 2)
                        THEN CASE 1
                                WHEN (NOT (OLD.A1_STATUS IN (1, 8, 32, 64))) OR (((OLD.A1_REF NOT NULL)) AND (NOT (OLD.A1_STATUS == 4)))
                                        THEN RAISE (ABORT, 'Error: someone goofed')
                                END
                        END
                END;

END;

Here is the test:
.selecttrace 0xfffff

UPDATE A1 SET
A1_STATUS = 2
WHERE A1_INDEX == 14;

Here is the .selecttrace
'-- SELECT (1/55A1FF75DF48) selFlags=0x0 nSelectRow=0
    '-- result-set
        '-- AS END
            '-- CASE
                |-- 1
                '-- LIST
                    |-- EQ fg.af=40000000.n DDL
                    |   |-- DOT fg.af=40000000.n DDL
                    |   |   |-- ID "NEW"
                    |   |   '-- ID "A1_STATUS"
                    |   '-- 2
                    '-- CASE
                        |-- 1
                        '-- LIST
                            |-- OR fg.af=40000000.n DDL
                            |   |-- NOT fg.af=40000000.n DDL
                            |   |   '-- IN flags=0x40000000
                            |   |       |-- DOT fg.af=40000000.n DDL
                            |   |       |   |-- ID "OLD"
                            |   |       |   '-- ID "A1_STATUS"
                            |   |       '-- LIST
                            |   |           |-- 1
                            |   |           |-- 8
                            |   |           |-- 32
                            |   |           '-- 64
                            |   '-- AND fg.af=40000000.n DDL
                            |       |-- NOTNULL fg.af=40000000.n DDL
                            |       |   '-- DOT fg.af=40000000.n DDL
                            |       |       |-- ID "OLD"
                            |       |       '-- ID "A1_REF"
                            |       '-- NOT fg.af=40000000.n DDL
                            |           '-- EQ fg.af=40000000.n DDL
                            |               |-- DOT fg.af=40000000.n DDL
                            |               |   |-- ID "OLD"
                            |               |   '-- ID "A1_STATUS"
                            |               '-- 4
                            '-- RAISE abort('Error: someone goofed')
1/0/55A1FF75DF48: after name resolution:
'-- SELECT (1/55A1FF75DF48) selFlags=0x4000c4 nSelectRow=0
    '-- result-set
        '-- AS END
            '-- CASE
                |-- 1
                '-- LIST
                    |-- EQ fg.af=40000000.n DDL
                    |   |-- NEW(5)
                    |   '-- 2
                    '-- CASE
                        |-- 1
                        '-- LIST
                            |-- OR fg.af=40000000.n DDL
                            |   |-- NOT fg.af=40000000.n DDL
                            |   |   '-- IN flags=0x40000000
                            |   |       |-- OLD(5)
                            |   |       '-- LIST
                            |   |           |-- 1
                            |   |           |-- 8
                            |   |           |-- 32
                            |   |           '-- 64
                            |   '-- AND fg.af=40000000.n DDL
                            |       |-- NOTNULL fg.af=40000000.n DDL
                            |       |   '-- OLD(6)
                            |       '-- NOT fg.af=40000000.n DDL
                            |           '-- EQ fg.af=40000000.n DDL
                            |               |-- OLD(5)
                            |               '-- 4
                            '-- RAISE abort('Error: someone goofed')
1/0/55A1FF75DF48: Constant propagation not helpful
1/0/55A1FF75DF48: After all FROM-clause analysis:
'-- SELECT (1/55A1FF75DF48) selFlags=0x4000c4 nSelectRow=0
    '-- result-set
        '-- AS END
            '-- CASE
                |-- 1
                '-- LIST
                    |-- EQ fg.af=40000000.n DDL
                    |   |-- NEW(5)
                    |   '-- 2
                    '-- CASE
                        |-- 1
                        '-- LIST
                            |-- OR fg.af=40000000.n DDL
                            |   |-- NOT fg.af=40000000.n DDL
                            |   |   '-- IN flags=0x40000000
                            |   |       |-- OLD(5)
                            |   |       '-- LIST
                            |   |           |-- 1
                            |   |           |-- 8
                            |   |           |-- 32
                            |   |           '-- 64
                            |   '-- AND fg.af=40000000.n DDL
                            |       |-- NOTNULL fg.af=40000000.n DDL
                            |       |   '-- OLD(6)
                            |       '-- NOT fg.af=40000000.n DDL
                            |           '-- EQ fg.af=40000000.n DDL
                            |               |-- OLD(5)
                            |               '-- 4
                            '-- RAISE abort('Error: someone goofed')
1/0/55A1FF75DF48: WhereBegin
1/0/55A1FF75DF48: end processing
'-- SELECT (1/55A1FF75DF48) selFlags=0x4000c4 nSelectRow=0
    '-- result-set
        '-- AS END
            '-- CASE
                |-- 1
                '-- LIST
                    |-- EQ fg.af=40000000.n DDL
                    |   |-- NEW(5)
                    |   '-- 2
                    '-- CASE
                        |-- 1
                        '-- LIST
                            |-- OR fg.af=40000000.n DDL
                            |   |-- NOT fg.af=40000000.n DDL
                            |   |   '-- IN flags=0x42000000
                            |   |       |-- OLD(5)
                            |   |       '-- LIST
                            |   |           |-- 1
                            |   |           |-- 8
                            |   |           |-- 32
                            |   |           '-- 64
                            |   '-- AND fg.af=40000000.n DDL
                            |       |-- NOTNULL fg.af=40000000.n DDL
                            |       |   '-- OLD(6)
                            |       '-- NOT fg.af=40000000.n DDL
                            |           '-- EQ fg.af=40000000.n DDL
                            |               |-- OLD(5)
                            |               '-- 4
                            '-- RAISE abort('Error: someone goofed')

Based on the .selecttrace I am tempted to conclude that the updated isn't executed. If I check the column the update was executed.

Observations why is are there 4 attempts after the row was selected?

(13) By anonymous on 2020-06-26 09:05:44 in reply to 12 [link]

And then I changed the A1_STATUS to 1 which should ignore the trigger after testing the condition.
Here is the test:
.selecttrace 0xfffff

UPDATE A1 SET
A1_STATUS = 1
WHERE A1_INDEX == 14;

Examining the .selecttrace log I discovered that the SQLite optimize-function attempts to execute((?) or scan(?) the trigger. So I made an error in the trigger to proof this:
CREATE TRIGGER IF NOT EXISTS A1_STOCK_UPDATE BEFORE UPDATE ON A1
WHEN (NEW.A1_STATUS = 2) AND (NEW.A1_REF ISNULL)
BEGIN
        SELECT CASE 1
                WHEN (NEW.A2_STATUS == 2)
                        THEN CASE 1
                                WHEN (NOT (OLD.A1_STATUS IN (1, 8, 32, 64))) OR (((OLD.A1_REF NOT NULL)) AND (NOT (OLD.A1_STATUS == 4)))
                                        THEN RAISE (ABORT, 'Error: someone goofed')
                                END
                        END
                END;

END;

The error (only the final part of the .selecttrace is shown) proofs that the optimize function scans the triggers and halts the update even if the trigger is not part of the equation.                      
Here is the final part of the .selecttrace log
                            |   |           '-- 64
                            |   '-- AND fg.af=40000000.n DDL
                            |       |-- NOTNULL fg.af=40000000.n DDL
                            |       |   '-- DOT fg.af=40000000.n DDL
                            |       |       |-- ID "OLD"
                            |       |       '-- ID "A1_REF"
                            |       '-- NOT fg.af=40000000.n DDL
                            |           '-- EQ fg.af=40000000.n DDL
                            |               |-- DOT fg.af=40000000.n DDL
                            |               |   |-- ID "OLD"
                            |               |   '-- ID "A1_STATUS"
                            |               '-- 4
                            '-- RAISE abort('Error: someone goofed')
Error: near line 3: no such column: NEW.A2_STATUS