SQLite 参数错误或其他 API 误用

SQLite bad parameter or other API misuse

错误

[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: SqliteException(14): bad parameter or other API misuse, bad parameter or other API misuse (code 21)
#0      new DatabaseImpl.open (package:sqlite3/src/impl/database.dart:53:7)
#1      Sqlite3.open (package:sqlite3/src/api/sqlite3.dart:51:25)
#2      _VmDelegate.open (package:moor/src/ffi/vm_database.dart:126:21)
#3      DelegatedDatabase.ensureOpen.<anonymous closure> (package:moor/src/runtime/executor/helpers/engines.dart:255:22)
<asynchronous suspension>
#4      BasicLock.synchronized (package:synchronized/src/basic_lock.dart:34:18)
<asynchronous suspension>
#5      QueryEngine.doWhenOpened.<anonymous closure> (package:moor/src/runtime/api/query_engine.dart)
<asynchronous suspension>

数据库路径

C:\Users\fosan\Documents\db.sqlite

环境

扑博士

[√] Flutter (Channel dev, 1.26.0-1.0.pre, on Microsoft Windows [Version 10.0.19613.1005],
    locale pt-BR)
    • Flutter version 1.26.0-1.0.pre at C:\tools\flutter
    • Framework revision 63062a6443 (8 days ago), 2020-12-13 23:19:13 +0800
    • Engine revision 4797b06652
    • Dart version 2.12.0 (build 2.12.0-141.0.dev)

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at C:\Users\fosan\AppData\Local\Android\sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.8.3)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio19\Community
    • Visual Studio Community 2019 version 16.8.30804.86
    • Windows 10 SDK version 10.0.18362.0

[√] Android Studio (version 4.1.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] Connected device (1 available)
    • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version
      10.0.19613.1005]

• No issues found!

代码

import 'dart:ffi';
import 'dart:io';

...
import 'package:flutter/material.dart';
import 'package:sqlite3/open.dart';
import 'package:window_size/window_size.dart';

void main() {
  open.overrideFor(OperatingSystem.windows, _openOnWindows);
  ...
  runApp(const App(appName: appName));
}

DynamicLibrary _openOnWindows() {
  final sqlite3LibraryPath = join(Platform.script.toFilePath(), 'sqlite3.dll');
  return DynamicLibrary.open(sqlite3LibraryPath);
}

import 'dart:io';

import 'package:moor/ffi.dart';
import 'package:moor/moor.dart';
import 'package:path/path.dart' as p;
import 'package:path_provider/path_provider.dart';

part 'local_database.g.dart';

@UseMoor(tables: [ClientsTable])
class LocalDatabase extends _$LocalDatabase {
  LocalDatabase() : super(_openConnection());

  @override
  int get schemaVersion => 1;

  Future<int> addClient(ClientRow newClient) =>
      into(clientsTable).insert(newClient);

  Stream<List<ClientRow>> get watchAllClients => select(clientsTable).watch();

  Future<int> deleteClient(int id) =>
      (delete(clientsTable)..where((tbl) => tbl.id.equals(id))).go();
}

LazyDatabase _openConnection() {
  return LazyDatabase(() async {
    final dbFolder = await getApplicationDocumentsDirectory();
    final file = File(p.join(dbFolder.path, 'db.sqlite'));
    return VmDatabase(file);
  });
}

@DataClassName("ClientRow")
class ClientsTable extends Table {
  IntColumn get id => integer().autoIncrement()();

  TextColumn get name => text()();

  TextColumn get phone => text()();

  TextColumn get street => text()();

  TextColumn get number => text()();

  TextColumn get city => text()();

  TextColumn get neighborhood => text()();

  TextColumn get uf => text()();

  TextColumn get reference => text()();
}

应该使用 sqflite: ^1.3.0 而不是 sqlite3_flutter_libs: ^0.3.0

我的问题有两件事,都与写权限有关。第一个问题是我的应用程序项目在 Desktop 文件夹下,第二个问题是 await getApplicationDocumentsDirectory(); 返回了 Documents 文件夹。

对我来说解决的是在项目的同一文件夹中创建数据库并将项目文件夹本身移动到 C:\StudioProjects

当 SQLite 抛出错误,然后您尝试再次使用相同的准备语句,而不重建它时,SQLite 将产生 General error: 21 bad parameter or other API misuse 错误。您必须从一开始就捕获并重建准备好的语句,以避免后续调用现在无效的准备语句堆栈。 (顺便说一句,这不是段错误,这一事实值得 SQLite 开发人员鼓掌。他们在这里用一种很容易出现段错误的语言做了一些很棒的工作。)应该注意的是,这在写语句(INSERT、UPDATE、DELETE 等)中会更频繁地发生,而只读语句 (SELECT) 不太可能导致出现此错误。所以先看看你写的语句。

现在任何事情都可能导致错误消息的发生。我的 Googleing 显示,许多库都没有正确处理文件夹权限或在运行时(实际执行查询时)检查它。

当我一个接一个地执行多个 INSERT 语句时,我 运行 首先进入这个问题,但是第一个语句由于 UNIQUE 约束导致后续语句给了我 General error: 21 bad parameter or other API misuse.