KnigaRead.com/

W Cat - S. D. F.

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн W Cat, "S. D. F." бесплатно, без регистрации.
Перейти на страницу:

* А почему ты изменил 170 строку.

- Искл. состояние может возникнуть не только из-за dll, но и в случае если база будет не родная (не совпадает пароль и др.) т.е. это место надо переписать более тщательно, сделаем это позже.

* Нет ничего более постоянного …

- Согласен, давай изменим строку 160

160           except // в дальнейшем обработать 1. отсутствие dll. 2. несовпадение пароля 3. другие случаи

- Теперь пришла пора для вкусненького.

* Погоди, сбегаю за кетчупом.

- Боюсь, ни клаве ни монитору кетчуп не понравится.

- Открою тебе великую тайну:

- Когда мы создали пустую базу. База там уже есть.

* Я что-то подобное подозревал, файл то не очень маленький.

- Да, в этом файле есть служебная база в которой будут хранится сведения о нашей базе.

* База о базе. Логично. Ведь логичное же, что директор завода Жигулей ездит на Мерседесе.

- Переписываем ShowTables:

-

procedure ShowTables(fn:string);

begin

 FMain.Caption := fn;

 with FMain.ListBox1 do

  begin

   Clear;

    PrintList('select DISTINCT R.RDB$RELATION_NAME '+

              'from RDB$RELATION_FIELDS R '+

    'where R.RDB$SYSTEM_FLAG = 0 order by R.RDB$RELATION_NAME');

  end;

end;

* Опять нет нумерации, значит это тоже временно.

- Совершенно точно. А теперь функция PrintList:

010 function PrintList( iSQL:string):boolean;

020 begin

030 with DataModule2.IBSQL1 do

040  begin

050     result := false;

060     Close;

070     SQL.Clear;

080     SQL.Add(iSQL);

090     ExecQuery;

100     if RecordCount = 0 then

110       begin

120         FMain.ListBox1.Items.Add('Empty');

130         result := true;

140         exit;

150       end;

160     while not EOF do

170      begin

180       FMain.ListBox1.Items.Add( trim(Fields[0].AsString));

190       Next;

200      end; // while

210  end;

220 end;

- PrintList выполняет (стр. 90) наш первый SQL запрос (стр. 80). В случае, когда осмысленного ответа нет (стр. 100-150) выдается надпись - 'Empty' т.е. базы нет, а иначе (стр. 160-200) выдаем список таблиц в нашей базе.

* А что за страшную строку получает PrintList получает как параметр.

- Это тот самый запрос и есть. Пока разбирать его не будем.

- * -

(уточнение, “- * -“ равняется банке пива)

- Ну как, чего ты такой…

* Опять, не работает.

- Привыкай к тяготам лишениям нашей службы…

- Ну что там у нас

* Operation cancelled at user's request

- Н-да, и что характерно, каждый раз на этом месте…

- Так, у компонента IBDatabase1 измени свойство LoginPrompt на False. И будет тебе счастье.

- * -

* Ну, что, сразу нельзя было сказать?

- Забыл, бывает…

- Как, заработало?

* Да, но гора родила мышь. Ввели много дополнительных слов, а результат тот же.

- Ничего, скоро мышка превратится в кошку, затем в собачку а там и до крокодила недалеко.

* Не п*ди, что будем делать дальше?

- Дальше?

Готовимся выполнять SQL запросы.


- Для начала, что попроще.

- На закладке History помести TMemo – во всю ее ширину и высоту, да, назови это дело His.

- А на закладке SQL надо расположить тоже TMemo (у меня оно названо Memo1) и для начала пару кнопок “Run SQL” и “Clear SQL”.

- Теперь делаем процедуры кнопок:

procedure TFMain.Button1Click(Sender: TObject);

begin  // кнопка run SQL

 RunSQL( MakeSQL);

end;

* Опять временно?

- Ну, не хочу тебя сразу пугать, все по очереди.

- Обрати внимание на комментарий к слову begin – рекомендую так подписывать процедуру, если название ее мало информативно.

* А вторая кнопка?

- Ну, даже неудобно…

procedure TFMain.Button2Click(Sender: TObject);

begin

 Memo1.Clear;

end;

* Да, проще некуда. Так теперь по очереди RunSQL( MakeSQL);

- Недавно переделал, довольно много повкалывал с этими 30 строками…

010 function RunSQL( S:string):boolean;

020 var

030  b : boolean; // отслеживание ошибки

040  Mistake : string; // сообщение ошибки

050 begin

060 with DataModule2.IBSQL1 do

070  begin

080     Close;

090     SQL.Clear;

100     SQL.Add(S);

110    try

120     ExecQuery;  // попытка выполнения запроса

130     b := true;  // ошибки нет

140    except    // Обработка ошибки

150      on E: Exception do

160         begin

170           b := false; // к сожалению, ошибка

180           Mistake := E.ClassName+' raised exception: '+E.Message;

190         end;

200    end; // try

210  end;  // with DataModule2

220   result := not b;

230  if b

240   then

250    begin // запрос выполнен

260      Hi.Lines.Add('ok');

270      Memo1.Clear; // и переход на закладку History

280      if DataModule2.IBSQL1.SQLType = SQLSelect

290       then PrintSELECT(S)  // распечатка результата запроса SELECT

300       else PageControl1.ActivePageIndex := 3;

310    end

320   else

330    begin // была ошибка

340     ShowMessage(Mistake); // сообщение об ошибке

350     Hi.Lines.Add('Error');

360     Hi.Lines.Add(Mistake); // запись в историю

370    end;

380  Hi.Lines.Add('------------');

390 end;

- Самое интересное происходит, когда запрос НЕ выполняется.

* Прочитал, все понятно, и над чем тут было биться?

- Все понятно? Отлично, объясни тогда строки 280, 290.

* Так, интересно. Определяется тип запроса и если это SELECT. Нечестно, ты еще ничего не сказал о PrintSELECT.

- Давай, это исправим:

010 procedure PrintSELECT(S:string);

020 var

030  i : integer;

040  a : string;

050  LHTML : TStringList;

060 begin

070  LHTML := TStringList.Create;

080   HTMLHead(LHTML);

090   LHTML.Add('<center>

'+ s + '

');

100 with DataModule2.IBSQL1 do

110 if RecordCount > 0 then

120   BEGIN

130    LHTML.Add('<h2>'+UniqueRelationName+'</h2>');

140    LHTML.Add('<center><table cellspacing=0 cellpadding=0 ><tr>');

150    S := ''; // формирование заголовка таблицы

160       for i := 0 to Current.Count-1 do

170           S := S + '<th>'+ Fields[i].Name +'</th>';

180     S := S + '</tr>'; // конец заголовка таблицы

190    LHTML.Add(S); // печать заголовка таблицы

200     while not EOF do

210      begin

220       S := '<tr>';   //

230       for i := 0 to Current.Count-1 do

240         begin // формирование строки данных

250          a := Fields[i].AsString;

260          if a = '' then a := ' - ';

270          S := S + '<td>'+a+'</td>';

280         end; // for

290       Next;

300       S := S + '</tr>';

310      LHTML.Add(S);

320      end; // while

330   LHTML.Add('</table></center>');

340  END

350  ELSE

360  LHTML.Add('<h3> EMPTY</h3>');

370  LHTML.Add('</body>');

380  LHTML.SaveToFile(Path+'~.htm');

390    Web.Navigate(Path+'~.htm');

400    PageControl1.ActivePageIndex := 2;

410   LHTML.Free;

420 end;

* Не маленький кусочек.

- Но очень важный кусочек, пожалуй, это сердце программы. Я его многократно переписывал, теперь стыдно показать ранние версии, а сейчас я горжусь написанным. Только, некомпетентные люди считают труд программиста скучным, безэмоциональным, нет эмоции, под внешним спокойствием, бушуют…

* Да ладно, расхвастался, к делу. В начале готовится заголовок HTML.

- Ну это просто:

procedure HTMLHead(LHTML : TStringList);

begin

  LHTML.add('<html><head>');

  LHTML.add('<meta http-equiv=<Content-Type< content=<text/html; charset=windows-1251<>');

  LHTML.add('<style>');

 LHTML.add('table {border:1px solid #c3c3c3; border-collapse:collapse;');

 LHTML.add(' text-align: center; width:90%;}');

 LHTML.add('table th {background-color:#e5eecc; border:1px solid #c3c3c3;');

 LHTML.add('padding:3px; vertical-align:top; }');

 LHTML.add('table td {border:1px solid #c3c3c3; padding:3px; vertical-align:top;');

 LHTML.add('</style></head><body>');

end;

- Тут, я ничего объяснять не буду HTML сегодня не наша тема.

- В цикле стр 200 – 320 выдается результат предшествующего запроса. Остальное все просто.

* Опять, таки не вижу, чему тут гордится.

- Мартышка, к старости, слаба глазами, стала? У меня есть предложение, после того как мы закончим разговор, отложи этот файл в далекую папку, и через пол года, напиши такую же программу самостоятельно, пользуясь справочниками, интернетом, но не этим текстом. Вот тогда, посмотрим.

* Хорошо! Спорим, что я напишу лучше!

- Вполне возможно. Я буду только рад. Выиграет только вселенский разум.

* Ладно, успокоились, что у нас еще есть неясного.

* А, что такое MakeSQL – по смыслу делается строка запроса?

- Да, это очень простая функция, и возможно это надо еще упростить…

010 function MakeSQL:string;

020 var

030  i : integer;

040 begin

050  result := '';

060  with FMain.Memo1 do

070  for i := 0 to Lines.Count - 1 do

080   if trim(Lines[i]) <> '' then

090    begin

100    FMain.His.Lines.Add(Lines[i]);

110   result := result + Lines[i] + ' ';

120  end;

130 result := trim(result);

140 end;

- Все, что находится в Memo1 записывается в одну строку(стр. 110) и одновременно сохраняется в истории(стр. 100).

* Так значит мы можем теперь выполнять SQL запросы?

- И да, и нет.

* ??

- Выполнять запросы можем, но не всегда увидим результат. Ну, еще не все готово.

* Так давай! Беги, покупай, эти тр-ан-зис-то-ры!

- Не спеши. Выполним, те SQL, что запланированы.

- Но сначала еще одна мелочь. Сделай обработчик для кнопки Show DB это на самой первой закладке.

procedure TFMain.Button3Click(Sender: TObject);

begin // Show DB

 ShowTables;

end;

???????

Первые запросы


- Ну, что, давай попробуем.

- Открой или сделай новую базу и выполни следующий запрос:

CREATE TABLE Salespeople

( snum integer,

sname char (10),

city char (10),

comm decimal );

* Говорит что все OK.

- Перейди на первую закладку и нажми кнопку Show DB.

* Ура!! Заработало!!

- Рано кричать, закрой программу, включи опять и открой твою базу.

* Есть, таблица сразу отобразилась.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*