unit usqlutils;

{$mode delphi}

interface

uses
  Classes, SysUtils, xmatdefs, matreal, MatEnt;


type

  { TSQLTableHelper }

  TSQLTableHelper = class
    tabla: string;

    campos, valores, tipos: TStringList;
    keyname: string;
    kkey: integer; // Posición del campo llave
    keyIsSerial: boolean;

    constructor Create( nombreTabla: string; keyName: string = 'nid'; keyIsSerial: boolean = true );
    procedure Free;

    procedure add( campo: string; valor: string; tipo: string = 'varchar' ); overload;
    procedure add( campo: string; valor: integer; tipo: string='integer'); overload;
    procedure add( campo: string; valor: TDateTime; tipo: string = 'timestamp' ); overload;
    procedure add( campo: string; valor: double; tipo: string = 'double precision' ); overload;
    procedure add( campo: string; valor: boolean; tipo: string = 'boolean' ); overload;

    // PostgreSQL
    procedure add( campo: string; valor: TDAOfDateTime; tipo: string = 'timestamp []' ); overload;
    procedure add( campo: string; valor: TDAofString; tipo: string = 'text []' ); overload;
    procedure add( campo: string; valor: TStrings; tipo: string = 'text []' ); overload;
    procedure add( campo: string; valor: TVectR; tipo: string = 'double precision []' ); overload;
    procedure add( campo: string; valor: TMatR; tipo: string = 'double precision [][]' ); overload;
    procedure add( campo: string; valor: TVectE; tipo: string = 'integer []' ); overload;
    procedure add( campo: string; valor: TMatE; tipo: string = 'integer [][]' ); overload;

    // Para insertar un registro solo usar kRec = -1
    // Cuando son muchos registros usar kRec = 0 ... NR-1 y en cada llamada va
    // retornando los string a concatenar para hacer el insert de los multiples registros en una
    // sola instrucción.
    function GetInsertStr( getNextVal: boolean = true; kRec: integer = -1 ): string;
    function GetUpdateStr: string;
    function GetCreateStr: string;
  end;



implementation

constructor TSQLTableHelper.Create( nombreTabla: string; keyName: string = 'nid'; keyIsSerial: boolean = true  );
begin
  inherited Create;
  tabla:= nombreTabla;
  campos:= TStringList.Create;
  valores:= TStringList.Create;
  tipos:= TStringList.Create;
  self.keyName:= keyName;
  self.keyIsSerial:= keyIsSerial;
  kkey:= -1;
end;




function TSQLTableHelper.GetInsertStr(getNextVal: boolean; kRec: integer
  ): string;
var
  resa, resb: string;
  k: integer;

begin
  if campos.Count  = 0 then
  begin
    result:= '';
    exit;
  end;

  resa:= '';
  resb:= '';

  for k:= 0 to campos.count -1 do
  begin
    if k > 0 then
    begin
        resa:= resa+', ';
        resb:= resb+', ';
    end;
    resa:= resa + campos[k];

    if keyIsSerial and  getNextVal and (k = kkey) then
       resb:= resb+'nextval('''+tabla+'_'+campos[k]+'_seq'+''')'
    else
      resb:= resb + ''''+valores[k]+'''';
  end;

  if kRec < 0 then
    result:= 'INSERT INTO '+tabla+' ( '+resa+' ) VALUES ( '+resb+' ); '
  else
    if kRec = 0 then
      result:= 'INSERT INTO '+tabla+' ( '+resa+' ) VALUES ( '+resb+' )'
    else
      result:= ', ( '+resb+' )'
end;


function TSQLTableHelper.GetUpdateStr: string;
var
  res: string;
  k: integer;
begin
  if campos.Count  = 0 then
  begin
    result:= '';
    exit;
  end;

  res:= 'UPDATE '+tabla+' SET ';
  for k:= 0 to campos.Count-1 do
  begin
    if k > 0 then res:= res+', ';
    res:= res+campos[k]+'= '''+valores[k]+'''';
  end;

  if kkey >= 0 then
    res:= res+' WHERE '+keyname+'= '''+valores[kkey]+'''; '
  else
    res:= res+';';
  result:= res;
end;

function TSQLTableHelper.GetCreateStr: string;
var
  res: string;
  k: integer;
begin
  if campos.Count  = 0 then
  begin
    result:= '';
    exit;
  end;

  res:= 'CREATE TABLE '+tabla+' ( ';


  for k:= 0 to campos.count-1 do
  begin
    if ( kkey = k ) then
      if keyIsSerial then
        res:= res+' '+Campos[k]+' serial PRIMARY KEY'
      else
        res:= res+' '+Campos[k]+' PRIMARY KEY'
    else
      res:= res+' '+Campos[k]+' '+tipos[k];
    if k < (campos.count-1) then
       res:= res+', ';
  end;
  res:= res+' ); ';
  result:= res;
end;

procedure TSQLTableHelper.add(campo: string; valor: string; tipo: string);
begin
  if campo = keyname then
    kkey:= campos.count;
  campos.add( campo );
  valores.add( valor );
  tipos.add( tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: integer; tipo: string);
begin
  add( campo, IntToStr( valor ), tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: TDateTime; tipo: string);
var
  dt: TDateTime;
begin
  dt:= valor + 0.5 / (3600.0*24.0);
  add( campo, FormatDateTime( 'yyyy-mm-dd hh:nn:ss', dt ), tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: double; tipo: string);
begin
  add( campo, FloatToStr( valor ), tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: boolean; tipo: string);
begin
  if valor then
    add( campo, '1', tipo)
  else
    add( campo, '0', tipo);
end;

procedure TSQLTableHelper.add(campo: string; valor: TDAOfDateTime; tipo: string
  );
var
  k: integer;
  s: string;
begin
  s:= '{';
  for k:= 0 to high( valor ) do
  begin
    if k > 0 then s:= s+',';
    s:= s+'"'+ FormatDateTime( 'yyyy-mm-dd hh:nn:ss', valor[k])+'"';
  end;
  s:= s+'}';
  add( campo, s, tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: TDAofString; tipo: string);
var
  k: integer;
  s: string;
begin
  s:= '{';
  for k:= 0 to high( valor ) do
  begin
    if k > 0 then s:= s+',';
    s:= s+'"'+valor[k]+'"';
  end;
  s:= s+'}';
  add( campo, s, tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: TStrings; tipo: string);
var
  k: integer;
  s: string;
begin
  s:= '{';
  for k:= 0 to valor.Count-1 do
  begin
    if k > 0 then s:= s+',';
    s:= s+'"'+valor[k]+'"';
  end;
  s:= s+'}';
  add( campo, s, tipo );
end;

procedure TSQLTableHelper.add(campo: string; valor: TVectR; tipo: string);
begin
  if valor <> nil then
    add( campo, valor.serialize_pg, tipo )
  else
    add( campo, '', tipo )
end;

procedure TSQLTableHelper.add(campo: string; valor: TMatR; tipo: string);
begin
  if valor <> nil then
    add( campo, valor.serialize_pg, tipo )
  else
    add( campo, '', tipo )
end;

procedure TSQLTableHelper.add(campo: string; valor: TVectE; tipo: string);
begin
  if valor <> nil then
   add( campo, valor.serialize_pg, tipo )
  else
    add( campo, '', tipo )
end;

procedure TSQLTableHelper.add(campo: string; valor: TMatE; tipo: string);
begin
  if valor <> nil then
   add( campo, valor.serialize_pg, tipo )
  else
    add( campo, '', tipo )
end;

procedure TSQLTableHelper.Free;
begin
  campos.Free;
  valores.Free;
  tipos.Free;
  inherited Free;
end;

end.

