mysqlconn.inc 37 KB

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