disqlite3database.pas

来自「DELPHI 访问SQLITE3 数据库的VCL控件」· PAS 代码 · 共 2,333 行 · 第 1/5 页

PAS
2,333
字号

  i := FStatements.Count - 1;
  while i >= 0 do
    begin
      Stmt := TDISQLite3Statement(FStatements[i]);
      Stmt.Active := False;
      Stmt.Database := nil;
      Dec(i);
    end;

  Connected := False;
  FStatements.Free;
  inherited;
end;

procedure TDISQLite3Database.AttachDatabase16(const ADatabaseName: WideString; AAlias: WideString = '');
var
  Stmt: TDISQLite3Statement;
begin
  CheckActive;
  CheckDatabaseName(ADatabaseName);

  if IsMemoryDatabaseName(ADatabaseName) and not WideFileExists(ADatabaseName) then
    raise EFOpenError.CreateFmt(SFOpenError, [WideExpandFileName(ADatabaseName)]);

  if AAlias = '' then
    AAlias := WideChangeFileExt(WideExtractFileName(ADatabaseName), '');

  Stmt := Prepare16('ATTACH ? AS ?');
  try
    Stmt.bind_Str16(1, ADatabaseName);
    Stmt.bind_Str16(2, AAlias);
    Stmt.Step;
  finally
    Stmt.Free;
  end;
end;

function TDISQLite3Database.Changes: Integer;
begin
  CheckActive;
  Result := sqlite3_changes(FHandle);
end;

function TDISQLite3Database.Check(const AErrorCode: Integer): Integer;
begin
  Result := AErrorCode;
  if Result <> SQLITE_OK then
    sqlite3_raise_exception(Result, FHandle);
end;

procedure TDISQLite3Database.CheckActive;
begin
  if not Assigned(FHandle) then
    DatabaseError(PResStringRec(@SDatabaseClosed), Self);
end;

procedure TDISQLite3Database.CheckDatabaseName(const ADatabaseName: WideString);
var
  l: Integer;
  p: PWideChar;
begin
  l := Length(ADatabaseName);
  if l > 0 then
    begin
      p := Pointer(ADatabaseName);
      repeat
        if p^ > WC_SPACE then Exit;
        Inc(p); Dec(l);
      until l = 0;
    end;
  DatabaseError(PResStringRec(@SDatabaseNameMissing), Self);
end;

procedure TDISQLite3Database.CheckInactive;
begin
  if Assigned(FHandle) then
    DatabaseError(PResStringRec(@SDatabaseOpen), Self);
end;

procedure TDISQLite3Database.Close;
begin
  SetConnected(False);
end;

procedure TDISQLite3Database.CloseStatements;
var
  i: Integer;
  Stmt: TDISQLite3Statement;
begin
  for i := 0 to FStatements.Count - 1 do
    begin
      Stmt := TDISQLite3Statement(FStatements[i]);
      Stmt.Active := False;
    end;
end;

procedure TDISQLite3Database.Commit;
begin
  if InTransaction then
    begin
      if FTransactionCount = 1 then
        begin
          CheckActive;
          Check(sqlite3_exec_with_callback(FHandle, 'COMMIT TRANSACTION;'));
        end;
      Dec(FTransactionCount);
    end;
end;

procedure TDISQLite3Database.DoAfterConnect;
begin
  if Assigned(FAfterConnect) then
    FAfterConnect(Self);
end;

procedure TDISQLite3Database.DoAfterCreateDatabase;
begin
  if Assigned(FAfterCreateDatabase) then
    FAfterCreateDatabase(Self);
end;

procedure TDISQLite3Database.DoAfterDisconnect;
begin
  if Assigned(FAfterDisconnect) then
    FAfterDisconnect(Self);
end;

procedure TDISQLite3Database.DoBeforeCreateDatabase;
begin
  if Assigned(FBeforeCreateDatabase) then
    FBeforeCreateDatabase(Self);
end;

procedure TDISQLite3Database.DoBeforeConnect;
begin
  if Assigned(FBeforeConnect) then
    FBeforeConnect(Self);
end;

procedure TDISQLite3Database.DoBeforeDisconnect;
begin
  if Assigned(FBeforeDisconnect) then
    FBeforeDisconnect(Self);
end;

procedure TDISQLite3Database.DoConnect;
var
  s8: AnsiString;
begin
  if not Assigned(FHandle) then
    begin
      CheckDatabaseName(FDatabaseName);

      if not IsMemoryDatabaseName(FDatabaseName) and not WideFileExists(FDatabaseName) then
        begin

          raise EFOpenError.CreateFmt(SFOpenError, [WideExpandFileName(FDatabaseName)]);
        end;

      s8 := sqlite3_encode_utf8(FDatabaseName);
      Check(sqlite3_open(PAnsiChar(s8), @FHandle));
      if FPassword <> '' then
        Check(sqlite3_key(FHandle, Pointer(FPassword), Length(FPassword)));
    end;
end;

procedure TDISQLite3Database.DoDisconnect;
var
  h: TDISQLite3StatementHandle;
begin
  if Assigned(FHandle) then
    begin
      CloseStatements;
      h := FHandle;
      FHandle := nil;
      Check(sqlite3_close(h));
    end;
end;

procedure TDISQLite3Database.DoInitDatabase;
begin
  if Assigned(FInitDatabase) then
    FInitDatabase(Self);
end;

function TDISQLite3Database.GetAutoVacuum: Boolean;
begin
  CheckActive;
  Check(sqlite3_get_auto_vacuum(FHandle, Result))
end;

procedure TDISQLite3Database.SetAutoVacuum(const AValue: Boolean);
begin
  CheckActive;
  Check(sqlite3_set_auto_vacuum(FHandle, AValue));
end;

function TDISQLite3Database.GetCacheSize: Integer;
begin
  CheckActive;
  Check(sqlite3_get_cache_size(FHandle, Result));
end;

procedure TDISQLite3Database.SetCacheSize(const AValue: Integer);
begin
  CheckActive;
  Check(sqlite3_pragma_set_cache_size(FHandle, AValue));
end;

procedure TDISQLite3Database.SetCaseSensitiveLike(const AValue: Boolean);
begin
  CheckActive;
  Check(sqlite3_pragma_set_case_sensitive_like(FHandle, AValue));
end;

function TDISQLite3Database.GetConnected: Boolean;
begin
  Result := Assigned(FHandle);
end;

function TDISQLite3Database.GetCountChanges: Boolean;
begin
  CheckActive;
  Check(sqlite3_pragma_get_count_changes(FHandle, Result))
end;

procedure TDISQLite3Database.SetCountChanges(const AValue: Boolean);
begin
  CheckActive;
  Check(sqlite3_pragma_set_count_changes(FHandle, AValue));
end;

function TDISQLite3Database.GetDefaultCacheSize: Integer;
begin
  CheckActive;
  Check(sqlite3_get_default_cache_size(FHandle, Result))
end;

procedure TDISQLite3Database.SetDefaultCacheSize(const AValue: Integer);
begin
  CheckActive;
  Check(sqlite3_set_default_cache_size(FHandle, AValue));
end;

function TDISQLite3Database.GetEmptyResultCallbacks: Boolean;
begin
  CheckActive;
  Check(sqlite3_get_empty_result_callbacks(FHandle, Result))
end;

procedure TDISQLite3Database.SetEmptyResultCallbacks(const Value: Boolean);
begin

end;

function TDISQLite3Database.GetEncoding: WideString;
{$IFDEF SQLITE_OMIT_UTF16}
var
  s8: AnsiString;
  {$ENDIF SQLITE_OMIT_UTF16}
begin
  CheckActive;
  {$IFDEF SQLITE_OMIT_UTF16}
  Check(sqlite3_pragma_get_encoding(FHandle, s8));
  Result := sqlite3_decode_utf8(s8);
  {$ELSE  SQLITE_OMIT_UTF16}
  Check(sqlite3_pragma_get_encoding16(FHandle, Result));
  {$ENDIF  SQLITE_OMIT_UTF16}
end;

procedure TDISQLite3Database.SetEncoding(const AValue: WideString);
begin
  CheckActive;
  {$IFDEF SQLITE_OMIT_UTF16}
  Check(sqlite3_set_encoding(FHandle, sqlite3_encode_utf8(AValue)));
  {$ELSE  SQLITE_OMIT_UTF16}
  Check(sqlite3_set_encoding16(FHandle, AValue));
  {$ENDIF  SQLITE_OMIT_UTF16}
end;

function TDISQLite3Database.GetInTransaction: Boolean;
begin
  Result := FTransactionCount > 0;
end;

function TDISQLite3Database.GetStatementClass: TDISQLite3StatementClass;
begin
  Result := TDISQLite3Statement;
end;

function TDISQLite3Database.GetSQLiteVersion: WideString;
begin
  Result := sqlite3_libversion;
end;

procedure TDISQLite3Database.CreateDatabase;
var
  s8: AnsiString;
begin
  CheckInactive;
  CheckDatabaseName(FDatabaseName);
  if WideFileExists(FDatabaseName) and not WideDeleteFile(FDatabaseName) then
    raise EFCreateError.CreateFmt(SFCreateError, [WideExpandFileName(FDatabaseName)]);

  DoBeforeConnect;
  DoBeforeCreateDatabase;

  s8 := sqlite3_encode_utf8(FDatabaseName);
  Check(sqlite3_open(PAnsiChar(s8), @FHandle));
  if FPassword <> '' then
    Check(sqlite3_key(FHandle, Pointer(FPassword), Length(FPassword)));

  DoInitDatabase;

  DoAfterCreateDatabase;
  DoAfterConnect;
end;

procedure TDISQLite3Database.Execute(const ASQL: AnsiString);
begin
  CheckActive;
  Check(sqlite3_exec_with_callback(FHandle, ASQL));
end;

procedure TDISQLite3Database.Execute16(const ASQL: WideString);
begin
  CheckActive;
  Check(sqlite3_exec_with_callback(FHandle, sqlite3_encode_utf8(ASQL)));
end;

function TDISQLite3Database.IntegrityCheck: Integer;
begin
  CheckActive;
  Result := sqlite3_integrity_check(FHandle);
end;

procedure TDISQLite3Database.Interrupt;
begin
  CheckActive;
  sqlite3_interrupt(FHandle);
end;

function TDISQLite3Database.IsMemoryDatabaseName(const ADatabaseName: WideString): Boolean;
begin
  Result := (Length(ADatabaseName) = 8) and
    (ADatabaseName[1] = ':') and
    ((ADatabaseName[2] = 'M') or (ADatabaseName[2] = 'm')) and
    ((ADatabaseName[3] = 'E') or (ADatabaseName[3] = 'e')) and
    ((ADatabaseName[4] = 'M') or (ADatabaseName[4] = 'm')) and
    ((ADatabaseName[5] = 'O') or (ADatabaseName[5] = 'o')) and
    ((ADatabaseName[6] = 'R') or (ADatabaseName[6] = 'r')) and
    ((ADatabaseName[7] = 'Y') or (ADatabaseName[7] = 'y')) and
    (ADatabaseName[8] = ':');
end;

function TDISQLite3Database.LastInsertRowID: Int64;
begin
  CheckActive;
  Result := sqlite3_last_insert_rowid(FHandle);
end;

procedure TDISQLite3Database.Loaded;
begin
  inherited;
  try
    if FStreamedConnected then
      SetConnected(True);
  except
    if csDesigning in ComponentState then
      {$IFDEF COMPILER_6_UP}
      if Assigned(Classes.ApplicationHandleException) then
        Classes.ApplicationHandleException(ExceptObject)
      else
        {$ENDIF}
        ShowException(ExceptObject, ExceptAddr)
    else
      raise;
  end;
end;

procedure TDISQLite3Database.Open;
begin
  SetConnected(True);
end;

function TDISQLite3Database.Prepare(const ASQL8: AnsiString): TDISQLite3Statement;
begin
  Result := GetStatementClass.Create;
  Result.Database := Self;
  Result.SQL8 := ASQL8;
  Result.Open;
end;

function TDISQLite3Database.Prepare16(const ASQL16: WideString): TDISQLite3Statement;
begin
  Result := GetStatementClass.Create;
  Result.Database := Self;
  Result.SQL16 := ASQL16;
  Result.Open;
end;

procedure TDISQLite3Database.RegisterStatement(const AStatement: TDISQLite3Statement);
begin
  if Assigned(AStatement) then
    FStatements.Add(AStatement);
end;

procedure TDISQLite3Database.ReKey(const ANewPassword: AnsiString);
begin
  CheckActive;
  Check(sqlite3_rekey(FHandle, Pointer(ANewPassword), Length(ANewPassword)));
  FPassword := ANewPassword;
end;

procedure TDISQLite3Database.Rollback;
begin
  if InTransaction then
    begin
      if FTransactionCount = 1 then
        begin
          CheckActive;
          Check(sqlite3_exec_with_callback(FHandle, 'ROLLBACK TRANSACTION;'));
        end;
      Dec(FTransactionCount);
    end;
end;

procedure TDISQLite3Database.SetConnected(const AValue: Boolean);
begin
  if (csReading in ComponentState) and AValue then
    FStreamedConnected := True
  else
    if AValue <> GetConnected then
      if AValue then
        begin
          DoBeforeConnect;
          DoConnect;
          DoInitDatabase;
          DoAfterConnect;
        end
      else
        begin
          DoBeforeDisconnect;
          DoDisconnect;
          DoAfterDisconnect;
        end;
end;

procedure TDISQLite3Database.SetDatabaseName(const AValue: WideString);
begin
  CheckInactive;
  FDatabaseName := AValue;
end;

procedure TDISQLite3Database.SetPassword(const AValue: AnsiString);
begin
  if Connected then
    begin
      Check(sqlite3_key(FHandle, Pointer(AValue), Length(AValue)));
    end;
  FPassword := AValue;
end;

procedure TDISQLite3D

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?