mysqlconn.inc 21 KB

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