React native expo SQLite 中的 INTEGER 类型限制为 4 个字节?
INTEGER type in React native expo SQLite limited to 4 bytes?
当尝试插入一个等于 4 字节 - 1 位的有符号整数(即 2^31,即 2147483648)时,我得到一个整数溢出条件(即它被转换为 -2147483648)。
sqlite 文档声明 INTEGER 类型最多支持 8 字节有符号整数:https://www.sqlite.org/datatype3.html
此外,超过 8 个字节 - 1 位 - 1 的值会导致异常。所以这导致了它是一个 expo / react-native bug 的想法。这是 Expo / react-native / 其他的已知错误吗?我找不到 where ExponentSQLite
is coming from。另请注意,2147483648
远低于 javascript MAX_SAFE_INTEGER,因此可能在 android 代码中,参数被转换为 4 字节有符号整数。
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)
}
)
})
})
}
这将导致(为简洁起见进行了编辑):
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}]
杂注user_version -> 0
语法 schema_version -> 46
世博会版本 -> 31.0.2
* 编辑 1 *
我已经提交了一个错误,让我们看看响应是什么:https://github.com/expo/expo/issues/3000
这是一个错误。
已修复:https://github.com/expo/expo/pull/3005
当尝试插入一个等于 4 字节 - 1 位的有符号整数(即 2^31,即 2147483648)时,我得到一个整数溢出条件(即它被转换为 -2147483648)。
sqlite 文档声明 INTEGER 类型最多支持 8 字节有符号整数:https://www.sqlite.org/datatype3.html
此外,超过 8 个字节 - 1 位 - 1 的值会导致异常。所以这导致了它是一个 expo / react-native bug 的想法。这是 Expo / react-native / 其他的已知错误吗?我找不到 where ExponentSQLite
is coming from。另请注意,2147483648
远低于 javascript MAX_SAFE_INTEGER,因此可能在 android 代码中,参数被转换为 4 字节有符号整数。
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)
}
)
})
})
}
这将导致(为简洁起见进行了编辑):
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}]
杂注user_version -> 0 语法 schema_version -> 46 世博会版本 -> 31.0.2
* 编辑 1 *
我已经提交了一个错误,让我们看看响应是什么:https://github.com/expo/expo/issues/3000
这是一个错误。 已修复:https://github.com/expo/expo/pull/3005