Delphi FireDAC 下的 Sqlite(十) 使用 R-Tree 搜索

R-Tree 主要用于三维空间的搜索, 据说这种搜索算法非常之快, 哪怕百万条记录也是眨眼间的事! SQLite 支持 1-5 维, FireDAC 也提供了 TFDSQLiteRTree 控件以方便定义回调函数. 为了简单, 我用二维表进行了成功的测试. 建立 R-Tree 表(索引)时需要使用特定语法, 譬如: FDConnection1.ExecSQL('CREATE VIRTUAL TABLE MyRTreeTable USING rtree(Id, minX, maxX, minY, maxY)'); //必须是 VIRTUAL 表 //USING rtree, 是必须的; 也可以是 USING rtree_i32 //Id, minX, maxX, minY, maxY; 这是 ID 与二维空间的数据, 这里无需指定参数类型; 因为参数类型是内定的: Id 是 64 位无符号整形(且是主键), 后面的数据是 32 位浮点 //如果使用 rtree_i32 定义, 后面的数据则都是 32 为整形; 另外如果指定了 SQLITE_RTREE_INT_ONLY 参数, 无论怎么定义, 内部都用整形计算.

为此我做了两个例子, 第一个例子先没有使用 TFDSQLiteRTree(也就是没用回调). 本例除了使用 TFDConnection, TFDPhysSQLiteDriverLink, TFDGUIxWaitCursor, TDataSource, TDBGrid 外, 还有一个 TPaintBox, 用于绘图和点击测试, 用到它的 OnPaint 和 OnMouseUp 事件. 可把下面代码直接贴在空白窗体上, 以快速完成窗体设计: object PaintBox1: TPaintBox Left = 408 Top = 16 Width = 617 Height = 473 OnMouseUp = PaintBox1MouseUp OnPaint = PaintBox1Paint end object DBGrid1: TDBGrid Left = 0 Top = 0 Width = 393 Height = 503 Align = alLeft DataSource = DataSource1 TabOrder = 0 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -11 TitleFont.Name = 'Tahoma' TitleFont.Style = [] end object FDConnection1: TFDConnection Left = 34 Top = 24 end object FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink Left = 143 Top = 24 end object FDGUIxWaitCursor1: TFDGUIxWaitCursor Provider = 'Forms' Left = 260 Top = 24 end object FDQuery1: TFDQuery Connection = FDConnection1 Left = 32 Top = 88 end object DataSource1: TDataSource DataSet = FDQuery1 Left = 132 Top = 88 end object FDSQLiteRTree1: TFDSQLiteRTree DriverLink = FDPhysSQLiteDriverLink1 Left = 256 Top = 96 end

代码:

var VBitmap: TBitmap; //当做内存画布procedure TForm1.FormCreate(Sender: TObject);
const
  W = 50; H = 30;
var
  i,x,y,x1,x2,y1,y2: Integer;
begin
  FDConnection1.Params.Add('DriverID=SQLite');
  FDConnection1.ExecSQL('CREATE VIRTUAL TABLE MyRTreeTable USING rtree(Id, minX, maxX, minY, maxY)'); //建表
  FDConnection1.Connected := True;

  {为数据库添加模拟数据}
  FDConnection1.StartTransaction;
  tryfor i := 0to100dobegin  x := Random(PaintBox1.Width);
      y := Random(PaintBox1.Height);
      FDConnection1.ExecSQL('INSERT INTO MyRTreeTable VALUES(:id, :x1, :x2, :y1, :y2)', [i, x, x+W, y, y+H]);end;
    FDConnection1.Commit;
  exceptFDConnection1.Rollback;
  end;

  {呈现}
  FDQuery1.Open('SELECT * FROM MyRTreeTable ORDER BY Id');
  for i := 0to DBGrid1.Columns.Count - 1do DBGrid1.Columns[i].Width := 66; //默认的网格列太宽了, 处理一下

  {根据刚刚添加的数据绘制一张内存图片}
  VBitmap := TBitmap.Create;
  VBitmap.SetSize(PaintBox1.Width, PaintBox1.Height);
  VBitmap.Canvas.Brush.Color := clWhite;
  VBitmap.Canvas.FillRect(Rect(0, 0, VBitmap.Width, VBitmap.Height));

  FDQuery1.First;
  whilenot FDQuery1.Eof do
  beginx1 := FDQuery1.Fields[1].AsInteger;
    x2 := FDQuery1.Fields[2].AsInteger;
    y1 := FDQuery1.Fields[3].AsInteger;
    y2 := FDQuery1.Fields[4].AsInteger;
    VBitmap.Canvas.Brush.Color := Random($EEEEEE);
    VBitmap.Canvas.FillRect(Rect(x1, y1, x2, y2));
    FDQuery1.Next;
  end;
end;

{在 OnMouseUp 事件中执行了 R-Tree 搜索}procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  i: Integer;
begin
  Caption := Format('%d, %d', [X, Y]);
  FDQuery1.Open('SELECT * FROM MyRTreeTable WHERE minX <= :X AND maxX > :X AND minY <= :Y AND maxY > :Y', [X,Y]); //[X,X,Y,Y] ?
  for i := 0to DBGrid1.Columns.Count - 1do DBGrid1.Columns[i].Width := 66; //这行只为缩小列宽end;

{呈现前面绘制的内存图片}procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  PaintBox1.Canvas.Draw(0, 0, VBitmap);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  VBitmap.Free;
end;

测试效果图:

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索object
, width
, end
left
firedac sqlite、delphi firedac、delphi firedac 教程、delphi firedac mssql、delphi firedac 用法,以便于您获取更多的相关知识。

时间: 2024-09-10 23:19:40

Delphi FireDAC 下的 Sqlite(十) 使用 R-Tree 搜索的相关文章

Delphi FireDAC 下的 Sqlite(十二) 备忘录

该话题的继续延伸主要就是 SQL 的语法了, 草草收场的原因是现在的脑筋已经进入了 IntraWeb 的世界. 相关备忘会随时补充在下面: //连接多个数据库的参考代码: FDConnection1.ExecSQL('ATTACH ''c:hr.sdb'' AS hr'); FDConnection1.ExecSQL('ATTACH ''c:cust.sdb'' AS cust'); FDQuery1.Open('select * from "Orders" o ' + 'left j

Delphi FireDAC 下的 Sqlite(九) 关于排序

SQLite 内部是按二进制排序, 可以支持 ANSI; FrieDAC 通过 TFDSQLiteCollation 支持了 Unicode 排序, 并可通过其 OnCompare 事件自定义排序. 下面的例子, 测试了这两种排序的不同. 可把下面代码直接贴在空白窗体上, 以快速完成窗体设计: object DBGrid1: TDBGrid Left = 0 Top = 0 Width = 297 Height = 199 Align = alLeft DataSource = DataSour

Delphi FireDAC 下的 Sqlite(八) 自定义函数

Sqlite 本身没有这个功能, FireDAC 通过 TFDSQLiteFunction 增加了该功能; 尽管通过某些 SQL 语句或通过视图也可以达到类似效果, 但函数会更灵活些. 本例先建了一个成绩表, 然后通过两个 TFDSQLiteFunction 实现了 "总分" 与 "平均分" 的计算. 你可以复制下面文本框中的内容, 然后直接往窗体上贴, 以快速完成窗体设计: object DBGrid1: TDBGrid Left = 8 Top = 88 Wid

Delphi FireDAC 下的 Sqlite(二) 第一个例子

为了方便测试, 我把官方提供的 C:\Users\Public\Documents\Embarcadero\Studio\14.0\Samples\data\FDDemo.sdb 复制了一份到 C:\Temp\FDDemo.sdb. {新建一个 VCL Forms Application, 然后添加如下控件(建议按 Ctrl + . 后用键盘输入添加):} TFDPhysSQLiteDriverLink // 用于驱动自动连接; 不同数据库各对应一个: TFDPhys****DriverLink

Delphi FireDAC 下的 Sqlite(一) 前言

很长时间没静下心来写博客了, 现在回来, 是 Delphi 不断地进步让我感动.振奋. Delphi XE5 并入了 FireDAC, 第一印象非常好, 恐怕 dbExpress 等等都要靠边站了. 让我最高兴地是 FireDAC 对 Sqlite 的支持! 优秀的 Sqlite 早就有很多 Delphi 的包装(http://www.sqlite.org/cvstrac/wiki?p=SqliteWrappers, 从 https://code.google.com/ 等还能搜到更多). 有静

Delphi FireDAC 下的 Sqlite(十一) 批量提交 SQL 命令的测试

可把下面代码直接贴在空白窗体上, 以快速完成窗体设计: object DBGrid1: TDBGrid Left = 0 Top = 0 Width = 265 Height = 338 Align = alLeft DataSource = DataSource1 TabOrder = 0 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -11 TitleFont.Nam

Delphi FireDAC 下的 Sqlite(七) 备份、优化和事务(Transaction)

用 TFDSQLiteBackup 控件, 两三行代码即可完成 Sqlite 数据库的备份. procedure TForm1.Button1Click(Sender: TObject); begin {先初始化目标} FDConnection1.DriverName := 'SQLite'; FDConnection1.Params.Add('Database=C:\Temp\FDDemo_Back.sdb'); //如果不指定这个路径, 就是备份到内存 FDConnection1.Open(

Delphi FireDAC 下的 Sqlite(六) 加密

主要就是设置 TFDConnection 的两个链接参数: Password, NewPassword, 非常简单. const dbPath = 'C:\Temp\SQLiteTest.sdb'; {建立加密数据库, 密码是 mm123}procedure TForm1.FormCreate(Sender: TObject); const strTable = 'CREATE TABLE MyTable(Id integer, Name string(10), Age byte)'; //Id

Delphi FireDAC 下的 Sqlite(五) 数据的插入、更新和删除

先在空白窗体上添加: TFDConnection.TFDPhysSQLiteDriverLink.TFDGUIxWaitCursor.TFDQuery.TDataSource.TDBGrid(并在设计时关联好). 你也可以复制下面文本框中的内容, 然后直接往窗体上贴, 以快速完成以上的添加过程: object DBGrid1: TDBGrid Left = 16 Top = 88 Width = 361 Height = 329 DataSource = DataSource1 TabOrder