mysqlconn.inc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  1. {$IFDEF MYSQL56_UP}
  2. {$DEFINE MYSQL55_UP}
  3. {$ENDIF}
  4. {$IFDEF MYSQL55_UP}
  5. {$DEFINE MYSQL51_UP}
  6. {$ENDIF}
  7. {$IFDEF MYSQL51_UP}
  8. {$DEFINE MYSQL50_UP}
  9. {$ENDIF}
  10. {$mode objfpc}{$H+}
  11. interface
  12. uses
  13. Classes, SysUtils,bufdataset,sqldb,db,ctypes,
  14. {$IFDEF mysql56}
  15. mysql56dyn;
  16. {$ELSE}
  17. {$IFDEF mysql55}
  18. mysql55dyn;
  19. {$ELSE}
  20. {$IFDEF mysql51}
  21. mysql51dyn;
  22. {$ELSE}
  23. {$IfDef mysql50}
  24. mysql50dyn;
  25. {$ELSE}
  26. {$IfDef mysql41}
  27. mysql41dyn;
  28. {$ELSE}
  29. mysql40dyn;
  30. {$EndIf}
  31. {$EndIf}
  32. {$endif}
  33. {$endif}
  34. {$ENDIF}
  35. Const
  36. MySQLVersion =
  37. {$IFDEF mysql56}
  38. '5.6';
  39. {$ELSE}
  40. {$IFDEF mysql55}
  41. '5.5';
  42. {$ELSE}
  43. {$IFDEF mysql51}
  44. '5.1';
  45. {$else}
  46. {$IfDef mysql50}
  47. '5.0';
  48. {$ELSE}
  49. {$IfDef mysql41}
  50. '4.1';
  51. {$ELSE}
  52. '4.0';
  53. {$EndIf}
  54. {$EndIf}
  55. {$endif}
  56. {$endif}
  57. {$ENDIF}
  58. MariaDBVersion =
  59. {$IFDEF mysql56} // MariaDB 10.0 is compatible with MySQL 5.6
  60. '10.0';
  61. {$ELSE} // MariaDB 5.1..5.5 presumably report the same version number as MySQL
  62. MySQLVersion;
  63. {$ENDIF}
  64. Type
  65. TTransactionName = Class(TSQLHandle)
  66. protected
  67. end;
  68. { TCursorName }
  69. TCursorName = Class(TSQLCursor)
  70. protected
  71. FRes: PMYSQL_RES; { Record pointer }
  72. FStatement : String;
  73. Row : MYSQL_ROW;
  74. Lengths : pculong; { Lengths of the columns of the current row }
  75. RowsAffected : QWord;
  76. LastInsertID : QWord;
  77. ParamBinding : TParamBinding;
  78. ParamReplaceString : String;
  79. MapDSRowToMSQLRow : array of integer;
  80. end;
  81. { TConnectionName }
  82. TConnectionName = class (TSQLConnection)
  83. private
  84. FHostInfo: String;
  85. FServerInfo: String;
  86. FMySQL : PMySQL;
  87. function GetClientInfo: string;
  88. function GetServerStatus: String;
  89. procedure ConnectMySQL(var HMySQL: PMySQL);
  90. procedure ExecuteDirectMySQL(const query : string);
  91. function EscapeString(const Str : string) : string;
  92. protected
  93. function StrToStatementType(s : string) : TStatementType; override;
  94. Procedure ConnectToServer; virtual;
  95. Procedure SelectDatabase; virtual;
  96. function MySQLDataType(AField: PMYSQL_FIELD; var NewType: TFieldType; var NewSize: Integer): Boolean;
  97. function MySQLWriteData(AField: PMYSQL_FIELD; FieldDef: TFieldDef; Source, Dest: PChar; Len: integer; out CreateBlob : boolean): Boolean;
  98. // SQLConnection methods
  99. procedure DoInternalConnect; override;
  100. procedure DoInternalDisconnect; override;
  101. function GetHandle : pointer; override;
  102. function GetAsSQLText(Field : TField) : string; overload; override;
  103. function GetAsSQLText(Param : TParam) : string; overload; override;
  104. Function AllocateCursorHandle : TSQLCursor; override;
  105. Procedure DeAllocateCursorHandle(var cursor : TSQLCursor); override;
  106. Function AllocateTransactionHandle : TSQLHandle; override;
  107. procedure PrepareStatement(cursor: TSQLCursor;ATransaction : TSQLTransaction;buf : string; AParams : TParams); override;
  108. procedure UnPrepareStatement(cursor:TSQLCursor); override;
  109. procedure FreeFldBuffers(cursor : TSQLCursor); override;
  110. procedure Execute(cursor: TSQLCursor;atransaction:tSQLtransaction;AParams : TParams); override;
  111. procedure AddFieldDefs(cursor: TSQLCursor; FieldDefs : TfieldDefs); override;
  112. function Fetch(cursor : TSQLCursor) : boolean; override;
  113. function LoadField(cursor : TSQLCursor;FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean; override;
  114. procedure LoadBlobIntoBuffer(FieldDef: TFieldDef;ABlobBuf: PBufBlobField; cursor: TSQLCursor;ATransaction : TSQLTransaction); override;
  115. function GetTransactionHandle(trans : TSQLHandle): pointer; override;
  116. function Commit(trans : TSQLHandle) : boolean; override;
  117. function RollBack(trans : TSQLHandle) : boolean; override;
  118. function StartdbTransaction(trans : TSQLHandle; AParams : string) : boolean; override;
  119. procedure CommitRetaining(trans : TSQLHandle); override;
  120. procedure RollBackRetaining(trans : TSQLHandle); override;
  121. function GetSchemaInfoSQL(SchemaType : TSchemaType; SchemaObjectName, SchemaPattern : string) : string; override;
  122. procedure UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string); override;
  123. function RowsAffected(cursor: TSQLCursor): TRowsCount; override;
  124. Public
  125. constructor Create(AOwner : TComponent); override;
  126. procedure GetFieldNames(const TableName : string; List : TStrings); override;
  127. procedure GetTableNames(List : TStrings; SystemTables : Boolean = false); override;
  128. function GetConnectionInfo(InfoType:TConnInfoType): string; override;
  129. Function GetInsertID: int64;
  130. procedure CreateDB; override;
  131. procedure DropDB; override;
  132. Property ServerInfo : String Read FServerInfo;
  133. Property HostInfo : String Read FHostInfo;
  134. property ClientInfo: string read GetClientInfo;
  135. property ServerStatus : String read GetServerStatus;
  136. published
  137. property DatabaseName;
  138. property HostName;
  139. property KeepConnection;
  140. property LoginPrompt;
  141. property Params;
  142. property Port stored false;
  143. property OnLogin;
  144. end;
  145. { TMySQLConnectionDef }
  146. TMySQLConnectionDef = Class(TConnectionDef)
  147. Class Function TypeName : String; override;
  148. Class Function ConnectionClass : TSQLConnectionClass; override;
  149. Class Function Description : String; override;
  150. Class Function DefaultLibraryName : String; override;
  151. Class Function LoadFunction : TLibraryLoadFunction; override;
  152. Class Function UnLoadFunction : TLibraryUnLoadFunction; override;
  153. Class Function LoadedLibraryName : string; override;
  154. end;
  155. {$IFDEF mysql56}
  156. TMySQL56Connection = Class(TConnectionName);
  157. TMySQL56ConnectionDef = Class(TMySQLConnectionDef);
  158. TMySQL56Transaction = Class(TTransactionName);
  159. TMySQL56Cursor = Class(TCursorName);
  160. {$ELSE}
  161. {$ifdef mysql55}
  162. TMySQL55Connection = Class(TConnectionName);
  163. TMySQL55ConnectionDef = Class(TMySQLConnectionDef);
  164. TMySQL55Transaction = Class(TTransactionName);
  165. TMySQL55Cursor = Class(TCursorName);
  166. {$else}
  167. {$IfDef mysql51}
  168. TMySQL51Connection = Class(TConnectionName);
  169. TMySQL51ConnectionDef = Class(TMySQLConnectionDef);
  170. TMySQL51Transaction = Class(TTransactionName);
  171. TMySQL51Cursor = Class(TCursorName);
  172. {$ELSE}
  173. {$IfDef mysql50}
  174. TMySQL50Connection = Class(TConnectionName);
  175. TMySQL50ConnectionDef = Class(TMySQLConnectionDef);
  176. TMySQL50Transaction = Class(TTransactionName);
  177. TMySQL50Cursor = Class(TCursorName);
  178. {$ELSE}
  179. {$IfDef mysql41}
  180. TMySQL41Connection = Class(TConnectionName);
  181. TMySQL41ConnectionDef = Class(TMySQLConnectionDef);
  182. TMySQL41Transaction = Class(TTransactionName);
  183. TMySQL41Cursor = Class(TCursorName);
  184. {$ELSE}
  185. TMySQL40Connection = Class(TConnectionName);
  186. TMySQL40ConnectionDef = Class(TMySQLConnectionDef);
  187. TMySQL40Transaction = Class(TTransactionName);
  188. TMySQL40Cursor = Class(TCursorName);
  189. {$EndIf}
  190. {$endif}
  191. {$EndIf}
  192. {$ENDIF}
  193. {$ENDIF}
  194. implementation
  195. uses
  196. dbconst,
  197. strutils,
  198. dateutils,
  199. FmtBCD;
  200. const
  201. Mysql_Option_Names : array[mysql_option] of string = ('MYSQL_OPT_CONNECT_TIMEOUT','MYSQL_OPT_COMPRESS',
  202. 'MYSQL_OPT_NAMED_PIPE','MYSQL_INIT_COMMAND',
  203. 'MYSQL_READ_DEFAULT_FILE','MYSQL_READ_DEFAULT_GROUP',
  204. 'MYSQL_SET_CHARSET_DIR','MYSQL_SET_CHARSET_NAME',
  205. 'MYSQL_OPT_LOCAL_INFILE','MYSQL_OPT_PROTOCOL',
  206. 'MYSQL_SHARED_MEMORY_BASE_NAME','MYSQL_OPT_READ_TIMEOUT',
  207. 'MYSQL_OPT_WRITE_TIMEOUT','MYSQL_OPT_USE_RESULT',
  208. 'MYSQL_OPT_USE_REMOTE_CONNECTION','MYSQL_OPT_USE_EMBEDDED_CONNECTION',
  209. 'MYSQL_OPT_GUESS_CONNECTION','MYSQL_SET_CLIENT_IP',
  210. 'MYSQL_SECURE_AUTH'
  211. {$IFDEF MYSQL50_UP}
  212. ,'MYSQL_REPORT_DATA_TRUNCATION', 'MYSQL_OPT_RECONNECT'
  213. {$IFDEF mysql51_UP}
  214. ,'MYSQL_OPT_SSL_VERIFY_SERVER_CERT'
  215. {$IFDEF mysql55_UP}
  216. ,'MYSQL_PLUGIN_DIR', 'MYSQL_DEFAULT_AUTH'
  217. {$IFDEF MYSQL56_UP}
  218. ,'MYSQL_OPT_BIND'
  219. ,'MYSQL_OPT_SSL_KEY', 'MYSQL_OPT_SSL_CERT', 'MYSQL_OPT_SSL_CA', 'MYSQL_OPT_SSL_CAPATH', 'MYSQL_OPT_SSL_CIPHER', 'MYSQL_OPT_SSL_CRL', 'MYSQL_OPT_SSL_CRLPATH'
  220. ,'MYSQL_OPT_CONNECT_ATTR_RESET', 'MYSQL_OPT_CONNECT_ATTR_ADD', 'MYSQL_OPT_CONNECT_ATTR_DELETE'
  221. ,'MYSQL_SERVER_PUBLIC_KEY'
  222. ,'MYSQL_ENABLE_CLEARTEXT_PLUGIN'
  223. ,'MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS'
  224. {$ENDIF}
  225. {$ENDIF}
  226. {$ENDIF}
  227. {$ENDIF}
  228. );
  229. Resourcestring
  230. SErrServerConnectFailed = 'Server connect failed.';
  231. SErrSetCharsetFailed = 'Failed to set connection character set: %s';
  232. SErrDatabaseSelectFailed = 'Failed to select database: %s';
  233. SErrDatabaseCreate = 'Failed to create database: %s';
  234. SErrDatabaseDrop = 'Failed to drop database: %s';
  235. SErrNoData = 'No data for record';
  236. SErrExecuting = 'Error executing query: %s';
  237. SErrFetchingdata = 'Error fetching row data: %s';
  238. SErrGettingResult = 'Error getting result set: %s';
  239. SErrNoQueryResult = 'No result from query.';
  240. SErrVersionMismatch = '%s can not work with the installed MySQL client version: Expected (%s), got (%s).';
  241. SErrSettingParameter = 'Error setting parameter "%s"';
  242. Procedure MySQLError(R : PMySQL; Msg: String; Comp : TComponent);
  243. Var
  244. MySQLError, MySQLState : String;
  245. MySQLErrno: integer;
  246. begin
  247. If (R<>Nil) then
  248. begin
  249. MySQLError:=StrPas(mysql_error(R));
  250. MySQLErrno:=mysql_errno(R);
  251. MySQLState:=StrPas(mysql_sqlstate(R));
  252. end
  253. else
  254. begin
  255. MySQLError:='';
  256. MySQLErrno:=0;
  257. MySQLState:='';
  258. end;
  259. raise ESQLDatabaseError.CreateFmt(Msg, [MySQLError], Comp, MySQLErrno, MySQLState);
  260. end;
  261. function MysqlOption(const OptionName: string; out AMysql_Option: mysql_option) : boolean;
  262. var AMysql_Option_i: mysql_option;
  263. begin
  264. result := false;
  265. for AMysql_Option_i:=low(AMysql_Option) to high(AMysql_Option) do
  266. if sametext(Mysql_Option_Names[AMysql_Option_i],OptionName) then
  267. begin
  268. result := true;
  269. AMysql_Option:=AMysql_Option_i;
  270. break;
  271. end;
  272. end;
  273. { TConnectionName }
  274. function TConnectionName.StrToStatementType(s : string) : TStatementType;
  275. begin
  276. s:=Lowercase(s);
  277. if (s='analyze') or (s='check') or (s='checksum') or (s='optimize') or (s='repair') or (s='show') then
  278. exit(stSelect)
  279. else if s='call' then
  280. exit(stExecProcedure)
  281. else
  282. Result := inherited StrToStatementType(s);
  283. end;
  284. function TConnectionName.GetClientInfo: string;
  285. begin
  286. // To make it possible to call this if there's no connection yet
  287. InitialiseMysql;
  288. Try
  289. Result:=strpas(mysql_get_client_info());
  290. Finally
  291. ReleaseMysql;
  292. end;
  293. end;
  294. function TConnectionName.GetServerStatus: String;
  295. begin
  296. CheckConnected;
  297. Result := mysql_stat(FMYSQL);
  298. end;
  299. function TConnectionName.GetInsertID: Int64;
  300. begin
  301. CheckConnected;
  302. Result:=mysql_insert_id(GetHandle);
  303. end;
  304. procedure TConnectionName.ConnectMySQL(var HMySQL: PMySQL);
  305. Var
  306. APort : Cardinal;
  307. i,e: integer;
  308. AMysql_Option: mysql_option;
  309. OptStr: string;
  310. OptInt: cuint;
  311. Opt: pointer;
  312. begin
  313. HMySQL := mysql_init(HMySQL);
  314. APort:=Abs(StrToIntDef(Params.Values['Port'],0));
  315. for i := 0 to Params.Count-1 do
  316. begin
  317. if MysqlOption(Params.Names[i],AMysql_Option) then
  318. begin
  319. OptStr:=Params.ValueFromIndex[i];
  320. val(OptStr,OptInt,e);
  321. if e=0 then
  322. Opt := @OptInt
  323. else
  324. Opt := pchar(OptStr);
  325. if mysql_options(HMySQL,AMysql_Option,Opt) <> 0 then
  326. MySQLError(HMySQL,Format(SErrSettingParameter,[Params.Names[i]]),Self);
  327. end;
  328. end;
  329. HMySQL:=mysql_real_connect(HMySQL,PChar(HostName),PChar(UserName),PChar(Password),Nil,APort,Nil,CLIENT_MULTI_RESULTS); //CLIENT_MULTI_RESULTS is required by CALL SQL statement(executes stored procedure), that produces result sets
  330. If (HMySQL=Nil) then
  331. MySQLError(Nil,SErrServerConnectFailed,Self);
  332. if (trim(CharSet) <> '') then
  333. // major_version*10000 + minor_version *100 + sub_version
  334. if (50007 <= mysql_get_server_version(HMySQL)) then
  335. begin
  336. // Only available for MySQL 5.0.7 and later...
  337. if mysql_set_character_set(HMySQL, PChar(CharSet)) <> 0 then
  338. MySQLError(HMySQL,SErrSetCharsetFailed,Self);
  339. end
  340. else
  341. if mysql_query(HMySQL,PChar('SET NAMES ''' + EscapeString(CharSet) +'''')) <> 0 then
  342. MySQLError(HMySQL,SErrExecuting,Self);
  343. end;
  344. function TConnectionName.GetAsSQLText(Field : TField) : string;
  345. begin
  346. if (not assigned(Field)) or Field.IsNull then
  347. Result := 'Null'
  348. else if Field.DataType = ftString then
  349. Result := '''' + EscapeString(Field.AsString) + ''''
  350. else
  351. Result := inherited GetAsSqlText(Field);
  352. end;
  353. function TConnectionName.GetAsSQLText(Param: TParam) : string;
  354. begin
  355. if (not assigned(Param)) or Param.IsNull then
  356. Result := 'Null'
  357. else if Param.DataType in [ftString,ftFixedChar,ftBlob,ftMemo,ftBytes,ftVarBytes] then
  358. Result := '''' + EscapeString(Param.AsString) + ''''
  359. else
  360. Result := inherited GetAsSqlText(Param);
  361. end;
  362. procedure TConnectionName.ConnectToServer;
  363. begin
  364. ConnectMySQL(FMySQL);
  365. FServerInfo := strpas(mysql_get_server_info(FMYSQL));
  366. FHostInfo := strpas(mysql_get_host_info(FMYSQL));
  367. end;
  368. procedure TConnectionName.SelectDatabase;
  369. begin
  370. if mysql_select_db(FMySQL,pchar(DatabaseName))<>0 then
  371. MySQLError(FMySQL,SErrDatabaseSelectFailed,Self);
  372. end;
  373. procedure TConnectionName.CreateDB;
  374. begin
  375. ExecuteDirectMySQL('CREATE DATABASE ' +DatabaseName);
  376. end;
  377. procedure TConnectionName.DropDB;
  378. begin
  379. ExecuteDirectMySQL('DROP DATABASE ' +DatabaseName);
  380. end;
  381. procedure TConnectionName.ExecuteDirectMySQL(const query : string);
  382. var AMySQL : PMySQL;
  383. begin
  384. CheckDisConnected;
  385. InitialiseMysql;
  386. try
  387. AMySQL := nil;
  388. ConnectMySQL(AMySQL);
  389. try
  390. if mysql_query(AMySQL,pchar(query))<>0 then
  391. MySQLError(AMySQL,SErrExecuting,Self);
  392. finally
  393. mysql_close(AMySQL);
  394. end;
  395. finally
  396. ReleaseMysql;
  397. end;
  398. end;
  399. function TConnectionName.EscapeString(const Str: string): string;
  400. var Len : integer;
  401. begin
  402. SetLength(result,length(str)*2+1);
  403. Len := mysql_real_escape_string(FMySQL,pchar(Result),pchar(Str),length(Str));
  404. SetLength(result,Len);
  405. end;
  406. procedure TConnectionName.DoInternalConnect;
  407. var
  408. FullVersion: string;
  409. begin
  410. InitialiseMysql;
  411. Fullversion:=strpas(mysql_get_client_info());
  412. // Version string should start with version number:
  413. // Note: in case of MariaDB version mismatch: tough luck, we report MySQL
  414. // version only.
  415. if (pos(MySQLVersion, Fullversion) <> 1) and
  416. (pos(MariaDBVersion, Fullversion) <> 1) then
  417. Raise EInOutError.CreateFmt(SErrVersionMisMatch,[ClassName,MySQLVersion,FullVersion]);
  418. inherited DoInternalConnect;
  419. ConnectToServer;
  420. SelectDatabase;
  421. end;
  422. procedure TConnectionName.DoInternalDisconnect;
  423. begin
  424. inherited DoInternalDisconnect;
  425. mysql_close(FMySQL);
  426. FMySQL:=Nil;
  427. ReleaseMysql;
  428. end;
  429. function TConnectionName.GetHandle: pointer;
  430. begin
  431. Result:=FMySQL;
  432. end;
  433. function TConnectionName.AllocateCursorHandle: TSQLCursor;
  434. begin
  435. {$IFDEF mysql56}
  436. Result:=TMySQL56Cursor.Create;
  437. {$ELSE}
  438. {$IfDef mysql55}
  439. Result:=TMySQL55Cursor.Create;
  440. {$ELSE}
  441. {$IfDef mysql51}
  442. Result:=TMySQL51Cursor.Create;
  443. {$ELSE}
  444. {$IfDef mysql50}
  445. Result:=TMySQL50Cursor.Create;
  446. {$ELSE}
  447. {$IfDef mysql41}
  448. Result:=TMySQL41Cursor.Create;
  449. {$ELSE}
  450. Result:=TMySQL40Cursor.Create;
  451. {$EndIf}
  452. {$EndIf}
  453. {$EndIf}
  454. {$EndIf}
  455. {$ENDIF}
  456. end;
  457. Procedure TConnectionName.DeAllocateCursorHandle(var cursor : TSQLCursor);
  458. begin
  459. FreeAndNil(cursor);
  460. end;
  461. function TConnectionName.AllocateTransactionHandle: TSQLHandle;
  462. begin
  463. // Result:=TTransactionName.Create;
  464. Result := nil;
  465. end;
  466. procedure TConnectionName.PrepareStatement(cursor: TSQLCursor;
  467. ATransaction: TSQLTransaction; buf: string;AParams : TParams);
  468. begin
  469. // if assigned(AParams) and (AParams.count > 0) then
  470. // DatabaseError('Parameters (not) yet supported for the MySQL SqlDB connection.',self);
  471. With Cursor as TCursorName do
  472. begin
  473. FStatement:=Buf;
  474. if assigned(AParams) and (AParams.count > 0) then
  475. FStatement := AParams.ParseSQL(FStatement,false,sqEscapeSlash in ConnOptions, sqEscapeRepeat in ConnOptions,psSimulated,paramBinding,ParamReplaceString);
  476. end
  477. end;
  478. procedure TConnectionName.UnPrepareStatement(cursor: TSQLCursor);
  479. Var
  480. C : TCursorName;
  481. begin
  482. C:=Cursor as TCursorName;
  483. if assigned(C.FRes) then //ExecSQL with dataset returned
  484. begin
  485. mysql_free_result(C.FRes);
  486. C.FRes:=nil;
  487. end;
  488. end;
  489. procedure TConnectionName.FreeFldBuffers(cursor: TSQLCursor);
  490. Var
  491. C : TCursorName;
  492. begin
  493. C:=Cursor as TCursorName;
  494. if assigned(C.FRes) then
  495. begin
  496. mysql_free_result(C.FRes);
  497. C.FRes:=Nil;
  498. end;
  499. SetLength(c.MapDSRowToMSQLRow,0);
  500. inherited;
  501. end;
  502. procedure TConnectionName.Execute(cursor: TSQLCursor;
  503. atransaction: tSQLtransaction;AParams : TParams);
  504. Var
  505. C : TCursorName;
  506. i : integer;
  507. ParamNames,ParamValues : array of string;
  508. Res: PMYSQL_RES;
  509. begin
  510. C:=Cursor as TCursorName;
  511. If (C.FRes=Nil) then
  512. begin
  513. if Assigned(AParams) and (AParams.count > 0) then
  514. begin
  515. setlength(ParamNames,AParams.Count);
  516. setlength(ParamValues,AParams.Count);
  517. for i := 0 to AParams.count -1 do
  518. begin
  519. ParamNames[AParams.count-i-1] := C.ParamReplaceString+inttostr(AParams[i].Index+1);
  520. ParamValues[AParams.count-i-1] := GetAsSQLText(AParams[i]);
  521. end;
  522. // paramreplacestring kan een probleem geven bij postgres als hij niet meer gewoon $ is?
  523. C.FStatement := stringsreplace(C.FStatement,ParamNames,ParamValues,[rfReplaceAll]);
  524. end;
  525. Log(detExecute, C.FStatement);
  526. if mysql_query(FMySQL,Pchar(C.FStatement))<>0 then
  527. begin
  528. if not ForcedClose then
  529. MySQLError(FMYSQL,SErrExecuting,Self)
  530. else //don't return a resulset. We are shutting down, not opening.
  531. begin
  532. C.RowsAffected:=0;
  533. C.FSelectable:= False;
  534. C.FRes:=nil;
  535. end;
  536. end
  537. else
  538. begin
  539. C.RowsAffected := mysql_affected_rows(FMYSQL);
  540. C.LastInsertID := mysql_insert_id(FMYSQL);
  541. C.FSelectable := False;
  542. repeat
  543. Res:=mysql_store_result(FMySQL); //returns a null pointer also if the statement didn't return a result set
  544. if mysql_errno(FMySQL)<>0 then
  545. begin
  546. if not ForcedClose then
  547. MySQLError(FMySQL, SErrGettingResult, Self)
  548. else
  549. begin
  550. C.RowsAffected:=0;
  551. C.FSelectable:= False;
  552. C.FRes:=nil;
  553. break;
  554. end;
  555. end;
  556. if Res<>nil then
  557. begin
  558. mysql_free_result(C.FRes);
  559. C.FRes:=Res;
  560. C.FSelectable:=True;
  561. end;
  562. until mysql_next_result(FMySQL)<>0;
  563. end;
  564. end;
  565. end;
  566. function TConnectionName.MySQLDataType(AField: PMYSQL_FIELD; var NewType: TFieldType; var NewSize: Integer): Boolean;
  567. var ASize, ADecimals: integer;
  568. begin
  569. Result := True;
  570. ASize := AField^.length;
  571. NewSize := 0;
  572. case AField^.ftype of
  573. FIELD_TYPE_LONGLONG:
  574. begin
  575. NewType := ftLargeint;
  576. end;
  577. FIELD_TYPE_TINY, FIELD_TYPE_SHORT, FIELD_TYPE_YEAR:
  578. begin
  579. if AField^.flags and UNSIGNED_FLAG <> 0 then
  580. NewType := ftWord
  581. else
  582. NewType := ftSmallint;
  583. end;
  584. FIELD_TYPE_LONG, FIELD_TYPE_INT24:
  585. begin
  586. if AField^.flags and AUTO_INCREMENT_FLAG <> 0 then
  587. NewType := ftAutoInc
  588. else
  589. NewType := ftInteger;
  590. end;
  591. {$ifdef mysql50_up}
  592. FIELD_TYPE_NEWDECIMAL,
  593. {$endif}
  594. FIELD_TYPE_DECIMAL:
  595. begin
  596. ADecimals:=AField^.decimals;
  597. if (ADecimals < 5) and (ASize-2-ADecimals < 15) then //ASize is display size i.e. with sign and decimal point
  598. NewType := ftBCD
  599. else if (ADecimals = 0) and (ASize < 20) then
  600. NewType := ftLargeInt
  601. else
  602. NewType := ftFmtBCD;
  603. NewSize := ADecimals;
  604. end;
  605. FIELD_TYPE_FLOAT, FIELD_TYPE_DOUBLE:
  606. begin
  607. NewType := ftFloat;
  608. end;
  609. FIELD_TYPE_TIMESTAMP, FIELD_TYPE_DATETIME:
  610. begin
  611. NewType := ftDateTime;
  612. end;
  613. FIELD_TYPE_DATE:
  614. begin
  615. NewType := ftDate;
  616. end;
  617. FIELD_TYPE_TIME:
  618. begin
  619. NewType := ftTime;
  620. end;
  621. FIELD_TYPE_VAR_STRING, FIELD_TYPE_STRING, FIELD_TYPE_ENUM, FIELD_TYPE_SET:
  622. begin
  623. // Since mysql server version 5.0.3 string-fields with a length of more
  624. // then 256 characters are suported
  625. if AField^.ftype = FIELD_TYPE_STRING then
  626. NewType := ftFixedChar
  627. else
  628. NewType := ftString;
  629. {$IFDEF MYSQL50_UP}
  630. if AField^.charsetnr = 63 then //BINARY vs. CHAR, VARBINARY vs. VARCHAR
  631. if NewType = ftFixedChar then
  632. NewType := ftBytes
  633. else
  634. NewType := ftVarBytes;
  635. {$ENDIF}
  636. NewSize := ASize;
  637. end;
  638. FIELD_TYPE_TINY_BLOB..FIELD_TYPE_BLOB:
  639. begin
  640. {$IFDEF MYSQL50_UP}
  641. if AField^.charsetnr = 63 then //character set is binary
  642. NewType := ftBlob
  643. else
  644. NewType := ftMemo;
  645. {$ELSE}
  646. NewType := ftBlob;
  647. {$ENDIF}
  648. end;
  649. {$IFDEF MYSQL50_UP}
  650. FIELD_TYPE_BIT:
  651. NewType := ftLargeInt;
  652. {$ENDIF}
  653. else
  654. Result := False;
  655. end;
  656. end;
  657. procedure TConnectionName.AddFieldDefs(cursor: TSQLCursor;
  658. FieldDefs: TfieldDefs);
  659. var
  660. C : TCursorName;
  661. I, TF, FC: Integer;
  662. field: PMYSQL_FIELD;
  663. DFT: TFieldType;
  664. DFS: Integer;
  665. begin
  666. // Writeln('MySQL: Adding fielddefs');
  667. C:=(Cursor as TCursorName);
  668. If (C.FRes=Nil) then
  669. begin
  670. // Writeln('res is nil');
  671. MySQLError(FMySQL,SErrNoQueryResult,Self);
  672. end;
  673. // Writeln('MySQL: have result');
  674. FC:=mysql_num_fields(C.FRes);
  675. SetLength(c.MapDSRowToMSQLRow,FC);
  676. TF := 1;
  677. For I:= 0 to FC-1 do
  678. begin
  679. field := mysql_fetch_field_direct(C.FRES, I);
  680. // Writeln('MySQL: creating fielddef ',I+1);
  681. if MySQLDataType(field, DFT, DFS) then
  682. begin
  683. FieldDefs.Add(FieldDefs.MakeNameUnique(field^.name), DFT, DFS,
  684. (field^.flags and (AUTO_INCREMENT_FLAG or NOT_NULL_FLAG {$IFDEF MYSQL50_UP}or NO_DEFAULT_VALUE_FLAG{$ENDIF})) = (NOT_NULL_FLAG {$IFDEF MYSQL50_UP}or NO_DEFAULT_VALUE_FLAG{$ENDIF}),
  685. TF);
  686. c.MapDSRowToMSQLRow[TF-1] := I;
  687. inc(TF);
  688. end
  689. end;
  690. // Writeln('MySQL: Finished adding fielddefs');
  691. end;
  692. function TConnectionName.Fetch(cursor: TSQLCursor): boolean;
  693. Var
  694. C : TCursorName;
  695. begin
  696. C:=Cursor as TCursorName;
  697. C.Row:=MySQL_Fetch_row(C.FRes);
  698. Result:=(C.Row<>Nil);
  699. if Result then
  700. C.Lengths := mysql_fetch_lengths(C.FRes)
  701. else
  702. C.Lengths := nil;
  703. end;
  704. function TConnectionName.LoadField(cursor : TSQLCursor;
  705. FieldDef : TfieldDef;buffer : pointer; out CreateBlob : boolean) : boolean;
  706. var
  707. field: PMYSQL_FIELD;
  708. C : TCursorName;
  709. i : integer;
  710. begin
  711. // Writeln('LoadFieldsFromBuffer');
  712. C:=Cursor as TCursorName;
  713. if (C.Row=nil) or (C.Lengths=nil) then
  714. begin
  715. // Writeln('LoadFieldsFromBuffer: row=nil');
  716. MySQLError(FMySQL,SErrFetchingData,Self);
  717. end;
  718. i := c.MapDSRowToMSQLRow[FieldDef.FieldNo-1];
  719. field := mysql_fetch_field_direct(C.FRES, i);
  720. Result := MySQLWriteData(field, FieldDef, C.Row[i], Buffer, C.Lengths[i], CreateBlob);
  721. end;
  722. procedure TConnectionName.LoadBlobIntoBuffer(FieldDef: TFieldDef;
  723. ABlobBuf: PBufBlobField; cursor: TSQLCursor; ATransaction: TSQLTransaction);
  724. var
  725. C : TCursorName;
  726. i : integer;
  727. len : longint;
  728. begin
  729. C:=Cursor as TCursorName;
  730. if (C.Row=nil) or (C.Lengths=nil) then
  731. MySQLError(FMySQL,SErrFetchingData,Self);
  732. i := c.MapDSRowToMSQLRow[FieldDef.FieldNo-1];
  733. len := C.Lengths[i];
  734. ReAllocMem(ABlobBuf^.BlobBuffer^.Buffer, len);
  735. Move(C.Row[i]^, ABlobBuf^.BlobBuffer^.Buffer^, len);
  736. ABlobBuf^.BlobBuffer^.Size := len;
  737. end;
  738. function InternalStrToInt(const S: string): integer;
  739. begin
  740. if S = '' then
  741. Result := 0
  742. else
  743. Result := StrToInt(S);
  744. end;
  745. function InternalStrToFloat(S: string): Extended;
  746. var
  747. I: Integer;
  748. Tmp: string;
  749. begin
  750. Tmp := '';
  751. for I := 1 to Length(S) do
  752. begin
  753. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  754. Tmp := Tmp + FormatSettings.DecimalSeparator
  755. else
  756. Tmp := Tmp + S[I];
  757. end;
  758. Result := StrToFloat(Tmp);
  759. end;
  760. function InternalStrToCurrency(S: string): Extended;
  761. var
  762. I: Integer;
  763. Tmp: string;
  764. begin
  765. Tmp := '';
  766. for I := 1 to Length(S) do
  767. begin
  768. if not (S[I] in ['0'..'9', '+', '-', 'E', 'e']) then
  769. Tmp := Tmp + FormatSettings.DecimalSeparator
  770. else
  771. Tmp := Tmp + S[I];
  772. end;
  773. Result := StrToCurr(Tmp);
  774. end;
  775. function InternalStrToDate(S: string): TDateTime;
  776. var
  777. EY, EM, ED: Word;
  778. begin
  779. EY := StrToInt(Copy(S,1,4));
  780. EM := StrToInt(Copy(S,6,2));
  781. ED := StrToInt(Copy(S,9,2));
  782. if (EY = 0) or (EM = 0) or (ED = 0) then
  783. Result:=0
  784. else
  785. Result:=EncodeDate(EY, EM, ED);
  786. end;
  787. function InternalStrToDateTime(S: string): TDateTime;
  788. var
  789. EY, EM, ED: Word;
  790. EH, EN, ES: Word;
  791. begin
  792. EY := StrToInt(Copy(S, 1, 4));
  793. EM := StrToInt(Copy(S, 6, 2));
  794. ED := StrToInt(Copy(S, 9, 2));
  795. EH := StrToInt(Copy(S, 12, 2));
  796. EN := StrToInt(Copy(S, 15, 2));
  797. ES := StrToInt(Copy(S, 18, 2));
  798. if (EY = 0) or (EM = 0) or (ED = 0) then
  799. Result := 0
  800. else
  801. Result := EncodeDate(EY, EM, ED);
  802. Result := ComposeDateTime(Result,EncodeTime(EH, EN, ES, 0));
  803. end;
  804. function InternalStrToTime(S: string): TDateTime;
  805. var
  806. EH, EM, ES: Word;
  807. p: integer;
  808. begin
  809. p := 1;
  810. EH := StrToInt(ExtractSubstr(S, p, [':'])); //hours can be 2 or 3 digits
  811. EM := StrToInt(ExtractSubstr(S, p, [':']));
  812. ES := StrToInt(ExtractSubstr(S, p, ['.']));
  813. Result := EncodeTimeInterval(EH, EM, ES, 0);
  814. end;
  815. function InternalStrToTimeStamp(S: string): TDateTime;
  816. var
  817. EY, EM, ED: Word;
  818. EH, EN, ES: Word;
  819. begin
  820. {$IFNDEF mysql40}
  821. EY := StrToInt(Copy(S, 1, 4));
  822. EM := StrToInt(Copy(S, 6, 2));
  823. ED := StrToInt(Copy(S, 9, 2));
  824. EH := StrToInt(Copy(S, 12, 2));
  825. EN := StrToInt(Copy(S, 15, 2));
  826. ES := StrToInt(Copy(S, 18, 2));
  827. {$ELSE}
  828. EY := StrToInt(Copy(S, 1, 4));
  829. EM := StrToInt(Copy(S, 5, 2));
  830. ED := StrToInt(Copy(S, 7, 2));
  831. EH := StrToInt(Copy(S, 9, 2));
  832. EN := StrToInt(Copy(S, 11, 2));
  833. ES := StrToInt(Copy(S, 13, 2));
  834. {$ENDIF}
  835. if (EY = 0) or (EM = 0) or (ED = 0) then
  836. Result := 0
  837. else
  838. Result := EncodeDate(EY, EM, ED);
  839. Result := Result + EncodeTime(EH, EN, ES, 0);
  840. end;
  841. function TConnectionName.MySQLWriteData(AField: PMYSQL_FIELD; FieldDef: TFieldDef; Source, Dest: PChar; Len: integer; out CreateBlob : boolean): Boolean;
  842. var
  843. VI: Integer;
  844. VL: LargeInt;
  845. VS: Smallint;
  846. VW: Word;
  847. VF: Double;
  848. VC: Currency;
  849. VD: TDateTime;
  850. VB: TBCD;
  851. Src : String;
  852. begin
  853. Result := False;
  854. CreateBlob := False;
  855. if Source = Nil then // If the pointer is NULL, the field is NULL
  856. exit;
  857. SetString(Src, Source, Len);
  858. if Len > FieldDef.Size then
  859. Len := FieldDef.Size;
  860. case FieldDef.DataType of
  861. ftSmallint:
  862. begin
  863. VS := InternalStrToInt(Src);
  864. Move(VS, Dest^, SizeOf(Smallint));
  865. end;
  866. ftWord:
  867. begin
  868. VW := InternalStrToInt(Src);
  869. Move(VW, Dest^, SizeOf(Word));
  870. end;
  871. ftInteger, ftAutoInc:
  872. begin
  873. VI := InternalStrToInt(Src);
  874. Move(VI, Dest^, SizeOf(Integer));
  875. end;
  876. ftLargeInt:
  877. begin
  878. {$IFDEF MYSQL50_UP}
  879. if AField^.ftype = FIELD_TYPE_BIT then
  880. begin
  881. VL := 0;
  882. for VI := 0 to Len-1 do
  883. VL := VL * 256 + PByte(Source+VI)^;
  884. end
  885. else
  886. {$ENDIF}
  887. if Src <> '' then
  888. VL := StrToInt64(Src)
  889. else
  890. VL := 0;
  891. Move(VL, Dest^, SizeOf(LargeInt));
  892. end;
  893. ftFloat:
  894. begin
  895. if Src <> '' then
  896. VF := InternalStrToFloat(Src)
  897. else
  898. VF := 0;
  899. Move(VF, Dest^, SizeOf(Double));
  900. end;
  901. ftBCD:
  902. begin
  903. VC := InternalStrToCurrency(Src);
  904. Move(VC, Dest^, SizeOf(Currency));
  905. end;
  906. ftFmtBCD:
  907. begin
  908. VB := StrToBCD(Src, FSQLFormatSettings);
  909. Move(VB, Dest^, SizeOf(TBCD));
  910. end;
  911. ftDate:
  912. begin
  913. if Src <> '' then
  914. VD := InternalStrToDate(Src)
  915. else
  916. VD := 0;
  917. Move(VD, Dest^, SizeOf(TDateTime));
  918. end;
  919. ftTime:
  920. begin
  921. if Src <> '' then
  922. VD := InternalStrToTime(Src)
  923. else
  924. VD := 0;
  925. Move(VD, Dest^, SizeOf(TDateTime));
  926. end;
  927. ftDateTime:
  928. begin
  929. if Src <> '' then
  930. if AField^.ftype = FIELD_TYPE_TIMESTAMP then
  931. VD := InternalStrToTimeStamp(Src)
  932. else
  933. VD := InternalStrToDateTime(Src)
  934. else
  935. VD := 0;
  936. Move(VD, Dest^, SizeOf(TDateTime));
  937. end;
  938. ftString, ftFixedChar:
  939. // String-fields which can contain more then dsMaxStringSize characters
  940. // are mapped to ftBlob fields, while their mysql-datatype is FIELD_TYPE_BLOB
  941. begin
  942. Move(Source^, Dest^, Len);
  943. (Dest+Len)^ := #0;
  944. end;
  945. ftVarBytes:
  946. begin
  947. PWord(Dest)^ := Len;
  948. Move(Source^, (Dest+sizeof(Word))^, Len);
  949. end;
  950. ftBytes:
  951. Move(Source^, Dest^, Len);
  952. ftBlob, ftMemo:
  953. CreateBlob := True;
  954. end;
  955. Result := True;
  956. end;
  957. procedure TConnectionName.UpdateIndexDefs(IndexDefs : TIndexDefs;TableName : string);
  958. var qry : TSQLQuery;
  959. begin
  960. if not assigned(Transaction) then
  961. DatabaseError(SErrConnTransactionnSet);
  962. qry := tsqlquery.Create(nil);
  963. qry.transaction := Transaction;
  964. qry.database := Self;
  965. with qry do
  966. begin
  967. ParseSQL := False;
  968. sql.clear;
  969. sql.add('show index from ' + TableName);
  970. open;
  971. end;
  972. while not qry.eof do with IndexDefs.AddIndexDef do
  973. begin
  974. Name := trim(qry.fieldbyname('Key_name').asstring);
  975. Fields := trim(qry.fieldbyname('Column_name').asstring);
  976. If Name = 'PRIMARY' then options := options + [ixPrimary];
  977. If qry.fieldbyname('Non_unique').asinteger = 0 then options := options + [ixUnique];
  978. qry.next;
  979. while (name = trim(qry.fieldbyname('Key_name').asstring)) and (not qry.eof) do
  980. begin
  981. Fields := Fields + ';' + trim(qry.fieldbyname('Column_name').asstring);
  982. qry.next;
  983. end;
  984. end;
  985. qry.close;
  986. qry.free;
  987. end;
  988. function TConnectionName.RowsAffected(cursor: TSQLCursor): TRowsCount;
  989. begin
  990. if assigned(cursor) then
  991. // Compile this without range-checking. RowsAffected can be -1, although
  992. // it's an unsigned integer. (small joke from the mysql-guys)
  993. // Without range-checking this goes ok. If Range is turned on, this results
  994. // in range-check errors.
  995. Result := (cursor as TCursorName).RowsAffected
  996. else
  997. Result := -1;
  998. end;
  999. constructor TConnectionName.Create(AOwner: TComponent);
  1000. const SingleBackQoutes: TQuoteChars = ('`','`');
  1001. begin
  1002. inherited Create(AOwner);
  1003. FConnOptions := FConnOptions + [sqEscapeRepeat] + [sqEscapeSlash];
  1004. FieldNameQuoteChars:=SingleBackQoutes;
  1005. FMySQL := Nil;
  1006. end;
  1007. procedure TConnectionName.GetFieldNames(const TableName: string; List: TStrings);
  1008. begin
  1009. GetDBInfo(stColumns,TableName,'field',List);
  1010. end;
  1011. procedure TConnectionName.GetTableNames(List: TStrings; SystemTables: Boolean);
  1012. begin
  1013. GetDBInfo(stTables,'','tables_in_'+DatabaseName,List)
  1014. end;
  1015. function TConnectionName.GetConnectionInfo(InfoType: TConnInfoType): string;
  1016. begin
  1017. Result:='';
  1018. try
  1019. InitialiseMysql;
  1020. case InfoType of
  1021. citServerType:
  1022. Result:='MySQL';
  1023. citServerVersion:
  1024. if Connected then
  1025. Result:=format('%6.6d', [mysql_get_server_version(FMySQL)]);
  1026. citServerVersionString:
  1027. if Connected then
  1028. Result:=mysql_get_server_info(FMySQL);
  1029. citClientVersion:
  1030. Result:=format('%6.6d', [mysql_get_client_version()]);
  1031. citClientName:
  1032. Result:=TMySQLConnectionDef.LoadedLibraryName;
  1033. else
  1034. Result:=inherited GetConnectionInfo(InfoType);
  1035. end;
  1036. finally
  1037. ReleaseMysql;
  1038. end;
  1039. end;
  1040. function TConnectionName.GetTransactionHandle(trans: TSQLHandle): pointer;
  1041. begin
  1042. Result:=Nil;
  1043. end;
  1044. function TConnectionName.Commit(trans: TSQLHandle): boolean;
  1045. begin
  1046. //mysql_commit(FMySQL);
  1047. Result := (mysql_query(FMySQL, 'COMMIT') = 0) or ForcedClose;
  1048. if not Result then
  1049. MySQLError(FMySQL, SErrExecuting, Self);
  1050. end;
  1051. function TConnectionName.RollBack(trans: TSQLHandle): boolean;
  1052. begin
  1053. //mysql_rollback(FMySQL);
  1054. Result := (mysql_query(FMySQL, 'ROLLBACK') = 0) or ForcedClose;
  1055. if not Result then
  1056. MySQLError(FMySQL, SErrExecuting, Self);
  1057. end;
  1058. function TConnectionName.StartdbTransaction(trans: TSQLHandle; AParams : string): boolean;
  1059. begin
  1060. Result := mysql_query(FMySQL, 'START TRANSACTION') = 0;
  1061. if not Result then
  1062. MySQLError(FMySQL, SErrExecuting, Self);
  1063. end;
  1064. procedure TConnectionName.CommitRetaining(trans: TSQLHandle);
  1065. begin
  1066. {$IFDEF MYSQL50_UP}
  1067. if mysql_query(FMySQL, 'COMMIT AND CHAIN') <> 0 then
  1068. MySQLError(FMySQL, SErrExecuting, Self);
  1069. {$ELSE}
  1070. if mysql_query(FMySQL, 'COMMIT') <> 0 then
  1071. MySQLError(FMySQL, SErrExecuting, Self);
  1072. if mysql_query(FMySQL, 'START TRANSACTION') <> 0 then
  1073. MySQLError(FMySQL, SErrExecuting, Self);
  1074. {$ENDIF}
  1075. end;
  1076. procedure TConnectionName.RollBackRetaining(trans: TSQLHandle);
  1077. begin
  1078. {$IFDEF MYSQL50_UP}
  1079. if mysql_query(FMySQL, 'ROLLBACK AND CHAIN') <> 0 then
  1080. MySQLError(FMySQL, SErrExecuting, Self);
  1081. {$ELSE}
  1082. if mysql_query(FMySQL, 'ROLLBACK') <> 0 then
  1083. MySQLError(FMySQL, SErrExecuting, Self);
  1084. if mysql_query(FMySQL, 'START TRANSACTION') <> 0 then
  1085. MySQLError(FMySQL, SErrExecuting, Self);
  1086. {$ENDIF}
  1087. end;
  1088. function TConnectionName.GetSchemaInfoSQL(SchemaType: TSchemaType;
  1089. SchemaObjectName, SchemaPattern: string): string;
  1090. begin
  1091. case SchemaType of
  1092. stTables : result := 'show tables';
  1093. stColumns : result := 'show columns from ' + EscapeString(SchemaObjectName);
  1094. else
  1095. DatabaseError(SMetadataUnavailable)
  1096. end; {case}
  1097. end;
  1098. { TMySQLConnectionDef }
  1099. class function TMySQLConnectionDef.TypeName: String;
  1100. begin
  1101. Result:='MySQL '+MySQLVersion;
  1102. end;
  1103. class function TMySQLConnectionDef.ConnectionClass: TSQLConnectionClass;
  1104. begin
  1105. {$IFDEF mysql56}
  1106. Result:=TMySQL56Connection;
  1107. {$ELSE}
  1108. {$IfDef mysql55}
  1109. Result:=TMySQL55Connection;
  1110. {$ELSE}
  1111. {$IfDef mysql51}
  1112. Result:=TMySQL51Connection;
  1113. {$ELSE}
  1114. {$IfDef mysql50}
  1115. Result:=TMySQL50Connection;
  1116. {$ELSE}
  1117. {$IfDef mysql41}
  1118. Result:=TMySQL41Connection;
  1119. {$ELSE}
  1120. Result:=TMySQL40Connection;
  1121. {$EndIf}
  1122. {$EndIf}
  1123. {$endif}
  1124. {$endif}
  1125. {$ENDIF}
  1126. end;
  1127. class function TMySQLConnectionDef.Description: String;
  1128. begin
  1129. Result:='Connect to a MySQL '+MySQLVersion+'database directly via the client library';
  1130. end;
  1131. class function TMySQLConnectionDef.DefaultLibraryName: String;
  1132. begin
  1133. Result:=mysqlvlib;
  1134. end;
  1135. class function TMySQLConnectionDef.LoadFunction: TLibraryLoadFunction;
  1136. begin
  1137. Result:=@InitialiseMySQL;
  1138. end;
  1139. class function TMySQLConnectionDef.UnLoadFunction: TLibraryUnLoadFunction;
  1140. begin
  1141. Result:=@ReleaseMySQL;
  1142. end;
  1143. class function TMySQLConnectionDef.LoadedLibraryName: string;
  1144. begin
  1145. Result:=MysqlLoadedLibrary;
  1146. end;
  1147. {$IFDEF mysql56}
  1148. initialization
  1149. RegisterConnection(TMySQL56ConnectionDef);
  1150. finalization
  1151. UnRegisterConnection(TMySQL56ConnectionDef);
  1152. {$ELSE}
  1153. {$IfDef mysql55}
  1154. initialization
  1155. RegisterConnection(TMySQL55ConnectionDef);
  1156. finalization
  1157. UnRegisterConnection(TMySQL55ConnectionDef);
  1158. {$else}
  1159. {$IfDef mysql51}
  1160. initialization
  1161. RegisterConnection(TMySQL51ConnectionDef);
  1162. finalization
  1163. UnRegisterConnection(TMySQL51ConnectionDef);
  1164. {$ELSE}
  1165. {$IfDef mysql50}
  1166. initialization
  1167. RegisterConnection(TMySQL50ConnectionDef);
  1168. finalization
  1169. UnRegisterConnection(TMySQL50ConnectionDef);
  1170. {$ELSE}
  1171. {$IfDef mysql41}
  1172. initialization
  1173. RegisterConnection(TMySQL41ConnectionDef);
  1174. finalization
  1175. UnRegisterConnection(TMySQL41ConnectionDef);
  1176. {$ELSE}
  1177. initialization
  1178. RegisterConnection(TMySQL40ConnectionDef);
  1179. finalization
  1180. UnRegisterConnection(TMySQL40ConnectionDef);
  1181. {$EndIf}
  1182. {$EndIf}
  1183. {$ENDIF}
  1184. {$endif}
  1185. {$ENDIF}
  1186. end.