Repository: xerial/sqlite-jdbc (java)

Issue:
aarch64 native library is tried to be loaded when using a 32-bit JVM
**Describe the bug**
When running inside a 32-bit JVM on a aarch64 processor, sqlite-jdbc tries to load the aarch64 native library. This of course fails.

**To Reproduce**
```
package org.example;

import java.sql.DriverManager;

public class Main {
  public static void main(String[] args) throws Exception {
    System.out.println("Arch: " + System.getProperty("sun.arch.data.model"));

    try (var connection = DriverManager.getConnection("jdbc:sqlite:/tmp/test.db");
      var statement = connection.createStatement();
      var result = statement.executeQuery("SELECT RANDOM();")) {
      while (result.next()) {
        System.out.println("Output: " + result.getLong(1));
      }
    }
  }
}
```

**Expected behavior**
As the code is running inside a 32-bit JVM, the `arm`, `armv6` or `armv7` native library should be loaded.

**Logs**
Output:
```
Arch: 32
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
OpenJDK Client VM warning: You have loaded library /tmp/sqlite-3.46.0.0-51c6d6c2-c417-498d-9da6-fb79c3df716a-libsqlitejdbc.so which might have disabled stack guard. The VM will try to fix the stack guard now.
It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.
Exception in thread "main" java.sql.SQLException: Error opening connection
	at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:283)
	at org.sqlite.SQLiteConnection.<init>(SQLiteConnection.java:67)
	at org.sqlite.jdbc3.JDBC3Connection.<init>(JDBC3Connection.java:28)
	at org.sqlite.jdbc4.JDBC4Connection.<init>(JDBC4Connection.java:19)
	at org.sqlite.JDBC.createConnection(JDBC.java:106)
	at org.sqlite.JDBC.connect(JDBC.java:79)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:681)
	at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:252)
	at org.example.Main.main(Main.java:9)
Caused by: org.sqlite.NativeLibraryNotFoundException: No native library found for os.name=Linux, os.arch=aarch64, paths=[/org/sqlite/native/Linux/aarch64:/usr/java/packages/lib:/usr/lib/arm-linux-gnueabihf/jni:/lib/arm-linux-gnueabihf:/usr/lib/arm-linux-gnueabihf:/usr/lib/jni:/lib:/usr/lib]
	at org.sqlite.SQLiteJDBCLoader.loadSQLiteNativeLibrary(SQLiteJDBCLoader.java:361)
	at org.sqlite.SQLiteJDBCLoader.initialize(SQLiteJDBCLoader.java:75)
	at org.sqlite.core.NativeDB.load(NativeDB.java:69)
	at org.sqlite.SQLiteConnection.open(SQLiteConnection.java:280)
	... 8 more
```

**Environment (please complete the following information):**
 - OS: Raspberry Pi OS
 - CPU architecture: aarch64
 - sqlite-jdbc version: 3.46.0.0

**Additional context**

Pull request:
fix: never return arch as aarch64 when running in a 32-bit JVM
Fixes #1127 

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dbc4a1ed..3cc4cb6d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -206,7 +206,7 @@ jobs:
           echo "PROJECT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)" | tee -a $GITHUB_ENV
       - name: Cancel action for non SNAPSHOT push
         if: github.event_name == 'push' && !endsWith(env.PROJECT_VERSION, '-SNAPSHOT')
-        uses: andymckay/cancel-action@0.4
+        uses: andymckay/cancel-action@0.5
       # from that point, if inputs.perform_release is true we perform a release, else we deploy snapshot
       - name: Prepare release
         if: inputs.perform_release
diff --git a/pom.xml b/pom.xml
index e7642f46..5b832c03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <junit.version>5.10.2</junit.version>
-        <surefire.version>3.2.5</surefire.version>
+        <surefire.version>3.3.0</surefire.version>
         <archunit.version>1.3.0</archunit.version>
         <graalvm.version>24.0.1</graalvm.version>
         <java9.sourceDirectory>${project.basedir}/src/main/java9</java9.sourceDirectory>
diff --git a/src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java b/src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
index 6277ba8a..1a2229c7 100644
--- a/src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
+++ b/src/main/java/org/sqlite/jdbc3/JDBC3DatabaseMetaData.java
@@ -1078,7 +1078,10 @@ public abstract class JDBC3DatabaseMetaData extends CoreDatabaseMetaData {
                             colType = colType.substring(0, iStartOfDimension).trim();
                         }
 
-                        int colGenerated = "2".equals(colHidden) ? 1 : 0;
+                        int colGenerated = 0;
+                        if ("2".equals(colHidden) || "3".equals(colHidden)) {
+                            colGenerated = 1;
+                        }
 
                         sql.append("select ")
                                 .append(i + 1)
diff --git a/src/main/java/org/sqlite/util/OSInfo.java b/src/main/java/org/sqlite/util/OSInfo.java
index 9af366ee..24640ef6 100644
--- a/src/main/java/org/sqlite/util/OSInfo.java
+++ b/src/main/java/org/sqlite/util/OSInfo.java
@@ -191,8 +191,14 @@ public class OSInfo {
                 // Use armv5, soft-float ABI
                 return "arm";
             } else if (armType.startsWith("aarch64")) {
-                // Use arm64
-                return "aarch64";
+                boolean is32bitJVM = "32".equals(System.getProperty("sun.arch.data.model"));
+                if (is32bitJVM) {
+                    // An aarch64 architecture should support armv7
+                    return "armv7";
+                } else {
+                    // Use arm64
+                    return "aarch64";
+                }
             }
 
             // Java 1.8 introduces a system property to determine armel or armhf


Test patch:
diff --git a/src/test/java/org/sqlite/DBMetaDataTest.java b/src/test/java/org/sqlite/DBMetaDataTest.java
index 03c7a2b9..31af5813 100644
--- a/src/test/java/org/sqlite/DBMetaDataTest.java
+++ b/src/test/java/org/sqlite/DBMetaDataTest.java
@@ -18,6 +18,7 @@ import java.util.Map;
 import java.util.Properties;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.condition.DisabledInNativeImage;
@@ -490,6 +491,29 @@ public class DBMetaDataTest {
         assertThat(rs.next()).isFalse();
     }
 
+    @Test
+    @DisplayName(
+            "Issue #1132 - Generated columns with stored in SQLite are not marked as generated")
+    public void getColumnsIncludingGeneratedStored() throws SQLException {
+        stat.executeUpdate(
+                "create table foo("
+                        + "\n"
+                        + "  id integer primary key,"
+                        + "\n"
+                        + "  bar int not null generated always as (id + 1) stored"
+                        + "\n"
+                        + ");");
+
+        ResultSet rs = meta.getColumns(null, null, "foo", "%");
+        assertThat(rs.next()).isTrue();
+        assertThat(rs.getString(4)).as("first column is named 'id'").isEqualTo("id");
+        assertThat(rs.getString(24)).as("first column is generated").isEqualTo("NO");
+        assertThat(rs.next()).isTrue();
+        assertThat(rs.getString(4)).as("second column is named 'bar'").isEqualTo("bar");
+        assertThat(rs.getString(24)).as("second column is generated").isEqualTo("YES");
+        assertThat(rs.next()).isFalse();
+    }
+
     @Test
     public void getColumnsWithEscape() throws SQLException {
         stat.executeUpdate("create table wildcard(col1 integer, co_1 integer, 'co%1' integer)");