mysqldb4.pp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. unit MySQLDB4;
  2. {$H+}
  3. interface
  4. uses
  5. SysUtils, Classes, db, mysql4,mysql4_com;
  6. type
  7. PMySQLDatasetBookmark = ^TMySQLDatasetBookmark;
  8. TMySQLDatasetBookmark = record
  9. BookmarkData: Integer;
  10. BookmarkFlag: TBookmarkFlag;
  11. end;
  12. Pinteger = ^Integer;
  13. TMySQLDatabase = class(TDatabase)
  14. Private
  15. FMYSQL: PMYSQL;
  16. FServerInfo: string;
  17. FHostInfo: string;
  18. function GetHostName: String;
  19. Function GetUserName : String;
  20. procedure SetHostName(const AValue: String);
  21. Procedure SetUserName (Value : String);
  22. Procedure SetPassword (Value : String);
  23. Function GetPassword : String;
  24. Function GetClientInfo : String;
  25. Protected
  26. Procedure ConnectToServer;
  27. Procedure SelectDatabase;
  28. Procedure DoInternalConnect; override;
  29. Procedure DoInternalDisConnect; override;
  30. procedure StartTransaction; override;
  31. procedure EndTransaction; override;
  32. function GetServerStatus: string;
  33. Public
  34. Procedure CreateDatabase;
  35. Procedure DropDatabase;
  36. Property ServerInfo : String Read FServerInfo;
  37. Property HostInfo : String Read FHostInfo;
  38. property ClientInfo: string read GetClientInfo;
  39. property ServerStatus : String read GetServerStatus;
  40. Published
  41. Property UserName : String Read GetUserName Write SetUserName;
  42. Property HostName : String Read GetHostName Write SetHostName;
  43. Property Password : String Read GetPassword Write SetPassword;
  44. end;
  45. TMySQLDataset = class(TDBDataSet)
  46. private
  47. FSQL: TStrings;
  48. FRecordSize: Integer;
  49. FBufferSize: Integer;
  50. // MySQL data
  51. FMYSQLRES: PMYSQL_RES;
  52. FCurrentRecord: Integer; { Record pointer }
  53. FAffectedRows: QWord;
  54. FLastInsertID: Integer;
  55. FLoadingFieldDefs: Boolean;
  56. procedure DoClose;
  57. procedure DoQuery;
  58. procedure DoGetResult;
  59. procedure CalculateSizes;
  60. procedure LoadBufferFromData(Buffer: PChar);
  61. protected
  62. Function FMySQL : PMySQL;
  63. procedure SetSQL(const Value: TStrings);
  64. function InternalStrToFloat(S: string): Extended;
  65. function InternalStrToDate(S: string): TDateTime;
  66. function InternalStrToTime(S: string): TDateTime;
  67. function InternalStrToDateTime(S: string): TDateTime;
  68. function InternalStrToTimeStamp(S: string): TDateTime;
  69. function MySQLFieldToFieldType(AType: enum_field_types; ASize: Integer;
  70. var NewType: TFieldType; var NewSize: Integer): Boolean;
  71. function MySQLDataSize(AType: enum_field_types; ASize: Integer): Integer;
  72. function MySQLWriteFieldData(AType: enum_field_types; ASize: Integer; Source: PChar;
  73. Dest: PChar): Integer;
  74. function GetCanModify: Boolean; override;
  75. { Mandatory overrides }
  76. // Record buffer methods:
  77. function AllocRecordBuffer: PChar; override;
  78. procedure FreeRecordBuffer(var Buffer: PChar); override;
  79. procedure InternalInitRecord(Buffer: PChar); override;
  80. function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override;
  81. function GetRecordSize: Word; override;
  82. procedure SetFieldData(Field: TField; Buffer: Pointer); override;
  83. // Bookmark methods:
  84. procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override;
  85. function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override;
  86. procedure InternalGotoBookmark(ABookmark: Pointer); override;
  87. procedure InternalSetToRecord(Buffer: PChar); override;
  88. procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override;
  89. procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override;
  90. // Navigational methods:
  91. procedure InternalFirst; override;
  92. procedure InternalLast; override;
  93. // Editing methods:
  94. procedure InternalAddRecord(Buffer: Pointer; DoAppend: Boolean); override;
  95. procedure InternalDelete; override;
  96. procedure InternalPost; override;
  97. // Misc methods:
  98. procedure InternalClose; override;
  99. procedure InternalHandleException; override;
  100. procedure InternalInitFieldDefs; override;
  101. procedure InternalOpen; override;
  102. function IsCursorOpen: Boolean; override;
  103. { Optional overrides }
  104. function GetRecordCount: Integer; override;
  105. function GetRecNo: Integer; override;
  106. procedure SetRecNo(Value: Integer); override;
  107. public
  108. constructor Create(AOwner: TComponent); override;
  109. destructor Destroy; override;
  110. procedure ExecSQL;
  111. // TDataset method
  112. function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override;
  113. property AffectedRows: QWord read FAffectedRows;
  114. property LastInsertID: Integer read FLastInsertID;
  115. published
  116. property Active;
  117. property Database;
  118. property SQL: TStrings read FSQL write SetSQL;
  119. property BeforeOpen;
  120. property AfterOpen;
  121. property BeforeClose;
  122. property AfterClose;
  123. property BeforeInsert;
  124. property AfterInsert;
  125. property BeforeEdit;
  126. property AfterEdit;
  127. property BeforePost;
  128. property AfterPost;
  129. property BeforeCancel;
  130. property AfterCancel;
  131. property BeforeDelete;
  132. property AfterDelete;
  133. property BeforeScroll;
  134. property AfterScroll;
  135. property OnDeleteError;
  136. property OnEditError;
  137. end;
  138. EMySQLError = Class(Exception);
  139. implementation
  140. Resourcestring
  141. SErrServerConnectFailed = 'Server connect failed.';
  142. SErrDatabaseSelectFailed = 'failed to select database: %s';
  143. SErrDatabaseCreate = 'Failed to create database: %s';
  144. SErrDatabaseDrop = 'Failed to drop database: %s';
  145. SErrNoData = 'No data for record';
  146. SErrExecuting = 'Error executing query: %s';
  147. SErrFetchingdata = 'Error fetching row data: %s';
  148. SErrGettingResult = 'Error getting result set: %s';
  149. Procedure MySQlError(R : PMySQL;Msg: String;Comp : TComponent);
  150. Var
  151. MySQLMsg : String;
  152. begin
  153. If (R<>Nil) then
  154. begin
  155. MySQLMsg:=Strpas(mysql_error(R));
  156. DatabaseErrorFmt(Msg,[MySQLMsg],Comp);
  157. end
  158. else
  159. DatabaseError(Msg,Comp);
  160. end;
  161. { TMySQLDataset }
  162. constructor TMySQLDataset.Create(AOwner: TComponent);
  163. begin
  164. inherited Create(AOwner);
  165. FSQL := TStringList.Create;
  166. FBufferSize := 0;
  167. FRecordSize := 0;
  168. FCurrentRecord := -1;
  169. FLoadingFieldDefs := False;
  170. FAffectedRows := 0;
  171. FLastInsertID := -1;
  172. FMYSQLRES := nil;
  173. end;
  174. destructor TMySQLDataset.Destroy;
  175. begin
  176. Close;
  177. FSQL.Free;
  178. inherited destroy;
  179. end;
  180. function TMySQLDataset.AllocRecordBuffer: PChar;
  181. begin
  182. Result := AllocMem(FBufferSize);
  183. end;
  184. procedure TMySQLDataset.FreeRecordBuffer(var Buffer: PChar);
  185. begin
  186. If (@Buffer<>nil) then
  187. FreeMem(Buffer);
  188. end;
  189. procedure TMySQLDataset.GetBookmarkData(Buffer: PChar; Data: Pointer);
  190. begin
  191. PInteger(Data)^ := PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData;
  192. end;
  193. function TMySQLDataset.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag;
  194. begin
  195. Result:=PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkFlag;
  196. end;
  197. function TMySQLDataset.GetFieldData(Field: TField; Buffer: Pointer): Boolean;
  198. var
  199. I, FC: Integer;
  200. fld: PMYSQL_FIELD;
  201. CurBuf: PChar;
  202. begin
  203. Result := False;
  204. CurBuf := ActiveBuffer;
  205. FC := mysql_num_fields(FMYSQLRES);
  206. for I := 0 to FC-1 do
  207. begin
  208. fld := mysql_fetch_field_direct(FMYSQLRES, I);
  209. if Field.FieldName = fld^.name then
  210. begin
  211. Move(CurBuf^, PChar(Buffer)^, MySQLDataSize(fld^.ftype, fld^.length));
  212. if Field.DataType in [ftString{, ftWideString}] then
  213. begin
  214. Result := PChar(buffer)^ <> #0;
  215. if Result then
  216. // Terminate string (necessary for enum fields)
  217. PChar(buffer)[fld^.length] := #0;
  218. end
  219. else
  220. Result := True;
  221. break;
  222. end
  223. else
  224. Inc(CurBuf, MySQLDataSize(fld^.ftype, fld^.length));
  225. end;
  226. end;
  227. function TMySQLDataset.GetRecNo: Integer;
  228. begin
  229. UpdateCursorPos;
  230. if (FCurrentRecord=-1) and (RecordCount > 0) then
  231. Result:=1
  232. else
  233. Result:=FCurrentRecord+1;
  234. end;
  235. function TMySQLDataset.GetRecord(Buffer: PChar; GetMode: TGetMode;
  236. DoCheck: Boolean): TGetResult;
  237. begin
  238. if RecordCount < 1 then
  239. Result := grEOF
  240. else
  241. begin
  242. Result := grOk;
  243. case GetMode of
  244. gmPrior:
  245. if FCurrentRecord <= 0 then
  246. begin
  247. Result := grBOF;
  248. FCurrentRecord := -1;
  249. end
  250. else
  251. Dec(FCurrentRecord);
  252. gmCurrent:
  253. if (FCurrentRecord<0) or (FCurrentRecord>=RecordCount) then
  254. Result := grError;
  255. gmNext:
  256. if FCurrentRecord>=RecordCount-1 then
  257. Result := grEOF
  258. else
  259. Inc(FCurrentRecord);
  260. end;
  261. if (Result=grOK) then
  262. begin
  263. LoadBufferFromData(Buffer);
  264. with PMySQLDatasetBookmark(Buffer + FRecordSize)^ do
  265. begin
  266. BookmarkData := FCurrentRecord;
  267. BookmarkFlag := bfCurrent;
  268. end;
  269. end
  270. else
  271. if (Result=grError) and (DoCheck) then
  272. DatabaseError(SerrNoData,Self);
  273. end;
  274. end;
  275. function TMySQLDataset.GetRecordCount: Integer;
  276. begin
  277. Result:=mysql_num_rows(FMYSQLRES);
  278. end;
  279. function TMySQLDataset.GetRecordSize: Word;
  280. begin
  281. Result:=FRecordSize;
  282. end;
  283. procedure TMySQLDataset.InternalAddRecord(Buffer: Pointer; DoAppend: Boolean);
  284. begin
  285. end;
  286. procedure TMySQLDataset.InternalClose;
  287. begin
  288. FCurrentRecord := -1;
  289. DoClose;
  290. if DefaultFields then
  291. DestroyFields;
  292. end;
  293. procedure TMySQLDataset.InternalDelete;
  294. begin
  295. end;
  296. procedure TMySQLDataset.InternalFirst;
  297. begin
  298. FCurrentRecord := -1;
  299. end;
  300. procedure TMySQLDataset.InternalGotoBookmark(ABookmark: Pointer);
  301. begin
  302. FCurrentRecord := PInteger(ABookmark)^;
  303. end;
  304. procedure TMySQLDataset.InternalHandleException;
  305. begin
  306. // Application.HandleException(self);
  307. end;
  308. procedure TMySQLDataset.InternalInitFieldDefs;
  309. var
  310. I, FC: Integer;
  311. field: PMYSQL_FIELD;
  312. DFT: TFieldType;
  313. DFS: Integer;
  314. WasClosed: Boolean;
  315. begin
  316. if FLoadingFieldDefs then Exit;
  317. FLoadingFieldDefs := True;
  318. try
  319. WasClosed := not IsCursorOpen;
  320. if WasClosed then
  321. begin
  322. DoQuery;
  323. DoGetResult;
  324. end;
  325. try
  326. FieldDefs.Clear;
  327. FC := mysql_num_fields(FMYSQLRES);
  328. for I := 0 to FC-1 do
  329. begin
  330. field := mysql_fetch_field_direct(FMYSQLRES, I);
  331. if MySQLFieldToFieldType(field^.ftype, field^.length, DFT, DFS) then
  332. TFieldDef.Create(FieldDefs, field^.name, DFT, DFS, False, I+1);
  333. end;
  334. finally
  335. if WasClosed then
  336. DoClose;
  337. end;
  338. finally
  339. FLoadingFieldDefs := False;
  340. end;
  341. end;
  342. procedure TMySQLDataset.InternalInitRecord(Buffer: PChar);
  343. begin
  344. FillChar(Buffer^, FBufferSize, 0);
  345. end;
  346. procedure TMySQLDataset.InternalLast;
  347. begin
  348. FCurrentRecord := RecordCount;
  349. end;
  350. procedure TMySQLDataset.InternalOpen;
  351. begin
  352. CheckDatabase;
  353. FMYSQLRES := nil;
  354. try
  355. DoQuery;
  356. DoGetResult;
  357. FCurrentRecord := -1;
  358. InternalInitFieldDefs;
  359. if DefaultFields then
  360. CreateFields;
  361. CalculateSizes;
  362. BindFields(True);
  363. except
  364. DoClose;
  365. raise;
  366. end;
  367. BookMarkSize:=SizeOf(Longint);
  368. end;
  369. procedure TMySQLDataset.InternalSetToRecord(Buffer: PChar);
  370. begin
  371. FCurrentRecord := PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData;
  372. end;
  373. function TMySQLDataset.IsCursorOpen: Boolean;
  374. begin
  375. Result:=(FMYSQLRES<>nil);
  376. end;
  377. procedure TMySQLDataset.SetBookmarkData(Buffer: PChar; Data: Pointer);
  378. begin
  379. PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkData := PInteger(Data)^;
  380. end;
  381. procedure TMySQLDataset.SetBookmarkFlag(Buffer: PChar;
  382. Value: TBookmarkFlag);
  383. begin
  384. PMySQLDatasetBookmark(Buffer + FRecordSize)^.BookmarkFlag := Value;
  385. end;
  386. procedure TMySQLDataset.SetFieldData(Field: TField; Buffer: Pointer);
  387. begin
  388. end;
  389. procedure TMySQLDataset.SetRecNo(Value: Integer);
  390. begin
  391. if (Value >= 0) and (Value <= RecordCount-1) then
  392. begin
  393. FCurrentRecord := Value-1;
  394. Resync([]);
  395. end;
  396. end;
  397. procedure TMySQLDataset.SetSQL(const Value: TStrings);
  398. begin
  399. FSQL.Assign(Value);
  400. FieldDefs.Clear;
  401. end;
  402. procedure TMySQLDataset.ExecSQL;
  403. begin
  404. try
  405. DoQuery;
  406. finally
  407. DoClose;
  408. end;
  409. end;
  410. procedure TMySQLDataset.InternalPost;
  411. begin
  412. end;
  413. function TMySQLDataset.MySQLFieldToFieldType(AType: enum_field_types; ASize: Integer;
  414. var NewType: TFieldType; var NewSize: Integer): Boolean;
  415. begin
  416. Result := True;
  417. case AType of
  418. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  419. FIELD_TYPE_INT24:
  420. begin
  421. NewType := ftInteger;
  422. NewSize := 0;
  423. end;
  424. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  425. begin
  426. NewType := ftFloat;
  427. NewSize := 0;
  428. end;
  429. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  430. begin
  431. NewType := ftDateTime;
  432. NewSize := 0;
  433. end;
  434. FIELD_TYPE_DATE:
  435. begin
  436. NewType := ftDate;
  437. NewSize := 0;
  438. end;
  439. FIELD_TYPE_TIME:
  440. begin
  441. NewType := ftTime;
  442. NewSize := 0;
  443. end;
  444. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  445. begin
  446. NewType := ftString;
  447. NewSize := ASize;
  448. end;
  449. else
  450. Result := False;
  451. end;
  452. end;
  453. procedure TMySQLDataset.CalculateSizes;
  454. var
  455. I, FC: Integer;
  456. field: PMYSQL_FIELD;
  457. begin
  458. FRecordSize := 0;
  459. FC := mysql_num_fields(FMYSQLRES);
  460. for I := 0 to FC-1 do
  461. begin
  462. field := mysql_fetch_field_direct(FMYSQLRES, I);
  463. FRecordSize := FRecordSize + MySQLDataSize(field^.ftype, field^.length);
  464. end;
  465. FBufferSize := FRecordSize + SizeOf(TMySQLDatasetBookmark);
  466. end;
  467. procedure TMySQLDataset.LoadBufferFromData(Buffer: PChar);
  468. var
  469. I, FC, CT: Integer;
  470. field: PMYSQL_FIELD;
  471. row: TMYSQL_ROW;
  472. begin
  473. mysql_data_seek(FMYSQLRES, FCurrentRecord);
  474. row := mysql_fetch_row(FMYSQLRES);
  475. if row = nil then
  476. MySQLError(FMySQL,SErrFetchingData,Self);
  477. FC := mysql_num_fields(FMYSQLRES);
  478. for I := 0 to FC-1 do
  479. begin
  480. field := mysql_fetch_field_direct(FMYSQLRES, I);
  481. CT := MySQLWriteFieldData(field^.ftype, field^.length, row^, Buffer);
  482. Inc(Buffer, CT);
  483. Inc(row);
  484. end;
  485. end;
  486. function TMySQLDataset.MySQLDataSize(AType: enum_field_types;
  487. ASize: Integer): Integer;
  488. begin
  489. Result := 0;
  490. case AType of
  491. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  492. FIELD_TYPE_INT24:
  493. begin
  494. Result := SizeOf(Integer);
  495. end;
  496. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  497. begin
  498. Result := SizeOf(Double);
  499. end;
  500. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATE, FIELD_TYPE_TIME, FIELD_TYPE_DATETIME:
  501. begin
  502. Result := SizeOf(TDateTime);
  503. end;
  504. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  505. begin
  506. Result := ASize;
  507. end;
  508. end;
  509. end;
  510. function TMySQLDataset.MySQLWriteFieldData(AType: enum_field_types;
  511. ASize: Integer; Source, Dest: PChar): Integer;
  512. var
  513. VI: Integer;
  514. VF: Double;
  515. VD: TDateTime;
  516. begin
  517. Result := 0;
  518. case AType of
  519. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG,
  520. FIELD_TYPE_INT24:
  521. begin
  522. Result := SizeOf(Integer);
  523. if Source <> '' then
  524. VI := StrToInt(Source)
  525. else
  526. VI := 0;
  527. Move(VI, Dest^, Result);
  528. end;
  529. FIELD_TYPE_DECIMAL, FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  530. begin
  531. Result := SizeOf(Double);
  532. if Source <> '' then
  533. VF := InternalStrToFloat(Source)
  534. else
  535. VF := 0;
  536. Move(VF, Dest^, Result);
  537. end;
  538. FIELD_TYPE_TIMESTAMP:
  539. begin
  540. Result := SizeOf(TDateTime);
  541. if Source <> '' then
  542. VD := InternalStrToTimeStamp(Source)
  543. else
  544. VD := 0;
  545. Move(VD, Dest^, Result);
  546. end;
  547. FIELD_TYPE_DATETIME:
  548. begin
  549. Result := SizeOf(TDateTime);
  550. if Source <> '' then
  551. VD := InternalStrToDateTime(Source)
  552. else
  553. VD := 0;
  554. Move(VD, Dest^, Result);
  555. end;
  556. FIELD_TYPE_DATE:
  557. begin
  558. Result := SizeOf(TDateTime);
  559. if Source <> '' then
  560. VD := InternalStrToDate(Source)
  561. else
  562. VD := 0;
  563. Move(VD, Dest^, Result);
  564. end;
  565. FIELD_TYPE_TIME:
  566. begin
  567. Result := SizeOf(TDateTime);
  568. if Source <> '' then
  569. VD := InternalStrToTime(Source)
  570. else
  571. VD := 0;
  572. Move(VD, Dest^, Result);
  573. end;
  574. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  575. begin
  576. Result := ASize;
  577. if Source <> '' then
  578. Move(Source^, Dest^, Result)
  579. else
  580. Dest^ := #0;
  581. end;
  582. end;
  583. end;
  584. function TMySQLDataset.InternalStrToFloat(S: string): Extended;
  585. var
  586. I: Integer;
  587. Tmp: string;
  588. begin
  589. Tmp := '';
  590. for I := 1 to Length(S) do
  591. begin
  592. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  593. Tmp := Tmp + DecimalSeparator
  594. else
  595. Tmp := Tmp + S[I];
  596. end;
  597. Result := StrToFloat(Tmp);
  598. end;
  599. function TMySQLDataset.InternalStrToDate(S: string): TDateTime;
  600. var
  601. EY, EM, ED: Word;
  602. begin
  603. EY := StrToInt(Copy(S,1,4));
  604. EM := StrToInt(Copy(S,6,2));
  605. ED := StrToInt(Copy(S,9,2));
  606. if (EY = 0) or (EM = 0) or (ED = 0) then
  607. Result:=0
  608. else
  609. Result:=EncodeDate(EY, EM, ED);
  610. end;
  611. function TMySQLDataset.InternalStrToDateTime(S: string): TDateTime;
  612. var
  613. EY, EM, ED: Word;
  614. EH, EN, ES: Word;
  615. begin
  616. EY := StrToInt(Copy(S, 1, 4));
  617. EM := StrToInt(Copy(S, 6, 2));
  618. ED := StrToInt(Copy(S, 9, 2));
  619. EH := StrToInt(Copy(S, 11, 2));
  620. EN := StrToInt(Copy(S, 14, 2));
  621. ES := StrToInt(Copy(S, 17, 2));
  622. if (EY = 0) or (EM = 0) or (ED = 0) then
  623. Result := 0
  624. else
  625. Result := EncodeDate(EY, EM, ED);
  626. Result := Result + EncodeTime(EH, EN, ES, 0);
  627. end;
  628. function TMySQLDataset.InternalStrToTime(S: string): TDateTime;
  629. var
  630. EH, EM, ES: Word;
  631. begin
  632. EH := StrToInt(Copy(S, 1, 2));
  633. EM := StrToInt(Copy(S, 4, 2));
  634. ES := StrToInt(Copy(S, 7, 2));
  635. Result := EncodeTime(EH, EM, ES, 0);
  636. end;
  637. function TMySQLDataset.InternalStrToTimeStamp(S: string): TDateTime;
  638. var
  639. EY, EM, ED: Word;
  640. EH, EN, ES: Word;
  641. begin
  642. EY := StrToInt(Copy(S, 1, 4));
  643. EM := StrToInt(Copy(S, 5, 2));
  644. ED := StrToInt(Copy(S, 7, 2));
  645. EH := StrToInt(Copy(S, 9, 2));
  646. EN := StrToInt(Copy(S, 11, 2));
  647. ES := StrToInt(Copy(S, 13, 2));
  648. if (EY = 0) or (EM = 0) or (ED = 0) then
  649. Result := 0
  650. else
  651. Result := EncodeDate(EY, EM, ED);
  652. Result := Result + EncodeTime(EH, EN, ES, 0);;
  653. end;
  654. procedure TMySQLDataset.DoClose;
  655. begin
  656. try
  657. if FMYSQLRES <> nil then
  658. mysql_free_result(FMYSQLRES);
  659. finally
  660. FMYSQLRES := nil;
  661. end;
  662. end;
  663. procedure TMySQLDataset.DoQuery;
  664. var
  665. Query: PChar;
  666. begin
  667. Query := FSQL.GetText;
  668. try
  669. if mysql_query(FMySQL,Query) <> 0 then
  670. MySQLError(FMYSQL,SErrExecuting,Self);
  671. finally
  672. StrDispose(Query);
  673. end;
  674. FAffectedRows := mysql_affected_rows(FMYSQL);
  675. FLastInsertID := mysql_insert_id(FMYSQL);
  676. end;
  677. function TMySQLDataset.GetCanModify: Boolean;
  678. begin
  679. Result := False;
  680. end;
  681. procedure TMySQLDataset.DoGetResult;
  682. begin
  683. FMYSQLRES := mysql_store_result(FMYSQL);
  684. if (FMYSQLRES=nil) then
  685. MySQLError(FMYSQL,SErrGettingResult,Self);
  686. FAffectedRows := mysql_affected_rows(FMYSQL);
  687. end;
  688. function TMySQLDataset.FMySQL: PMySQL;
  689. begin
  690. Result:=(Database as TMySQLDatabase).FMySQL;
  691. end;
  692. { TMySQLDatabase }
  693. function TMySQLDatabase.GetUserName: String;
  694. begin
  695. result:=Params.values['UserName'];
  696. end;
  697. function TMySQLDatabase.GetHostName: String;
  698. begin
  699. Result:=Params.Values['HostName'];
  700. end;
  701. procedure TMySQLDatabase.SetHostName(const AValue: String);
  702. begin
  703. Params.Values['HostName']:=AValue;
  704. end;
  705. procedure TMySQLDatabase.SetUserName(Value: String);
  706. begin
  707. Params.Values['UserName']:=Value;
  708. end;
  709. procedure TMySQLDatabase.SetPassword(Value: String);
  710. begin
  711. Params.Values['Password']:=Value;
  712. end;
  713. function TMySQLDatabase.GetPassword: String;
  714. begin
  715. Result:=Params.Values['Password'];
  716. end;
  717. function TMySQLDatabase.GetClientInfo: String;
  718. begin
  719. Result:=strpas(mysql_get_client_info);
  720. end;
  721. procedure TMySQLDatabase.ConnectToServer;
  722. Var
  723. H,U,P : String;
  724. begin
  725. if (FMySQL=Nil) then
  726. New(FMySQL);
  727. H:=HostName;
  728. U:=UserName;
  729. P:=Password;
  730. mysql_init(FMySQL);
  731. FMySQL:=mysql_real_connect(FMySQL,PChar(H),PChar(U),Pchar(P),Nil,0,Nil,0);
  732. If (FMySQL=Nil) then
  733. MySQlError(Nil,SErrServerConnectFailed,Self);
  734. FServerInfo := strpas(mysql_get_server_info(FMYSQL));
  735. FHostInfo := strpas(mysql_get_host_info(FMYSQL));
  736. end;
  737. procedure TMySQLDatabase.SelectDatabase;
  738. begin
  739. if mysql_select_db(FMySQL,pchar(DatabaseName))<>0 then
  740. MySQLError(FMySQL,SErrDatabaseSelectFailed,Self);
  741. end;
  742. procedure TMySQLDatabase.DoInternalConnect;
  743. begin
  744. if (FMySQL<>nil) then
  745. DoInternalDisconnect;
  746. ConnectToServer;
  747. SelectDatabase;
  748. end;
  749. procedure TMySQLDatabase.DoInternalDisConnect;
  750. begin
  751. mysql_close(FMySQL);
  752. FMySQL:=Nil;
  753. FServerInfo:='';
  754. FHostInfo:='';
  755. end;
  756. procedure TMySQLDatabase.StartTransaction;
  757. begin
  758. // Nothing yet
  759. end;
  760. procedure TMySQLDatabase.EndTransaction;
  761. begin
  762. // Nothing yet
  763. end;
  764. procedure TMySQLDatabase.CreateDatabase;
  765. Var
  766. Disconnect : Boolean;
  767. begin
  768. Disconnect:=(FMySQL=Nil);
  769. if Disconnect then
  770. ConnectToServer;
  771. try
  772. {if mysql_create_db(FMySQL,Pchar(DatabaseName))<>0 then
  773. MySQLError(FMySQL,SErrDatabaseCreate,Self);}
  774. Finally
  775. If Disconnect then
  776. DoInternalDisconnect;
  777. end;
  778. end;
  779. procedure TMySQLDatabase.DropDatabase;
  780. Var
  781. Disconnect : Boolean;
  782. begin
  783. Disconnect:=(FMySQL=Nil);
  784. if Disconnect then
  785. ConnectToServer;
  786. If (FMySQL=Nil) then
  787. ConnectToServer;
  788. try
  789. {
  790. if mysql_drop_db(FMySQL,Pchar(DatabaseName))<>0 then
  791. MySQLError(FMySQL,SErrDatabaseDrop,Self);
  792. }
  793. Finally
  794. If Disconnect then
  795. DoInternalDisconnect;
  796. end;
  797. end;
  798. function TMySQLDatabase.GetServerStatus: string;
  799. begin
  800. CheckConnected;
  801. Result := mysql_stat(FMYSQL);
  802. end;
  803. end.
  804. {
  805. $Log$
  806. Revision 1.1 2004-09-30 19:36:00 michael
  807. + Split out in version 3 and 4
  808. Revision 1.6 2004/09/29 20:26:48 michael
  809. + Adapted to version 4 of mysql
  810. Revision 1.5 2004/09/20 07:13:38 michael
  811. + Database property published
  812. Revision 1.4 2003/08/16 16:42:21 michael
  813. + Fixes in TDBDataset etc. Changed MySQLDb to use database as well
  814. Revision 1.3 2002/11/07 14:27:59 sg
  815. * AffectedRows now is a QWord (to match recent MySQL versions)
  816. * Result strings for enums etc. are now correctly terminated
  817. * Fixed a memory leak in DoQuery: The query string didn't get released
  818. Revision 1.2 2002/09/07 15:15:23 peter
  819. * old logs removed and tabs fixed
  820. }