Forgot Password,

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

You must login to ask a question.

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

databaseanswers.net Latest Questions

  • 1
Clara
Beginner

INTEGER type in React native expo SQLite limited to 4 bytes?

When trying to insert a signed integer equal to 4 bytes – 1 bit (i.e. 2^31 i.e. 2147483648) I get an integer overflow condition (i.e. it is converted to -2147483648).

The sqlite docs state the INTEGER type supports up to 8 byte signed integer: https://www.sqlite.org/datatype3.html
Additionally values above 8 bytes – 1 bit – 1 cause an exception. So this leads to the idea it’s an expo / react-native bug. Is this a known bug in Expo / react-native / something else? I couldn’t find where ExponentSQLite is coming from. Note also that 2147483648 is well below the javascript MAX_SAFE_INTEGER so perhaps in the android code the parameters are being converted into a 4 byte signed integer.

import { SQLite } from 'expo'

async function main() {
  const db = SQLite.openDatabase('mydb')

  await exec_sql({ db, sql: `DROP TABLE IF EXISTS table_name;` })
  await exec_sql({ db, sql: `CREATE TABLE table_name (id INTEGER PRIMARY KEY, created_at INTEGER NOT NULL);` })
  await exec_sql({ db, sql: `INSERT INTO table_name (created_at) VALUES (?);`, parameters: [Math.pow(2, (8 * 4) - 1) - 1] })
  await exec_sql({ db, sql: `INSERT INTO table_name (created_at) VALUES (?);`, parameters: [Math.pow(2, (8 * 4) - 1)] })

  await exec_sql({ db, sql: `INSERT INTO table_name (created_at) VALUES (9223372036854775000);`, parameters: [] })
  // set to 9223372036854775000 as javascript Number.MAX_SAFE_INTEGER means `Math.pow(2, (8 * 8) - 1) - 1`
  // is rounded higher to 9223372036854776000
  await exec_sql({ db, sql: `INSERT INTO table_name (created_at) VALUES (?);`, parameters: [9223372036854775000] })

// This will error with
  // Error in callNativeModules()
  // Over flow during conversion: 9223372036854776000 (rounding up due to javascript's Number.MAX_SAFE_INTEGER)
  // await exec_sql({ db, sql: `INSERT INTO table_name (created_at) VALUES (?);`, parameters: [Math.pow(2, (8 * 8) - 1)] })
  await exec_sql({ db, sql: `SELECT * FROM table_name;` })
}

main()

function exec_sql ({ db, sql, parameters = [] }) {
  return new Promise((resolve, reject) => {
    db.transaction(tx => {
      console.debug(`Executing ${sql} with parameters: ${parameters}`)
      tx.executeSql(sql, parameters,
        (_, result) => {
          console.debug(`Have result: ${JSON.stringify(result)}`)
          if (result && result.rows && result.rows._array) {
            resolve({ items: result.rows._array })
          } else {
            resolve()
          }
        },
        (_, err) => {
          console.error(`Error during executing sql: `, err)
          reject(err)
        }
      )
    })
  })
}

This will result in (edited for brevity):

Executing CREATE TABLE IF NOT EXISTS table_name (id INTEGER PRIMARY KEY, created_at INTEGER NOT NULL); with parameters: 
Executing INSERT INTO table_name (created_at) VALUES (?); with parameters: 2147483647
Executing INSERT INTO table_name (created_at) VALUES (?); with parameters: 2147483648
Executing INSERT INTO table_name (created_at) VALUES (9223372036854775000); with parameters: 
Executing INSERT INTO table_name (created_at) VALUES (?); with parameters: 9223372036854775000
Executing SELECT * FROM table_name; with parameters: 
Have result: [{"id": 1, "created_at": 2147483647}, {"id": 2, "created_at": -2147483648}, {"id": 3, "created_at": -808},{"id": 4, "created_at": -1024}]

PRAGMA user_version -> 0
PRAGMA schema_version -> 46
expo version -> 31.0.2

* Edit 1 *

I have filed a bug, let’s see what the response is: https://github.com/expo/expo/issues/3000

Related Questions

Leave an answer

You must login to add an answer.