2.1.2. Sqlj

Вместо ExecSql и ExecSqlEx. Когда размер паскаль-скрипта переваливает за два экрана становится неудобно переходить от вызова к тексту sql и обратно. Также при большом количестве входных/выходных параметров теряется связь между названием, типом и значением параметра и вероятность опечаток сильно увеличивается. Эти недостатки можно исправить использованием стандарта SqlJ при вызове sql из паскаль-операций.

2.1.2.1. Примеры

ExecSql и ExecSqlEx SqlJ
<sql>
  <refsrv>
  [out bprefsrv]
  begin
    :bprefsrv := nvl(BTK_ClientGate.GetClassProperty(:idpClass, BTK.EnableRefService), 1);
  end;
</refsrv>
</sql>
<pascal>
  // Найти значение свойства EnableRefService
  z := ExecSQLEx('refsrv', 'bprefsrv;idpClass', [ftFloat, ftFloat], [0, GetVar('IDCLASS')]);
  AddVar('EnableRefService#', z[0], ftFloat);
</pascal>
<pascal>
  // Найти значение свойства EnableRefService
  z := #ExecSQL{
    begin
      :bprefsrv := nvl(BTK_ClientGate.GetClassProperty(:idpClass, BTK.EnableRefService), 1);
    end;
  } using {
    var bprefsrv:ftFloat = 0
    val idpClass:ftFloat = GetVar('IDCLASS')
  };
  AddVar('EnableRefService#', z.bprefsrv, ftFloat);
</pascal>
<sql>
<ins>
[OUT id]
begin
  :id := STK_StockAPI.INSERTITEMEX(:idParent#,:IDPStockType#);
  if :idParent# is null then
    STK_StockAPI.SetidDepartment( :id, :FILTER$FLT_IDDEPOWNER );
  end if;
end;
</ins>
</sql>
<pascal>
  selection.execopscript('INSERTITEM_Before');
  ExecSQL('ins');
    if SelfVarExists('idItem#') then
      SetVar('idItem#', getVar('id'))
    else AddVar('idItem#',  getVar('id'), ftFloat);
    Setvar('idParent', GetVar('idParent#'));
</pascal>
<pascal>
  selection.execopscript('INSERTITEM_Before');
  #ExecSQL{
    begin
      :id := STK_StockAPI.INSERTITEMEX(:idParent#, :IDPStockType#);
      if :idParent# is null then
        STK_StockAPI.SetidDepartment(:id, :FILTER$FLT_IDDEPOWNER);
      end if;
    end;
  } using {
    var id out
  };
  if SelfVarExists('idItem#') then SetVar('idItem#', getVar('id'))
  else AddVar('idItem#', getVar('id'), ftFloat);
  Setvar('idParent', GetVar('idParent#'));
</pascal>
<sql>
 <CheckTransBeforeReturnToCreate>
   begin
     STM_SettlementDocApi.CheckTransBeforeReturnToCreate(:id, :idState);
   end;
</CheckTransBeforeReturnToCreate>
</sql>
<pascal>
  ExecSql('CheckTransBeforeReturnToCreate');
</pascal>
<pascal>
  #ExecSQL{
    begin
      STM_SettlementDocApi.CheckTransBeforeReturnToCreate(:id, :idState);
    end;
  };
</pascal>
<sql>
  <DoChangeIBState>
  begin
    STM_InvoiceBillApi.DoChangeStateForInvoiceBill(:idSelf, :npStVal);
  end;
  </DoChangeIBState>
</sql>
<pascal>
   ExecSQLEx('DoChangeIBState','npStVal;idSelf',[ftFloat,ftFloat],[0,GetVar('id')]);
</pascal>
<pascal>
  #ExecSQL{
    begin
      STM_InvoiceBillApi.DoChangeStateForInvoiceBill(:idSelf, :npStVal);
    end;
  } using {
    val npStVal:ftFloat = 0
    val idSelf:ftFloat = GetVar('id')
  };
</pascal>
<sql>
  <DoChangeIBState>
  [out npRes]
  begin
    :npRes := STM_InvoiceBillApi.DoChangeStateForInvoiceBill(:idSelf, :npStVal);
  end;
  </DoChangeIBState>
</sql>
<pascal>
  v := ExecSQLEx('DoChangeIBState','npRes;npStVal;idSelf',[ftFloat,ftFloat,ftFloat],[0,0,GetVar('id')]);

  if v[0] = 1 then showmessage(1);
</pascal>
<pascal>
  v := #ExecSQL{
    begin
      :npRes := STM_InvoiceBillApi.DoChangeStateForInvoiceBill(:idSelf, :npStVal);
    end;
  } using {
    var npRes:ftFloat = 0
    val npStVal:ftFloat = 0
    val idSelf:ftFloat = GetVar('id')
  };

  if v.npRes = 1 then showmessage(1);
</pascal>
<pascal>
  args := CreateArgs();
  args.sSqlText := 'select t.num from btk_solidseq t where t.num < :npMaxNum order by t.num';
  args.aParam := [['npMaxNum',ftFloat,10]];
  ovCur := libs['SEL_BTS_SqlCursorLib'].Execute('getSqlCursor', args);

  if not ovCur.IsEmpty then
  repeat
    showMessage(ovCur.GetSelfVar('num'));
  until not ovCur.NextRecord;
</pascal>
<pascal>
  v = #sql{
         select t.num from btk_solidseq t where t.num < :npMaxNum order by t.num
      } using {
        val npMaxNum:ftFloat = 10
      };
  while not v.Eof do
  begin
    showMessage(v.rec.num);

    v.Next;
  end;
</pascal>
 
<pascal>
  #SelectSQl{
    select t.num from btk_solidseq t where t.num = :npMaxNum
  } into {
    nvNum:ftFloat = $num
  } using {
    val npMaxNum:ftFloat = 10
  };
  showMessage(nvNum);
</pascal>

2.1.2.2. Реальные примеры

На базе devBTK в редакторе операций выборки в меню под молоточками добавлена операция “Сравнение ExecSql и SqlJ”. Если ее вызвать, откроется двухпанельный редактор: слева обычный скрипт, справа конвертированный в sqlj. Скрипт слева можно менять и после нажатия на кнопку обновить обновится конвертированная версия.