2
0

mysqlconn.inc 36 KB

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