mysqlconn.inc 21 KB

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