Advertisement
Guest User

Untitled

a guest
May 4th, 2017
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 14.38 KB | None | 0 0
  1. unit managedb;
  2. {$mode objfpc}{$h+}
  3.  
  4. interface
  5.  
  6. uses
  7.   sqldb, Variants, FBLDatabase, FBLTransaction ,FBLDsql, FBLExcept, ibase_h;
  8.  
  9. type
  10.   TArray = array of variant;
  11.   IDB = Interface
  12.     function initDB          : boolean;
  13.     function getErrorCode    : integer;
  14.     function getErrorMessage : string;
  15.     function getDatabaseName : string;
  16.     function executeQuery    : boolean;
  17.     procedure setQuery(thequery: string);
  18.     procedure setData(value: variant);
  19.     function getResult       : TArray;
  20.   end;
  21.  
  22.   TDB = class
  23.     private
  24.       db : IDB;
  25.     public
  26.       constructor Create(db_type: string);
  27.       function initDB          : boolean;
  28.       function getErrorCode    : integer;
  29.       function getErrorMessage : string;
  30.       function getDatabaseName : string;
  31.       function executeQuery    : boolean;
  32.       procedure setQuery(thequery: string);
  33.       procedure setData(value: variant);
  34.       function getResult       : TArray;
  35.       destructor Destroy; override;
  36.   end;
  37.  
  38.   TDBSQlite = class(TInterfacedObject, IDB)
  39.     private
  40.       DATABASE_FILE : string;
  41.     public
  42.       constructor Create;
  43.       function initDB : boolean;
  44.       function getErrorCode    : integer;
  45.       function getErrorMessage : string;
  46.       function getDatabaseName : string;
  47.       function executeQuery    : boolean;
  48.       procedure setQuery(thequery: string);
  49.       procedure setData(value: variant);
  50.       function getResult       : TArray;
  51.       destructor Destroy; override;
  52.   end;
  53.  
  54.   TDBFirebird = class(TInterfacedObject, IDB)
  55.     private
  56.       DATABASE_FILE : string;
  57.       query        : string;
  58.       dataValue    : array of variant;
  59.       resultValue  : array of variant;
  60.       MyDB         : TFBLDatabase;
  61.       errorCode    : integer;
  62.       errorMessage : string;
  63.       procedure createTables;
  64.       procedure createKeys;
  65.       procedure createSequences;
  66.       procedure createTriggers;
  67.       procedure createData;
  68.     public
  69.       constructor Create;
  70.       function initDB          : boolean;
  71.       function getErrorCode    : integer;
  72.       function getErrorMessage : string;
  73.       function getDatabaseName : string;
  74.       function executeQuery    : boolean;
  75.       procedure setQuery(thequery: string);
  76.       procedure setData(value: variant);
  77.       function getResult       : TArray;
  78.       destructor Destroy; override;
  79.   end;
  80.  
  81. implementation
  82.  
  83. constructor TDB.Create(db_type: string);
  84. begin
  85.   inherited Create;
  86.  
  87.   if (db_type = 'sqlite') then
  88.     db := TDBSQlite.Create
  89.   else if (db_type = 'firebird') then
  90.     db := TDBFirebird.Create
  91. end;
  92.  
  93. destructor TDB.Destroy;
  94. begin
  95.   inherited Destroy;
  96. end;
  97.  
  98. function TDB.initDB: boolean;
  99. begin
  100.   initDB := db.initDB;
  101. end;
  102.  
  103. function TDB.getErrorCode : integer;
  104. begin
  105.   getErrorCode := db.getErrorCode;
  106. end;
  107.  
  108. function TDB.getErrorMessage : string;
  109. begin
  110.   getErrorMessage := db.getErrorMessage;
  111. end;
  112.  
  113. function TDB.getDatabaseName : string;
  114. begin
  115.   getDatabaseName := db.getDatabaseName;
  116. end;
  117.  
  118. function TDB.executeQuery : boolean;
  119. begin
  120.   executeQuery := db.executeQuery;
  121. end;
  122.  
  123. procedure TDB.setQuery(thequery : string);
  124. begin
  125.   db.setQuery(thequery);
  126. end;
  127.  
  128. procedure TDB.setData(value : variant);
  129. begin
  130.   db.setData(value)
  131. end;
  132.  
  133. function TDB.getResult : TArray;
  134. begin
  135.   getResult := db.getResult;
  136. end;
  137.  
  138. {TODO: implementare db per SQLite}
  139. constructor TDBSQlite.Create;
  140. begin
  141.   inherited Create;
  142.  
  143.   DATABASE_FILE := 'mail.db'
  144. end;
  145.  
  146. destructor TDBSQlite.Destroy;
  147. begin
  148.   inherited Destroy;
  149. end;
  150.  
  151. function TDBSQlite.initDB : boolean;
  152. begin
  153.   initDB := False;
  154. end;
  155.  
  156. function TDBSQlite.getErrorCode : integer;
  157. begin
  158.   getErrorCode := 0;
  159. end;
  160.  
  161. function TDBSQlite.getErrorMessage : string;
  162. begin
  163.   getErrorMessage := 'Not implemented';
  164. end;
  165.  
  166. function TDBSQlite.getDatabaseName : string;
  167. begin
  168.   getDatabaseName := DATABASE_FILE;
  169. end;
  170.  
  171. function TDBSQlite.executeQuery : boolean;
  172. begin
  173.   executeQuery := False;
  174. end;
  175.  
  176. procedure TDBSQlite.setQuery(thequery : string);
  177. begin
  178. end;
  179.  
  180. procedure TDBSQlite.setData(value : variant);
  181. begin
  182. end;
  183.  
  184. function TDBSQlite.getResult : TArray;
  185. begin
  186.   getResult := nil;
  187. end;
  188.  
  189. {TODO: cambiare libreria per Firebird}
  190. constructor TDBFirebird.Create;
  191. begin
  192.   inherited Create;
  193.  
  194.   DATABASE_FILE := 'mail.fdb';
  195.  
  196.   MyDB := TFBLDatabase.Create(nil);
  197.   MyDb.DBFile := DATABASE_FILE;
  198.   MyDb.User := 'sysdba';
  199.   MyDb.Password := 'masterkey';
  200.   MyDb.Protocol := ptLocal;
  201. end;
  202.  
  203. destructor TDBFirebird.Destroy;
  204. begin
  205.   MyDB.free;
  206.   inherited Destroy;
  207. end;
  208.  
  209. function TDBFirebird.getDatabaseName : string;
  210. begin
  211.   getDatabaseName := DATABASE_FILE;
  212. end;
  213.  
  214. function TDBFirebird.initDB: boolean;
  215. begin
  216.   try
  217.     MyDB.CreateDatabase(DATABASE_FILE,
  218.                         'sysdba',
  219.                         'masterkey',
  220.                         3,
  221.                         4096,
  222.                         'UTF8');
  223.     createTables;
  224.     createSequences;
  225.     createTriggers;
  226.     //createKeys; {Note: non funziona}
  227.     createData;
  228.     initDB := True;
  229.   except
  230.     on E: EFBLError do
  231.       begin
  232.         errorCode := E.ISC_ErrorCode;
  233.         errorMessage := E.Message;
  234.         initDB := False;
  235.       end;
  236.   end;
  237. end;
  238.  
  239. function TDBFirebird.getErrorMessage: string;
  240. begin
  241.   getErrorMessage := errorMessage;
  242. end;
  243.  
  244. function TDBFirebird.getErrorCode: integer;
  245. begin
  246.   getErrorCode := errorCode;
  247. end;
  248.  
  249. procedure TDBFirebird.createTables;
  250. var
  251.   trans  : TFBLTransaction;
  252.   sqlstr : TFBLDsql;
  253. begin
  254.   trans := TFBLTransaction.Create(nil);
  255.   sqlstr := TFBLDsql.Create(nil);
  256.  
  257.   trans.database := MyDB;
  258.   sqlstr.transaction := trans;
  259.  
  260.   MyDB.Connect; // Open the connection with the database
  261.   trans.StartTransaction;
  262.  
  263.   sqlstr.sql.text := 'CREATE TABLE identities(' +
  264.                      'identity_id integer not null, ' +
  265.                      'identity_desc varchar(30), ' +
  266.                      'is_default char(1), ' +
  267.                      'name varchar(30), ' +
  268.                      'surname varchar(30), ' +
  269.                      'organization varchar(30), ' +
  270.                      'email varchar(50), ' +
  271.                      'constraint pk_identity primary key(identity_id))';
  272.   sqlstr.ExecSQL;
  273.  
  274.   sqlstr.sql.text := 'CREATE TABLE accounts(' +
  275.                      'account_id integer not null, ' +
  276.                      'name varchar(30), ' +
  277.                      'protocol varchar(10), ' +
  278.                      'host varchar(30), ' +
  279.                      'port integer, ' +
  280.                      'userid varchar(30), ' +
  281.                      'account_pwd varchar(255), ' +
  282.                      'constraint pk_accounts primary key(account_id))';
  283.   sqlstr.ExecSQL;
  284.  
  285.   sqlstr.sql.text := 'CREATE TABLE folders( ' +
  286.                      'folder_id integer not null, ' +
  287.                      'name varchar(50), ' +
  288.                      'parent varchar(50), ' +
  289.                      'constraint pk_folders primary key(folder_id))';
  290.   sqlstr.ExecSQL;
  291.  
  292.   sqlstr.sql.text := 'CREATE TABLE emails( ' +
  293.                      'email_id integer not null, ' +
  294.                      'folder_id integer, ' +
  295.                      'constraint pk_emails primary key(email_id))';
  296.   sqlstr.ExecSQL;
  297.  
  298.   sqlstr.sql.text := 'CREATE TABLE headers( ' +
  299.                      'email_id integer, ' +
  300.                      'header_name varchar(50), ' +
  301.                      'header_value varchar(10000))';
  302.   sqlstr.ExecSQL;
  303.  
  304.   sqlstr.sql.text := 'CREATE TABLE bodies( ' +
  305.                      'email_id integer, ' +
  306.                      'body blob sub_type text)';
  307.   sqlstr.ExecSQL;
  308.  
  309.   trans.Commit;
  310.  
  311.   MyDB.Disconnect;
  312.   sqlstr.free;
  313.   trans.free;
  314. end;
  315.  
  316. procedure TDBFirebird.createData;
  317. var
  318.   i       : integer;
  319.   trans   : TFBLTransaction;
  320.   sqlstr  : TFBLDsql;
  321.   folders : array[1..4] of string = ('Inbox', 'Outbox', 'Sentbox', 'Draftbox');
  322. begin
  323.   trans := TFBLTransaction.Create(nil);
  324.   sqlstr := TFBLDsql.Create(nil);
  325.  
  326.   trans.database := MyDB;
  327.   sqlstr.transaction := trans;
  328.  
  329.   MyDB.Connect; // Open the connection with the database
  330.   trans.StartTransaction;
  331.  
  332.   for i := 1 to 4 do
  333.   begin
  334.     sqlstr.sql.text := 'INSERT INTO folders (name, parent) VALUES(?, ?)';
  335.     sqlstr.prepare;
  336.     sqlstr.ParamAsString(0, folders[i]);
  337.     sqlstr.ParamAsString(1, folders[i]);
  338.     sqlstr.ExecSQl;
  339.   end;
  340.    
  341.   trans.Commit;
  342.  
  343.   MyDB.Disconnect;
  344.   sqlstr.free;
  345.   trans.free;
  346. end;
  347.  
  348. procedure TDBFirebird.createKeys;
  349. var
  350.   trans  : TFBLTransaction;
  351.   sqlstr : TFBLDsql;
  352. begin
  353.   trans := TFBLTransaction.Create(nil);
  354.   sqlstr := TFBLDsql.Create(nil);
  355.  
  356.   trans.database := MyDB;
  357.   sqlstr.transaction := trans;
  358.  
  359.   MyDB.Connect;
  360.   trans.StartTransaction;
  361.  
  362.   sqlstr.sql.text := 'ALTER TABLE emails ' +
  363.                      'ADD CONSTRAINT fk_emails_1 ' +
  364.              'FOREIGN KEY (folder_id) ' +
  365.              'REFERENCES folders(folder_id) ' +
  366.              'ON DELETE CASCADE';
  367.   sqlstr.ExecSQL;
  368.  
  369.   sqlstr.sql.text := 'ALTER TABLE bodies ' +
  370.                      'ADD CONSTRAINT fk_bodies_1 ' +
  371.              'FOREIGN KEY (email_id) ' +
  372.              'REFERENCES emails(email_id) ' +
  373.              'ON DELETE CASCADE';
  374.   sqlstr.ExecSQL;
  375.  
  376.   sqlstr.sql.text := 'ALTER TABLE headers ' +
  377.                      'ADD CONSTRAINT fk_headers_1 ' +
  378.              'FOREIGN KEY (email_id) ' +
  379.              'REFERENCES emails(email_id) ' +
  380.              'ON DELETE CASCADE';
  381.   sqlstr.ExecSQL;
  382.  
  383.   trans.Commit;
  384.   MyDB.Disconnect;
  385.  
  386.   sqlstr.free;
  387.   trans.free;
  388. end;
  389.  
  390. procedure TDBFirebird.createSequences;
  391. var
  392.   trans  : TFBLTransaction;
  393.   sqlstr : TFBLDsql;
  394. begin
  395.   trans := TFBLTransaction.Create(nil);
  396.   sqlstr := TFBLDsql.Create(nil);
  397.  
  398.   trans.database := MyDB;
  399.   sqlstr.transaction := trans;
  400.  
  401.   MyDB.Connect;
  402.   trans.StartTransaction;
  403.  
  404.   sqlstr.sql.text := 'CREATE GENERATOR accounts_seq';
  405.   sqlstr.ExecSQL;
  406.  
  407.   sqlstr.sql.text := 'CREATE GENERATOR folders_seq';
  408.   sqlstr.ExecSQL;
  409.  
  410.   sqlstr.sql.text := 'CREATE GENERATOR emails_seq';
  411.   sqlstr.ExecSQL;
  412.  
  413.   sqlstr.sql.text := 'CREATE GENERATOR identity_seq';
  414.   sqlstr.ExecSQL;
  415.  
  416.   trans.Commit;
  417.   MyDB.Disconnect;
  418.  
  419.   sqlstr.free;
  420.   trans.free;
  421. end;
  422.  
  423. procedure TDBFirebird.createTriggers;
  424. var
  425.   trans  : TFBLTransaction;
  426.   sqlstr : TFBLDsql;
  427. begin
  428.   trans := TFBLTransaction.Create(nil);
  429.   sqlstr := TFBLDsql.Create(nil);
  430.  
  431.   trans.database := MyDB;
  432.   sqlstr.transaction := trans;
  433.  
  434.   MyDB.Connect;
  435.   trans.StartTransaction;
  436.  
  437.   sqlstr.sql.text := 'CREATE TRIGGER gen_seq_accounts ' +
  438.                      'FOR accounts ' +
  439.                      'BEFORE INSERT ' +
  440.                      'POSITION 0 ' +
  441.                      'AS ' +
  442.                      'BEGIN ' +
  443.                      'new.account_id = GEN_ID(accounts_seq, 1); ' +
  444.                      'END';
  445.   sqlstr.ExecSQL;
  446.  
  447.   sqlstr.sql.text := 'CREATE TRIGGER gen_seq_emails ' +
  448.                      'FOR emails ' +
  449.                      'BEFORE INSERT ' +
  450.                      'POSITION 0 ' +
  451.                      'AS ' +
  452.                      'BEGIN ' +
  453.                      'new.email_id = GEN_ID(emails_seq, 1); ' +
  454.                      'END';
  455.   sqlstr.ExecSQL;
  456.  
  457.   sqlstr.sql.text := 'CREATE TRIGGER gen_seq_folders ' +
  458.                      'FOR folders ' +
  459.                      'BEFORE INSERT ' +
  460.                      'POSITION 0 ' +
  461.                      'AS ' +
  462.                      'BEGIN ' +
  463.                      'new.folder_id = GEN_ID(folders_seq, 1); ' +
  464.                      'END';
  465.   sqlstr.ExecSQL;
  466.  
  467.   sqlstr.sql.text := 'CREATE TRIGGER gen_seq_identities ' +
  468.                      'FOR identities ' +
  469.                      'BEFORE INSERT ' +
  470.                      'POSITION 0 ' +
  471.                      'AS ' +
  472.                      'BEGIN ' +
  473.                      'new.identity_id = GEN_ID(identity_seq, 1); ' +
  474.                      'END';
  475.   sqlstr.ExecSQL;
  476.  
  477.   trans.Commit;
  478.   MyDB.Disconnect;
  479.  
  480.   sqlstr.free;
  481.   trans.free;
  482. end;
  483.  
  484. procedure TDBFirebird.setQuery(thequery: string);
  485. begin
  486.   query := thequery;
  487. end;
  488.  
  489. procedure TDBFirebird.setData(value: variant);
  490. var
  491.   lengthArray : integer;
  492. begin
  493.   {TODO: trovare una maniera migliore per implemetare i dati passati alla query}
  494.   lengthArray := Length(dataValue);
  495.   SetLength(dataValue, lengthArray + 1);
  496.   dataValue[lengthArray] := value;
  497. end;
  498.  
  499. function TDBFirebird.executeQuery: boolean;
  500. var
  501.   trans       : TFBLTransaction;
  502.   sqlstr      : TFBLDsql;
  503.   i, j        : integer;
  504.   lengthArray : integer;
  505.   returnValue : boolean;
  506.   curDataType : Integer;
  507. begin
  508.   trans := TFBLTransaction.Create(nil);
  509.   sqlstr := TFBLDsql.Create(nil);
  510.  
  511.   trans.database := MyDB;
  512.   sqlstr.transaction := trans;
  513.  
  514.   MyDB.Connect; // Open the connection with the database
  515.   try
  516.     trans.StartTransaction;
  517.    
  518.     // Set the query and prepare the statement
  519.     sqlstr.sql.text := query;
  520.     sqlstr.Prepare;
  521.    
  522.     // Check lenght of the array
  523.     if Length(dataValue) > 0 then
  524.     //writeln('Elements in data: ', Length(dataValue));
  525.     begin
  526.       for i := 0 to Length(dataValue) -1 do
  527.       begin
  528.         writeln('Value ', i, ' is: ', dataValue[i]);
  529.         curDataType := VarType(dataValue[i]) and VarTypeMask;
  530.         case curDataType of
  531.           varInteger : sqlstr.ParamAsLong(i, dataValue[i]);
  532.           varInt64   : sqlstr.ParamAsInt64(i, dataValue[i]);
  533.           varString  : sqlstr.ParamAsString(i, dataValue[i]);
  534.         end;
  535.       end;
  536.     end;
  537.    
  538.     // Execute the query
  539.     sqlstr.ExecSQL;
  540.    
  541.     if sqlstr.FetchCount <> 0 then
  542.     begin
  543.       for i := 0 to sqlstr.FetchCount - 1 do
  544.       begin
  545.         for j := 0 to sqlstr.FieldCount - 1 do
  546.         begin
  547.           lengthArray := Length(resultValue);
  548.           SetLength(resultValue, lengthArray + 1);
  549.           if sqlstr.FieldType(i) = SQL_LONG then
  550.           begin
  551.            resultValue[lengthArray] := sqlstr.FieldAsLong(i);
  552.           end;
  553.         end;
  554.       end;
  555.     end;
  556.    
  557.     trans.Commit;
  558.    
  559.     returnValue := True;
  560.   except
  561.     on E: EFBLError do
  562.     begin
  563.       errorCode := E.ISC_ErrorCode;
  564.       errorMessage := E.Message;
  565.       returnValue := False;
  566.     end;
  567.   end;
  568.  
  569.   MyDB.Disconnect;
  570.   sqlstr.free;
  571.   trans.free;
  572.  
  573.   executeQuery := returnValue;
  574. end;
  575.  
  576. function TDBFirebird.getResult : TArray;
  577. var
  578.   i   : integer;
  579.   res : TArray;
  580. begin
  581.   SetLength(res, Length(resultValue));
  582.  
  583.   for i := 0 to Length(resultValue) -1 do
  584.   begin
  585.     res[i] := resultValue[i];
  586.   end;
  587.  
  588.   getResult := res;
  589. end;
  590.  
  591. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement