однопользовательская реляционная СУБД, причем база
TjanSQL - однопользовательская реляционная СУБД, причем база данных представлена в виде плоских текстовых файлов, где разделителем между столбцами служит точка с запятой. TjanSQL поддерживает следующие команды языка SQL: SELECT (с возможностью объединения таблиц, вычислений и псевдонимов полей), UPDATE, INSERT (значения полей и подзапросы), DELETE, CREATE TABLE, DROP TABLE, ALTER TABLE, CONNECT TO, COMMIT, WHERE, IN (список или подзапрос), GROUP BY, HAVING, ORDER BY (ASC, DESC), а также вложенные подзапросы, статистические функции (COUNT, SUM, AVG, MAX, MIN), операторы (+, -, *, /, and, or, >, >=, <, <=, =, <>, Like), функции UPPER, LOWER, TRIM, LEFT, MID, RIGHT, LEN, FIX, SOUNDEX, SQR, SQRT и др.
Все это я узнал из аннотации к архиву. Начало интригующее… После распаковки zip-архива объемом 425 Кб обнаружилось еще несколько интересных особенностей. В первую очередь, порадовало наличие в образовавшемся каталоге таких поддиректорий, как db, demosource и sql, а также файла janSQL.hlp. Появилась надежда, что не придется исследовать исходные коды компонентов для определения набора и назначения их свойств и методов.
Увы, она не оправдалась. К сожалению, более тесное знакомство с TjanSQL вызвало больше отрицательных эмоций, нежели положительных. Первым разочарованием стало отсутствие законченных компонент, которые можно было бы использовать по аналогии с Data Access. В частности, для подключения к текстовой базе данных необходимо в режиме runtime создавать (и ликвидировать) объект класса TjanSQL, используя примерно такой код:
var janSQLDemoF: TjanSQLDemoF; appldir:string; thefile:string; db:TjanSQL; procedure TjanSQLDemoF.FormCreate (Sender: TObject); begin db:=TjanSQL.create; end; procedure TjanSQLDemoF.FormDestroy (Sender: TObject); begin db.free; end;
Таким образом, в TjanSQL отсутствует одно из основных, на мой взгляд, преимуществ компонентного Delphi-программирования: для доступа к базе данных необходимо прописывать всю настроечную информацию в тексте программы. Конечно, это тоже своего рода design-time, но помилуйте - что стоило разработать невизуальный компонент, аналог какого-нибудь TDataBase или TAdoConnection?
Второй минус - демонстрационный проект, поставляемый вместе с классами Tjan* (язык не поворачивается назвать их компонентами), просто так не работает. Я впервые столкнулся с ситуацией, когда демо-проект не скомпилировался при попытке запуска. Делать нечего - начал разбираться. Как выяснилось, проблема устранима - достаточно закомментировать те строки, которые вызывают "раздражение" у модулей проекта Delphi, а также изменить пути к модулям с описанием классов доступа к базе данных - они почему-то "зашиты" в проект с точностью до имени каталога и буквы диска. Так я узнал, что у разработчика на компьютере как минимум три логических диска (пути начинались с Е:\…).
В файле помощи тоже ряд пробелов. Зачем было помещать в оглавление ссылки на страницы, содержащие только заголовок? Впрочем, возможно, я придираюсь...
Но главным, на мой взгляд, недостатком TjanSQL является невозможность непосредственной связи между TJanSQL и компонентами Data Aware, как это делается, в частности, с TQuery, TDataSource и TDBGrid. В демонстрационном проекте для отображения информации, получаемой с помощью SQL-запросов, используется обычный TStringGrid. В следующем примере приводится та часть кода, которая относится к обработке и визуализации результатов запроса:
unit janSQLDemoU; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, FileCtrl,Grids, ExtCtrls, ComCtrls, ToolWin, Menus, janSQL, StdCtrls, Buttons;
type TjanSQLDemoF = class (TForm) MainMenu1: TMainMenu; ToolBar1: TToolBar; StatusBar1: TStatusBar; Panel1: TPanel; Splitter1: TSplitter; viewgrid: TStringGrid; sqlmemo: TMemo; cmdExecute: TSpeedButton; edmessage: TEdit; Insert1: TMenuItem; ApplicationFolder1: TMenuItem; SelectedFolder1: TMenuItem; Help1: TMenuItem; Contents1: TMenuItem; procedure cmdExecuteClick (Sender: TObject);
private procedure showresults (resultset:integer); Private declarations
public Public declarations end;
var janSQLDemoF: TjanSQLDemoF; appldir:string; db:TjanSQL;
implementation {$R *.DFM}
procedure TjanSQLDemoF.cmdExecuteClick (Sender: TObject); var sqlresult:integer; sqltext:string; begin sqltext:=sqlmemo.text; sqlresult:=db.SQLDirect (sqltext); if sqlresult<>0 then begin edmessage.Text:='OK'; sqlmemo.text:=''; if sqlresult>0 then begin showresults (sqlresult); db.ReleaseRecordset (sqlresult); end; end else edmessage.Text:=db.Error; sqlmemo.SetFocus; end;
procedure TjanSQLDemoF.showresults (resultset:integer); var r1:integer; i,arow,acol,c,rc,fc:integer; begin r1:=resultset; rc:=db.RecordSets [r1].recordcount; if rc=0 then exit; fc:=db.RecordSets [r1].fieldcount; if fc=0 then exit; viewgrid.RowCount:=rc+1; viewgrid.ColCount:=fc; for i:=0 to fc-1 do viewgrid.Cells [i,0]:=db.recordsets [r1].FieldNames [i]; for arow:=0 to rc-1 do for acol:=0 to fc-1 do viewgrid.cells [acol,arow+1]:=db.RecordSets [r1].records [arow].fields [acol]; end;
Только не подумайте, что я собрался обругать всё и вся. Я всего лишь считаю необходимым предупредить вас о подводных камнях, на которые вы можете напороться при использовании TJanSQL.
Вообще TJanSQL - очень полезный набор разработок. Но только если рассматривать его не как конечный продукт, а как базу для написания собственных BDE-независимых компонентов для работы с плоскими текстовыми файлами, организованными в реляционные базы данных.
Действительно, возможность обращения к структурированным текстовым файлам с использованием SQL - ценное преимущество. Можно совместить помещенные в TJanSQL функции, например, со стандартными компонентами Data Access или воспользоваться другими разработками - компонентами для организации временных таблиц в памяти. Это обеспечит доступ к плоским текстовым файлам на уровне SQL-запросов - сервис, аналогичный стандартным Delphi-компонентам, но без зависимости от такого монстра, как Borland Database Engine. Стоит ли говорить, какие перспективы тогда откроются?
Содержание раздела