mysqlconn.inc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. {$mode objfpc}{$H+}
  2. {$MACRO on}
  3. interface
  4. uses
  5. Classes, SysUtils,sqldb,db,dynlibs,
  6. {$IfDef mysql50}
  7. mysql50dyn;
  8. {$DEFINE TConnectionName:=TMySQL50Connection}
  9. {$DEFINE TTransactionName:=TMySQL50Transaction}
  10. {$DEFINE TCursorName:=TMySQL50Cursor}
  11. {$ELSE}
  12. {$IfDef mysql41}
  13. mysql41dyn;
  14. {$DEFINE TConnectionName:=TMySQL41Connection}
  15. {$DEFINE TTransactionName:=TMySQL41Transaction}
  16. {$DEFINE TCursorName:=TMySQL41Cursor}
  17. {$ELSE}
  18. {$IFDEF mysql4} // temporary backwards compatibility for Lazarus
  19. mysql40dyn;
  20. {$DEFINE TConnectionName:=TMySQLConnection}
  21. {$DEFINE TTransactionName:=TMySQLTransaction}
  22. {$DEFINE TCursorName:=TMySQLCursor}
  23. {$ELSE}
  24. mysql40dyn;
  25. {$DEFINE TConnectionName:=TMySQL40Connection}
  26. {$DEFINE TTransactionName:=TMySQL40Transaction}
  27. {$DEFINE TCursorName:=TMySQL40Cursor}
  28. {$EndIf}
  29. {$EndIf}
  30. {$EndIf}
  31. Type
  32. TTransactionName = Class(TSQLHandle)
  33. protected
  34. end;
  35. { TCursorName }
  36. TCursorName = Class(TSQLCursor)
  37. protected
  38. FQMySQL : PMySQL;
  39. FRes: PMYSQL_RES; { Record pointer }
  40. FNeedData : Boolean;
  41. FStatement : String;
  42. Row : MYSQL_ROW;
  43. RowsAffected : QWord;
  44. LastInsertID : QWord;
  45. ParamBinding : TParamBinding;
  46. ParamReplaceString : String;
  47. MapDSRowToMSQLRow : array of integer;
  48. end;
  49. TConnectionName = class (TSQLConnection)
  50. private
  51. FDialect: integer;
  52. FHostInfo: String;
  53. FServerInfo: String;
  54. FMySQL : PMySQL;
  55. FDidConnect : Boolean;
  56. function GetClientInfo: string;
  57. function GetServerStatus: String;
  58. procedure ConnectMySQL(var HMySQL : PMySQL;H,U,P : pchar);
  59. procedure ExecuteDirectMySQL(const query : string);
  60. protected
  61. function StrToStatementType(s : string) : TStatementType; override;
  62. Procedure ConnectToServer; virtual;
  63. Procedure SelectDatabase; virtual;
  64. function MySQLDataType(AType: enum_field_types; ASize, ADecimals: Integer; var NewType: TFieldType; var NewSize: Integer): Boolean;
  65. function MySQLWriteData(AType: enum_field_types;ASize: Integer; AFieldType: TFieldType; BlobStrings: TStringList ;Source, Dest: PChar): Boolean;
  66. // SQLConnection methods
  67. procedure DoInternalConnect; override;
  68. procedure DoInternalDisconnect; override;
  69. function GetHandle : pointer; override;
  70. function GetAsSQLText(Field : TField) : string; overload; virtual;
  71. function GetAsSQLText(Param : TParam) : string; overload; virtual;
  72. Function AllocateCursorHandle : TSQLCursor; override;
  73. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
  74. Function AllocateTransactionHandle : TSQLHandle; override;
  75. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
  76. procedure UnPrepareStatement(cursor:TSQLCursor); override;
  77. procedure FreeFldBuffers(cursor : TSQLCursor); override;
  78. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams); override;
  79. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
  80. function Fetch(cursor : TSQLCursor) : boolean; override;
  81. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer) : boolean; override;
  82. function GetTransactionHandle(trans : TSQLHandle): pointer; override;
  83. function Commit(trans : TSQLHandle) : boolean; override;
  84. function RollBack(trans : TSQLHandle) : boolean; override;
  85. function StartdbTransaction(trans : TSQLHandle; AParams : string) : boolean; override;
  86. procedure CommitRetaining(trans : TSQLHandle); override;
  87. procedure RollBackRetaining(trans : TSQLHandle); override;
  88. procedure UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string); override;
  89. Public
  90. procedure CreateDB; override;
  91. procedure DropDB; override;
  92. Property ServerInfo : String Read FServerInfo;
  93. Property HostInfo : String Read FHostInfo;
  94. property ClientInfo: string read GetClientInfo;
  95. property ServerStatus : String read GetServerStatus;
  96. published
  97. property Dialect : integer read FDialect write FDialect;
  98. property DatabaseName;
  99. property HostName;
  100. property KeepConnection;
  101. property LoginPrompt;
  102. property Params;
  103. property OnLogin;
  104. end;
  105. EMySQLError = Class(Exception);
  106. implementation
  107. uses dbconst;
  108. { TConnectionName }
  109. Resourcestring
  110. SErrServerConnectFailed = 'Server connect failed.';
  111. SErrDatabaseSelectFailed = 'failed to select database: %s';
  112. SErrDatabaseCreate = 'Failed to create database: %s';
  113. SErrDatabaseDrop = 'Failed to drop database: %s';
  114. SErrNoData = 'No data for record';
  115. SErrExecuting = 'Error executing query: %s';
  116. SErrFetchingdata = 'Error fetching row data: %s';
  117. SErrGettingResult = 'Error getting result set: %s';
  118. SErrNoQueryResult = 'No result from query.';
  119. SErrNotversion50 = 'TMySQL50Connection can not work with the installed MySQL client version (%s).';
  120. SErrNotversion41 = 'TMySQL41Connection can not work with the installed MySQL client version (%s).';
  121. SErrNotversion40 = 'TMySQL40Connection can not work with the installed MySQL client version (%s).';
  122. Procedure MySQlError(R : PMySQL;Msg: String;Comp : TComponent);
  123. Var
  124. MySQLMsg : String;
  125. begin
  126. If (R<>Nil) then
  127. begin
  128. MySQLMsg:=Strpas(mysql_error(R));
  129. DatabaseErrorFmt(Msg,[MySQLMsg],Comp);
  130. end
  131. else
  132. DatabaseError(Msg,Comp);
  133. end;
  134. function TConnectionName.StrToStatementType(s : string) : TStatementType;
  135. begin
  136. S:=Lowercase(s);
  137. if s = 'show' then exit(stSelect);
  138. result := inherited StrToStatementType(s);
  139. end;
  140. function TConnectionName.GetClientInfo: string;
  141. Var
  142. B : Boolean;
  143. begin
  144. // To make it possible to call this if there's no connection yet
  145. B:=(MysqlLibraryHandle=Nilhandle);
  146. If B then
  147. InitialiseMysql;
  148. Try
  149. Result:=strpas(mysql_get_client_info());
  150. Finally
  151. if B then
  152. ReleaseMysql;
  153. end;
  154. end;
  155. function TConnectionName.GetServerStatus: String;
  156. begin
  157. CheckConnected;
  158. Result := mysql_stat(FMYSQL);
  159. end;
  160. procedure TConnectionName.ConnectMySQL(var HMySQL : PMySQL;H,U,P : pchar);
  161. begin
  162. HMySQL := mysql_init(HMySQL);
  163. HMySQL:=mysql_real_connect(HMySQL,PChar(H),PChar(U),Pchar(P),Nil,0,Nil,0);
  164. If (HMySQL=Nil) then
  165. MySQlError(Nil,SErrServerConnectFailed,Self);
  166. end;
  167. function TConnectionName.GetAsSQLText(Field : TField) : string;
  168. var esc_str : pchar;
  169. begin
  170. if (not assigned(field)) or field.IsNull then Result := 'Null'
  171. else if field.DataType = ftString then
  172. begin
  173. Getmem(esc_str,sizeof(field.asstring)*2+1);
  174. mysql_real_escape_string(FMySQL,esc_str,pchar(field.asstring),length(field.asstring));
  175. Result := '''' + esc_str + '''';
  176. Freemem(esc_str);
  177. end
  178. else Result := inherited GetAsSqlText(field);
  179. end;
  180. function TConnectionName.GetAsSQLText(Param: TParam) : string;
  181. var esc_str : pchar;
  182. begin
  183. if (not assigned(param)) or param.IsNull then Result := 'Null'
  184. else if param.DataType in [ftString,ftBlob] then
  185. begin
  186. Getmem(esc_str,length(param.asstring)*2+1);
  187. mysql_real_escape_string(FMySQL,esc_str,pchar(param.asstring),length(param.asstring));
  188. Result := '''' + esc_str + '''';
  189. Freemem(esc_str);
  190. end
  191. else Result := inherited GetAsSqlText(Param);
  192. end;
  193. procedure TConnectionName.ConnectToServer;
  194. Var
  195. H,U,P : String;
  196. begin
  197. H:=HostName;
  198. U:=UserName;
  199. P:=Password;
  200. ConnectMySQL(FMySQL,pchar(H),pchar(U),pchar(P));
  201. FServerInfo := strpas(mysql_get_server_info(FMYSQL));
  202. FHostInfo := strpas(mysql_get_host_info(FMYSQL));
  203. end;
  204. procedure TConnectionName.SelectDatabase;
  205. begin
  206. if mysql_select_db(FMySQL,pchar(DatabaseName))<>0 then
  207. MySQLError(FMySQL,SErrDatabaseSelectFailed,Self);
  208. end;
  209. procedure TConnectionName.CreateDB;
  210. begin
  211. ExecuteDirectMySQL('CREATE DATABASE ' +DatabaseName);
  212. end;
  213. procedure TConnectionName.DropDB;
  214. begin
  215. ExecuteDirectMySQL('DROP DATABASE ' +DatabaseName);
  216. end;
  217. procedure TConnectionName.ExecuteDirectMySQL(const query : string);
  218. var ADidConnect : boolean;
  219. H,U,P : String;
  220. AMySQL : PMySQL;
  221. begin
  222. CheckDisConnected;
  223. ADidConnect:=(MySQLLibraryHandle=NilHandle);
  224. if ADidConnect then
  225. InitialiseMysql;
  226. H:=HostName;
  227. U:=UserName;
  228. P:=Password;
  229. AMySQL := nil;
  230. ConnectMySQL(AMySQL,pchar(H),pchar(U),pchar(P));
  231. if mysql_query(AMySQL,pchar(query))<>0 then
  232. MySQLError(AMySQL,Format(SErrExecuting,[StrPas(mysql_error(AMySQL))]),Self);
  233. mysql_close(AMySQL);
  234. if ADidConnect then
  235. ReleaseMysql;
  236. end;
  237. procedure TConnectionName.DoInternalConnect;
  238. begin
  239. FDidConnect:=(MySQLLibraryHandle=NilHandle);
  240. if FDidConnect then
  241. InitialiseMysql;
  242. {$IFDEF mysql50}
  243. if copy(strpas(mysql_get_client_info()),1,3)<>'5.0' then
  244. Raise EInOutError.CreateFmt(SErrNotversion50,[strpas(mysql_get_client_info())]);
  245. {$ELSE}
  246. {$IFDEF mysql41}
  247. if copy(strpas(mysql_get_client_info()),1,3)<>'4.1' then
  248. Raise EInOutError.CreateFmt(SErrNotversion41,[strpas(mysql_get_client_info())]);
  249. {$ELSE}
  250. if copy(strpas(mysql_get_client_info()),1,3)<>'4.0' then
  251. Raise EInOutError.CreateFmt(SErrNotversion40,[strpas(mysql_get_client_info())]);
  252. {$ENDIF}
  253. {$ENDIF}
  254. inherited DoInternalConnect;
  255. ConnectToServer;
  256. SelectDatabase;
  257. end;
  258. procedure TConnectionName.DoInternalDisconnect;
  259. begin
  260. inherited DoInternalDisconnect;
  261. mysql_close(FMySQL);
  262. FMySQL:=Nil;
  263. if FDidConnect then
  264. ReleaseMysql;
  265. end;
  266. function TConnectionName.GetHandle: pointer;
  267. begin
  268. Result:=FMySQL;
  269. end;
  270. function TConnectionName.AllocateCursorHandle: TSQLCursor;
  271. begin
  272. Result:=TCursorName.Create;
  273. end;
  274. Procedure TConnectionName.DeAllocateCursorHandle(var cursor : TSQLCursor);
  275. begin
  276. FreeAndNil(cursor);
  277. end;
  278. function TConnectionName.AllocateTransactionHandle: TSQLHandle;
  279. begin
  280. // Result:=TTransactionName.Create;
  281. Result := nil;
  282. end;
  283. procedure TConnectionName.PrepareStatement(cursor: TSQLCursor;
  284. ATransaction: TSQLTransaction; buf: string;AParams : TParams);
  285. begin
  286. // if assigned(AParams) and (AParams.count > 0) then
  287. // DatabaseError('Parameters (not) yet supported for the MySQL SqlDB connection.',self);
  288. With Cursor as TCursorName do
  289. begin
  290. FStatement:=Buf;
  291. if assigned(AParams) and (AParams.count > 0) then
  292. FStatement := AParams.ParseSQL(FStatement,false,psSimulated,paramBinding,ParamReplaceString);
  293. if FStatementType=stSelect then
  294. FNeedData:=True;
  295. ConnectMySQL(FQMySQL,FMySQL^.host,FMySQL^.user,FMySQL^.passwd);
  296. if mysql_select_db(FQMySQL,pchar(DatabaseName))<>0 then
  297. MySQLError(FQMySQL,SErrDatabaseSelectFailed,Self);
  298. end
  299. end;
  300. procedure TConnectionName.UnPrepareStatement(cursor: TSQLCursor);
  301. begin
  302. With Cursor as TCursorName do
  303. begin
  304. mysql_close(FQMySQL);
  305. FQMysql := nil;
  306. end;
  307. end;
  308. procedure TConnectionName.FreeFldBuffers(cursor: TSQLCursor);
  309. Var
  310. C : TCursorName;
  311. begin
  312. C:=Cursor as TCursorName;
  313. if c.FStatementType=stSelect then
  314. c.FNeedData:=False;
  315. if (c.FQMySQL <> Nil) then
  316. begin
  317. mysql_close(c.FQMySQL);
  318. c.FQMySQL:=Nil;
  319. end;
  320. If (C.FRes<>Nil) then
  321. begin
  322. Mysql_free_result(C.FRes);
  323. C.FRes:=Nil;
  324. end;
  325. SetLength(c.MapDSRowToMSQLRow,0);
  326. inherited;
  327. end;
  328. procedure TConnectionName.Execute(cursor: TSQLCursor;
  329. atransaction: tSQLtransaction;AParams : TParams);
  330. Var
  331. C : TCursorName;
  332. i : integer;
  333. begin
  334. C:=Cursor as TCursorName;
  335. If (C.FRes=Nil) then
  336. begin
  337. if Assigned(AParams) and (AParams.count > 0) then
  338. for i := 0 to AParams.count -1 do
  339. C.FStatement := stringreplace(C.FStatement,C.ParamReplaceString+inttostr(AParams[i].Index+1),GetAsSQLText(AParams[i]),[rfReplaceAll,rfIgnoreCase]);
  340. if mysql_query(c.FQMySQL,Pchar(C.FStatement))<>0 then
  341. MySQLError(c.FQMYSQL,Format(SErrExecuting,[StrPas(mysql_error(c.FQMySQL))]),Self)
  342. else
  343. begin
  344. C.RowsAffected := mysql_affected_rows(c.FQMYSQL);
  345. C.LastInsertID := mysql_insert_id(c.FQMYSQL);
  346. if C.FNeedData then
  347. C.FRes:=mysql_use_result(c.FQMySQL);
  348. end;
  349. end;
  350. end;
  351. function TConnectionName.MySQLDataType(AType: enum_field_types; ASize, ADecimals: Integer;
  352. var NewType: TFieldType; var NewSize: Integer): Boolean;
  353. begin
  354. Result := True;
  355. case AType of
  356. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  357. FIELD_TYPE_INT24:
  358. begin
  359. NewType := ftInteger;
  360. NewSize := 0;
  361. end;
  362. {$ifdef mysql50}
  363. FIELD_TYPE_NEWDECIMAL,
  364. {$endif}
  365. FIELD_TYPE_DECIMAL: if ADecimals < 5 then
  366. begin
  367. NewType := ftBCD;
  368. NewSize := 0;
  369. end
  370. else
  371. begin
  372. NewType := ftFloat;
  373. NewSize := 0;
  374. end;
  375. FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  376. begin
  377. NewType := ftFloat;
  378. NewSize := 0;
  379. end;
  380. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  381. begin
  382. NewType := ftDateTime;
  383. NewSize := 0;
  384. end;
  385. FIELD_TYPE_DATE:
  386. begin
  387. NewType := ftDate;
  388. NewSize := 0;
  389. end;
  390. FIELD_TYPE_TIME:
  391. begin
  392. NewType := ftTime;
  393. NewSize := 0;
  394. end;
  395. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  396. begin
  397. NewType := ftString;
  398. NewSize := ASize;
  399. end;
  400. FIELD_TYPE_BLOB:
  401. begin
  402. NewType := ftBlob;
  403. NewSize := 0;
  404. end
  405. else
  406. Result := False;
  407. end;
  408. end;
  409. procedure TConnectionName.AddFieldDefs(cursor: TSQLCursor;
  410. FieldDefs: TfieldDefs);
  411. var
  412. C : TCursorName;
  413. I, TF, FC: Integer;
  414. field: PMYSQL_FIELD;
  415. DFT: TFieldType;
  416. DFS: Integer;
  417. begin
  418. // Writeln('MySQL: Adding fielddefs');
  419. C:=(Cursor as TCursorName);
  420. If (C.FRes=Nil) then
  421. begin
  422. // Writeln('res is nil');
  423. MySQLError(c.FQMySQL,SErrNoQueryResult,Self);
  424. end;
  425. // Writeln('MySQL: have result');
  426. FC:=mysql_num_fields(C.FRes);
  427. SetLength(c.MapDSRowToMSQLRow,FC);
  428. TF := 1;
  429. For I:= 0 to FC-1 do
  430. begin
  431. field := mysql_fetch_field_direct(C.FRES, I);
  432. // Writeln('MySQL: creating fielddef ',I+1);
  433. if MySQLDataType(field^.ftype, field^.length, field^.decimals, DFT, DFS) then
  434. begin
  435. TFieldDef.Create(FieldDefs, field^.name, DFT, DFS, False, TF);
  436. c.MapDSRowToMSQLRow[TF-1] := I;
  437. inc(TF);
  438. end
  439. end;
  440. // Writeln('MySQL: Finished adding fielddefs');
  441. end;
  442. function TConnectionName.Fetch(cursor: TSQLCursor): boolean;
  443. Var
  444. C : TCursorName;
  445. begin
  446. C:=Cursor as TCursorName;
  447. C.Row:=MySQL_Fetch_row(C.FRes);
  448. Result:=(C.Row<>Nil);
  449. end;
  450. function TConnectionName.LoadField(cursor : TSQLCursor;
  451. FieldDef : TfieldDef;buffer : pointer) : boolean;
  452. var
  453. field: PMYSQL_FIELD;
  454. row : MYSQL_ROW;
  455. C : TCursorName;
  456. begin
  457. // Writeln('LoadFieldsFromBuffer');
  458. C:=Cursor as TCursorName;
  459. if C.Row=nil then
  460. begin
  461. // Writeln('LoadFieldsFromBuffer: row=nil');
  462. MySQLError(c.FQMySQL,SErrFetchingData,Self);
  463. end;
  464. Row:=C.Row;
  465. inc(Row,c.MapDSRowToMSQLRow[FieldDef.FieldNo-1]);
  466. field := mysql_fetch_field_direct(C.FRES, c.MapDSRowToMSQLRow[FieldDef.FieldNo-1]);
  467. Result := MySQLWriteData(field^.ftype, field^.length, FieldDef.DataType, c.FBlobStrings, Row^, Buffer);
  468. end;
  469. function InternalStrToFloat(S: string): Extended;
  470. var
  471. I: Integer;
  472. Tmp: string;
  473. begin
  474. Tmp := '';
  475. for I := 1 to Length(S) do
  476. begin
  477. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  478. Tmp := Tmp + DecimalSeparator
  479. else
  480. Tmp := Tmp + S[I];
  481. end;
  482. Result := StrToFloat(Tmp);
  483. end;
  484. function InternalStrToCurrency(S: string): Extended;
  485. var
  486. I: Integer;
  487. Tmp: string;
  488. begin
  489. Tmp := '';
  490. for I := 1 to Length(S) do
  491. begin
  492. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  493. Tmp := Tmp + DecimalSeparator
  494. else
  495. Tmp := Tmp + S[I];
  496. end;
  497. Result := StrToCurr(Tmp);
  498. end;
  499. function InternalStrToDate(S: string): TDateTime;
  500. var
  501. EY, EM, ED: Word;
  502. begin
  503. EY := StrToInt(Copy(S,1,4));
  504. EM := StrToInt(Copy(S,6,2));
  505. ED := StrToInt(Copy(S,9,2));
  506. if (EY = 0) or (EM = 0) or (ED = 0) then
  507. Result:=0
  508. else
  509. Result:=EncodeDate(EY, EM, ED);
  510. end;
  511. function InternalStrToDateTime(S: string): TDateTime;
  512. var
  513. EY, EM, ED: Word;
  514. EH, EN, ES: Word;
  515. begin
  516. EY := StrToInt(Copy(S, 1, 4));
  517. EM := StrToInt(Copy(S, 6, 2));
  518. ED := StrToInt(Copy(S, 9, 2));
  519. EH := StrToInt(Copy(S, 12, 2));
  520. EN := StrToInt(Copy(S, 15, 2));
  521. ES := StrToInt(Copy(S, 18, 2));
  522. if (EY = 0) or (EM = 0) or (ED = 0) then
  523. Result := 0
  524. else
  525. Result := EncodeDate(EY, EM, ED);
  526. Result := Result + EncodeTime(EH, EN, ES, 0);
  527. end;
  528. function InternalStrToTime(S: string): TDateTime;
  529. var
  530. EH, EM, ES: Word;
  531. begin
  532. EH := StrToInt(Copy(S, 1, 2));
  533. EM := StrToInt(Copy(S, 4, 2));
  534. ES := StrToInt(Copy(S, 7, 2));
  535. Result := EncodeTime(EH, EM, ES, 0);
  536. end;
  537. function InternalStrToTimeStamp(S: string): TDateTime;
  538. var
  539. EY, EM, ED: Word;
  540. EH, EN, ES: Word;
  541. begin
  542. {$IFNDEF mysql40}
  543. EY := StrToInt(Copy(S, 1, 4));
  544. EM := StrToInt(Copy(S, 6, 2));
  545. ED := StrToInt(Copy(S, 9, 2));
  546. EH := StrToInt(Copy(S, 12, 2));
  547. EN := StrToInt(Copy(S, 15, 2));
  548. ES := StrToInt(Copy(S, 18, 2));
  549. {$ELSE}
  550. EY := StrToInt(Copy(S, 1, 4));
  551. EM := StrToInt(Copy(S, 5, 2));
  552. ED := StrToInt(Copy(S, 7, 2));
  553. EH := StrToInt(Copy(S, 9, 2));
  554. EN := StrToInt(Copy(S, 11, 2));
  555. ES := StrToInt(Copy(S, 13, 2));
  556. {$ENDIF}
  557. if (EY = 0) or (EM = 0) or (ED = 0) then
  558. Result := 0
  559. else
  560. Result := EncodeDate(EY, EM, ED);
  561. Result := Result + EncodeTime(EH, EN, ES, 0);;
  562. end;
  563. function TConnectionName.MySQLWriteData(AType: enum_field_types;ASize: Integer; AFieldType: TFieldType; BlobStrings: TStringList; Source, Dest: PChar): Boolean;
  564. var
  565. VI: Integer;
  566. VF: Double;
  567. VC: Currency;
  568. VD: TDateTime;
  569. Src : String;
  570. begin
  571. Result := False;
  572. if Source = Nil then
  573. exit;
  574. Src:=StrPas(Source);
  575. case AType of
  576. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG,
  577. FIELD_TYPE_INT24:
  578. begin
  579. if (Src<>'') then
  580. VI := StrToInt(Src)
  581. else
  582. VI := 0;
  583. Move(VI, Dest^, SizeOf(Integer));
  584. end;
  585. FIELD_TYPE_LONGLONG:
  586. begin
  587. if (Src<>'') then
  588. VI := StrToInt64(Src)
  589. else
  590. VI := 0;
  591. Move(VI, Dest^, SizeOf(LargeInt));
  592. end;
  593. {$ifdef mysql50}
  594. FIELD_TYPE_NEWDECIMAL,
  595. {$endif}
  596. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  597. if AFieldType = ftBCD then
  598. begin
  599. VC := InternalStrToCurrency(Src);
  600. Move(VC, Dest^, SizeOf(Currency));
  601. end
  602. else
  603. begin
  604. if Src <> '' then
  605. VF := InternalStrToFloat(Src)
  606. else
  607. VF := 0;
  608. Move(VF, Dest^, SizeOf(Double));
  609. end;
  610. FIELD_TYPE_TIMESTAMP:
  611. begin
  612. if Src <> '' then
  613. VD := InternalStrToTimeStamp(Src)
  614. else
  615. VD := 0;
  616. Move(VD, Dest^, SizeOf(TDateTime));
  617. end;
  618. FIELD_TYPE_DATETIME:
  619. begin
  620. if Src <> '' then
  621. VD := InternalStrToDateTime(Src)
  622. else
  623. VD := 0;
  624. Move(VD, Dest^, SizeOf(TDateTime));
  625. end;
  626. FIELD_TYPE_DATE:
  627. begin
  628. if Src <> '' then
  629. VD := InternalStrToDate(Src)
  630. else
  631. VD := 0;
  632. Move(VD, Dest^, SizeOf(TDateTime));
  633. end;
  634. FIELD_TYPE_TIME:
  635. begin
  636. if Src <> '' then
  637. VD := InternalStrToTime(Src)
  638. else
  639. VD := 0;
  640. Move(VD, Dest^, SizeOf(TDateTime));
  641. end;
  642. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  643. begin
  644. { Write('Moving string of size ',asize,' : ');
  645. P:=Source;
  646. If (P<>nil) then
  647. While P[0]<>#0 do
  648. begin
  649. Write(p[0]);
  650. inc(p);
  651. end;
  652. Writeln;
  653. } if Src<> '' then
  654. Move(Source^, Dest^, ASize)
  655. else
  656. Dest^ := #0;
  657. end;
  658. FIELD_TYPE_BLOB:
  659. begin
  660. // The data is stored in the TStringlist BlobStrings and it's index is
  661. // stored in the record-buffer.
  662. vi := BlobStrings.Add(Src);
  663. Move(VI, Dest^, SizeOf(Integer));
  664. end
  665. end;
  666. Result := True;
  667. end;
  668. procedure TConnectionName.UpdateIndexDefs(var IndexDefs : TIndexDefs;TableName : string);
  669. var qry : TSQLQuery;
  670. begin
  671. if not assigned(Transaction) then
  672. DatabaseError(SErrConnTransactionnSet);
  673. qry := tsqlquery.Create(nil);
  674. qry.transaction := Transaction;
  675. qry.database := Self;
  676. with qry do
  677. begin
  678. ReadOnly := True;
  679. sql.clear;
  680. sql.add('show index from ' + TableName);
  681. open;
  682. end;
  683. while not qry.eof do with IndexDefs.AddIndexDef do
  684. begin
  685. Name := trim(qry.fieldbyname('Key_name').asstring);
  686. Fields := trim(qry.fieldbyname('Column_name').asstring);
  687. If Name = 'PRIMARY' then options := options + [ixPrimary];
  688. If qry.fieldbyname('Non_unique').asinteger = 0 then options := options + [ixUnique];
  689. qry.next;
  690. { while (name = qry.fields[0].asstring) and (not qry.eof) do
  691. begin
  692. Fields := Fields + ';' + trim(qry.Fields[2].asstring);
  693. qry.next;
  694. end;}
  695. end;
  696. qry.close;
  697. qry.free;
  698. end;
  699. function TConnectionName.GetTransactionHandle(trans: TSQLHandle): pointer;
  700. begin
  701. Result:=Nil;
  702. end;
  703. function TConnectionName.Commit(trans: TSQLHandle): boolean;
  704. begin
  705. // Do nothing.
  706. end;
  707. function TConnectionName.RollBack(trans: TSQLHandle): boolean;
  708. begin
  709. // Do nothing
  710. end;
  711. function TConnectionName.StartdbTransaction(trans: TSQLHandle; AParams : string): boolean;
  712. begin
  713. // Do nothing
  714. end;
  715. procedure TConnectionName.CommitRetaining(trans: TSQLHandle);
  716. begin
  717. // Do nothing
  718. end;
  719. procedure TConnectionName.RollBackRetaining(trans: TSQLHandle);
  720. begin
  721. // Do nothing
  722. end;
  723. end.