mysqlconn.inc 23 KB

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