fpodbc.pp 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465
  1. unit fpodbc;
  2. {$mode objfpc}
  3. {$h+}
  4. interface
  5. uses odbcsql,SysUtils,Classes;
  6. Type
  7. TDSNTypes = (dtUser,dtSystem,dtBoth);
  8. TODBCParamType = (ptUnknown,ptInput,ptInputOutput,ptResult,ptOutput,ptRetVal);
  9. TODBCParamTypes = Set of TODBCParamType;
  10. TODBCObject = Class(TComponent)
  11. Private
  12. FHandle : SQLHandle;
  13. FHandleType : SQLSmallint;
  14. Function GetHandle : SQLHandle;
  15. function GetHandleAllocated: Boolean;
  16. function GetExtendedErrorInfo: String;
  17. Protected
  18. Function CreateHandle : SQLHandle; Virtual;
  19. Function ParentHandle : SQLHandle; Virtual;
  20. Procedure FreeHandle;
  21. Function CheckODBC(Res : Integer;Msg : String) : Integer;
  22. Public
  23. Destructor Destroy; override;
  24. Property Handle : SQLHandle Read GetHandle;
  25. Property HandleAllocated : Boolean Read GetHandleAllocated;
  26. end;
  27. TODBCEnvironment = Class(TODBCObject)
  28. Private
  29. FODBCBehaviour : Integer;
  30. procedure SetODBCbehaviour(const Value: Integer);
  31. function GetNullTerminate: Boolean;
  32. procedure SetNullTerminate(const Value: Boolean);
  33. protected
  34. function CreateHandle: SQLHandle; override;
  35. Procedure SetIntAttribute(Const Attr,Value : Integer);
  36. Procedure SetStringAttribute(Const Attr: Integer; Value : String);
  37. Function GetIntAttribute(Const Attr : Integer) : Integer;
  38. Function GetStringAttribute(Const Attr : Integer) : String;
  39. Public
  40. Constructor Create(Aowner : TComponent);override;
  41. Function GetDriverNames(List : Tstrings) : Integer;
  42. Function GetDataSourceNames(List : Tstrings; Types : TDSNTypes;Descriptions : Boolean) : Integer;
  43. function GetDriverOptions(Driver: String; Options: TStrings): Integer;
  44. Property ODBCBehaviour : Integer Read FODBCBehaviour Write SetODBCbehaviour;
  45. Property NullTerminateStrings : Boolean Read GetNullTerminate Write SetNullTerminate;
  46. end;
  47. TConnectionBrowseEvent = Procedure (Sender : TObject;InParams,OutParams : Tstrings) of Object;
  48. TODBCConnection = Class(TODBCObject)
  49. Private
  50. FActive : Boolean;
  51. FDriverParams : TStrings;
  52. FDSN,
  53. FDriverName,
  54. FUserName,
  55. FPassword : String;
  56. FEnvironMent : TODBCEnvironment;
  57. FOnBrowseConnection : TConnectionBrowseEvent;
  58. FWindowHandle : integer;
  59. FDriverCOmpletion: SQLUSmallInt;
  60. function GetDriverName: String;
  61. function GetDriverParams: TStrings;
  62. procedure SetActive(const Value: Boolean);
  63. procedure SetDriverName(const Value: String);
  64. procedure SetDriverParams(const Value: TStrings);
  65. procedure SetDSN(const Value: String);
  66. function GetEnvironment: TODBCEnvironMent;
  67. procedure SetEnvironment(const Value: TODBCEnvironMent);
  68. Protected
  69. procedure ConnectToDriver;
  70. procedure ConnectToDSN;
  71. Procedure ConnectBrowsing;
  72. Function ParentHandle : SQLHandle; override;
  73. Procedure CheckActive;
  74. Procedure CheckInActive;
  75. Public
  76. Constructor Create(Aowner : TComponent);override;
  77. Destructor Destroy; override;
  78. Procedure Connect;
  79. Procedure Disconnect;
  80. Procedure GetTableNames(S : TStrings; SystemTables : Boolean);
  81. Procedure GetFieldNames(TableName : String; S : TStrings);
  82. Procedure GetPrimaryKeyFields(TableName : String; S : TStrings);
  83. procedure GetProcedureNames(S : TStrings);
  84. procedure GetProcedureParams(ProcName : String;ParamTypes : TODBCParamTypes; S : TStrings);
  85. Property DSN : String Read FDSN Write SetDSN;
  86. Property DriverName : String Read GetDriverName Write SetDriverName;
  87. Property DriverCompletion : SQLUSmallInt Read FDriverCOmpletion Write FDriverCompletion;
  88. Property DriverParams : TStrings Read GetDriverParams Write SetDriverParams;
  89. Property Active : Boolean Read FActive Write SetActive;
  90. Property Environment : TODBCEnvironMent Read GetEnvironment Write SetEnvironment;
  91. Property UserName : String Read FUserName Write FUserName;
  92. Property Password : string Read FPassword Write FPassword;
  93. Property OnBrowseConnection : TConnectionBrowseEvent Read FonBrowseConnection Write FOnBrowseConnection;
  94. Property WindowHandle : integer Read FWindowHandle Write FWindowHandle;
  95. end;
  96. TODBCStatement = Class;
  97. TODBCFieldList = Class(TCollection)
  98. Private
  99. FStatement : TODBCStatement;
  100. Public
  101. Constructor Create(Statement : TODBCStatement);
  102. end;
  103. {
  104. TODBCStatement allocates 1 big data buffer. For each bound field
  105. two things are allocated in the buffer:
  106. - Size of fetched data as filled in by fetch.
  107. - data. (may be zero for blobs etc)
  108. The FBuffOffset contains the offset in the buffer of the size field.
  109. Data immediatly follows the size.
  110. }
  111. TODBCField = Class(TCollectionItem)
  112. Private
  113. FDecimalDigits,
  114. FPosition : SQLSmallInt;
  115. FName : String;
  116. FSize : SQLUInteger; // Declared size, as returned by DescribeCol
  117. FNullable : Boolean;
  118. FDataType : SQLSmallInt; // Declared type, as returned by DescribeCol
  119. FBuffOffSet : SQLInteger; // Offset in data buffer.
  120. FBuffer : Pointer; // Pointer to data.
  121. FBufSize : SQLInteger; // Allocated buffer size.
  122. FBufType : SQLSmallInt; // Allocated buffer type
  123. function GetAsString: String;
  124. function GetData : PChar;
  125. Function GetIsNull : Boolean;
  126. Function GetAsInteger : Integer;
  127. Function GetAsBoolean : Boolean;
  128. Function GetAsDouble : Double;
  129. Function GetAsDateTime : TDateTime;
  130. Public
  131. Property Position : SQLSmallint Read FPosition;
  132. Property Name : String read FName;
  133. Property DataType : SQLSmallInt read FDatatype;
  134. Property Size : SQLUinteger read FSize;
  135. property DecimalDigits : SQLSmallInt read FDecimalDigits;
  136. Property Nullable : Boolean Read FNullable;
  137. Property Data : Pchar Read GetData;
  138. Property BufType : SQLSmallInt Read FBufType;
  139. Property BufSize : SQLInteger Read FBufSize;
  140. Property IsNull : Boolean Read GetIsNull;
  141. Property AsString : String Read GetAsString;
  142. Property AsInteger : Integer Read GetAsInteger;
  143. Property AsBoolean : Boolean Read GetAsBoolean;
  144. Property AsDouble : Double Read GetAsDouble;
  145. Property AsDateTime : TDateTime Read GetAsDateTime;
  146. end;
  147. TODBCStatement = Class(TODBCObject)
  148. Private
  149. FBOF,FEOF : Boolean;
  150. FConnection: TODBCConnection;
  151. FFields : TODBCFieldList;
  152. FBuffer : Pointer;
  153. Protected
  154. Function ParentHandle : SQLHandle; override;
  155. procedure SetConnection(const Value: TODBCConnection);
  156. procedure AllocBuffers;
  157. Public
  158. Constructor Create(Aowner : TComponent);override;
  159. Destructor Destroy; override;
  160. Procedure BindFields(RestrictList : TStrings);virtual;
  161. Procedure ClearFields;virtual;
  162. Function Fetch : Boolean;
  163. Property Connection : TODBCConnection Read FConnection Write SetConnection;
  164. Property BOF : Boolean read FBOF;
  165. Property EOF : Boolean read FEOF;
  166. Property Fields : TODBCFieldList Read FFields;
  167. end;
  168. TODBCTableList = Class(TODBCStatement)
  169. Public
  170. Procedure GetTableNames(S : TStrings; SystemTables : Boolean);
  171. end;
  172. TODBCFieldNamesList = Class(TODBCStatement)
  173. Public
  174. Procedure GetFieldNames(TableName : String;S : TStrings);
  175. end;
  176. TODBCPrimaryKeyFieldsList = Class(TODBCStatement)
  177. Public
  178. Procedure GetPrimaryKeyFields(TableName : String;S : TStrings);
  179. end;
  180. TODBCProcedureList = Class(TODBCStatement)
  181. Public
  182. Procedure GetProcedureList(S : TStrings);
  183. end;
  184. TODBCProcedureParams = Class(TODBCStatement)
  185. Procedure GetProcedureParams(ProcName: String; ParamTypes: TODBCParamTypes; S: TStrings);
  186. end;
  187. TStatementState = (ssInactive,ssPrepared,ssBound,ssOpen);
  188. TODBCSQLStatement = Class(TODBCStatement)
  189. Private
  190. FSQL : TStrings;
  191. FState : TStatementState;
  192. function GetActive: Boolean;
  193. procedure SetActive(const Value: Boolean);
  194. Protected
  195. procedure FreeStatement(Option: SQLUSMALLINT);
  196. procedure ExecuteDirect;
  197. procedure ExecutePrepared;
  198. Procedure SetSQL(const Value: TStrings);
  199. Public
  200. Constructor Create(Aowner : TComponent);override;
  201. Destructor Destroy; override;
  202. procedure Prepare;
  203. procedure Unprepare;
  204. Procedure BindFields(RestrictList : TStrings);override;
  205. procedure ExecSQL;
  206. Procedure Open;
  207. Procedure Close;
  208. procedure GetFieldList(List: TStrings);
  209. Property Active : Boolean Read GetActive Write SetActive;
  210. Property SQL : TStrings Read FSQL Write SetSQL;
  211. end;
  212. EODBCError = Class(Exception);
  213. Const
  214. ODBCParamTypeNames : Array [TODBCParamType] of string
  215. = ('Unknown','Input','Input/Output','Result','Output','RetVal');
  216. Function DefaultEnvironment : TODBCEnvironment;
  217. implementation
  218. { TODBCObject }
  219. resourcestring
  220. SErrUnexpected = 'Unexpected ODBC error:';
  221. SErrEnvironmentHandle = 'Cannot allocate environment handle:';
  222. SErrInvalidBehaviour = 'Invalid value for ODBC behaviour: %d';
  223. SErrNotConnected = 'Operation invalid when not connected.';
  224. SErrConnected = 'Operation invalid when connected.';
  225. SNeedDSNOrDriver = 'Cannot connect with empty DSN and driver names.';
  226. SErrGettingDataSources = 'Error getting datasources:';
  227. SErrGettingDriverNames = 'Error getting driver names:';
  228. SErrGettingDriverOptions = 'Error getting driver options:';
  229. SErrSettingEnvAttribute = 'Error setting environment attribute:';
  230. SErrGettingEnvAttribute = 'Error Getting environment attribute:';
  231. SErrBrowseConnecting = 'Error connecting to datasource via browse:';
  232. SErrDSNConnect = 'Error connecting to DSN:';
  233. SErrDriverConnect = 'Error connecting to driver:';
  234. SErrDisconnecting = 'Error disconnecting:';
  235. SErrNoConnectionForStatement = 'Missing connection for statement.';
  236. SErrNoSQLStatement = 'Missing SQL statement.';
  237. SErrPreparing = 'Error preparing statement:';
  238. SErrGettingTableNames = 'Error getting table names:';
  239. SErrFetchingData = 'Error fetching data:';
  240. SErrFieldNames = 'Error getting field names:';
  241. SErrPrimaryKeys = 'Error getting primary key names:';
  242. SErrProcedureNames = 'Error getting procedure names:';
  243. SErrExecuting = 'Error while executing statement:';
  244. SErrExecutingPrepared = 'Error while executing prepared statement:';
  245. SErrNotPrepared = 'Statement is not prepared';
  246. SErrNotInactive = 'Statement is already prepared or executed.';
  247. SErrStatementActive = 'A statement is still active';
  248. SErrColumnCount = 'Error retrieving cilumn count:';
  249. SErrColDescription = 'Error retrieving column description';
  250. SErrInvalidConversion = 'invalid type conversion';
  251. SErrBindCol = 'Error binding column';
  252. Const
  253. ODBCSuccess = [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO];
  254. Procedure ODBCError (Msg : String);
  255. begin
  256. Raise EODBCError.Create(Msg);
  257. end;
  258. Procedure ODBCErrorFmt (Fmt : String;Args : Array of const);
  259. begin
  260. Raise EODBCError.CreateFmt(Fmt,Args);
  261. end;
  262. Function CheckODBC(Res : Integer;Msg : String) : Integer;
  263. begin
  264. Result:=Res;
  265. if not Res in [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO] then
  266. begin
  267. If MSG='' then
  268. MSG:=SErrUnexpected;
  269. ODBCErrorFmt(msg,[res]);
  270. end;
  271. end;
  272. function TODBCObject.CheckODBC(Res: Integer; Msg: String): Integer;
  273. Var S : String;
  274. begin
  275. Result:=Res;
  276. if not Res in [SQL_SUCCESS,SQL_SUCCESS_WITH_INFO] then
  277. begin
  278. If MSG='' then
  279. MSG:=SErrUnexpected;
  280. S:=GetExtendedErrorInfo;
  281. If S<>'' then
  282. Msg:=Msg+LineEnding+S;
  283. ODBCError(msg);
  284. end;
  285. end;
  286. function TODBCObject.GetExtendedErrorInfo : String;
  287. Var
  288. Res : SQLreturn;
  289. I,MsgLen : SQLSmallInt;
  290. SQLState : Array[0..6] of Char;
  291. NativeError : SQLInteger;
  292. MSg : Array[0..SQL_MAX_MESSAGE_LENGTH] of Char;
  293. SState,SMsg : String;
  294. begin
  295. I:=0;
  296. Result:='';
  297. Repeat
  298. Inc(i);
  299. Res:=SQLGetDiagRec(FhandleType, FHandle, i, SqlState, NativeError,
  300. Msg, sizeof(Msg), MsgLen);
  301. If Res<>SQL_NO_DATA then
  302. begin
  303. SState:=SQLState;
  304. SMsg:=Msg;
  305. If Length(Result)>0 then
  306. Result:=Result+LineEnding;
  307. Result:=Result+Format('[%s] : %s (%d)',[SState,SMsg,NativeError]);
  308. end;
  309. Until (Res=SQL_NO_DATA);
  310. end;
  311. function TODBCObject.CreateHandle: SQLHandle;
  312. begin
  313. {$ifdef debug}
  314. Writeln(Classname,': Creating handle of type ',FHAndleType,' and parent ',ParentHandle);
  315. {$endif}
  316. CheckODBC(SQLAllocHandle(FHandleType,ParentHandle,FHandle),SErrEnvironmentHandle);
  317. Result:=FHandle;
  318. end;
  319. destructor TODBCObject.Destroy;
  320. begin
  321. If FHandle<>0 then
  322. FreeHandle;
  323. inherited;
  324. end;
  325. procedure TODBCObject.FreeHandle;
  326. begin
  327. If FHandle<>0 then
  328. begin
  329. SQLFreeHandle(FHandleType,FHandle);
  330. FHandle:=0;
  331. end;
  332. end;
  333. function TODBCObject.GetHandle: SQLHandle;
  334. begin
  335. If FHandle=0 then
  336. CreateHandle;
  337. Result:=FHandle;
  338. end;
  339. function TODBCObject.GetHandleAllocated: Boolean;
  340. begin
  341. Result:=(FHandle<>0)
  342. end;
  343. function TODBCObject.ParentHandle: SQLHandle;
  344. begin
  345. Result:=SQL_NULL_HANDLE;
  346. end;
  347. { TODBCEnvironment }
  348. constructor TODBCEnvironment.Create(Aowner: TComponent);
  349. begin
  350. FHandleType:=SQL_HANDLE_ENV;
  351. inherited;
  352. end;
  353. function TODBCEnvironment.CreateHandle: SQLHandle;
  354. begin
  355. Result:=Inherited CreateHandle;
  356. ODBCbehaviour:=SQL_OV_ODBC3;
  357. end;
  358. function TODBCEnvironment.GetDataSourceNames(List: Tstrings;
  359. Types: TDSNTypes;Descriptions : Boolean): Integer;
  360. var
  361. DSNName,
  362. DSNDesc: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
  363. lenn,lend : SQLSmallInt;
  364. Dir : SQLSmallInt;
  365. Sn,SD : String;
  366. begin
  367. Case Types of
  368. dtSystem : Dir:=SQL_FETCH_FIRST_SYSTEM;
  369. dtUser : Dir:=SQL_FETCH_FIRST_USER;
  370. dtBoth : Dir:=SQL_FETCH_FIRST;
  371. end;
  372. List.Clear;
  373. CheckODBC(SQLDatasources(Handle, Dir,
  374. DSNName,SQL_MAX_OPTION_STRING_LENGTH, @lenn,
  375. DSNDesc,SQL_MAX_OPTION_STRING_LENGTH, @lend),SErrGettingDataSources);
  376. Repeat
  377. If Not Descriptions then
  378. List.Add(DSNName)
  379. else
  380. begin
  381. SN:=DSNName;
  382. SD:=DSNDesc;
  383. List.Add(SN+'='+SD);
  384. end;
  385. Until Not (SQLDataSources(Handle, SQL_FETCH_NEXT,
  386. DSNName, SQL_MAX_OPTION_STRING_LENGTH, @lenn,
  387. DSNDesc,SQL_MAX_OPTION_STRING_LENGTH, @lend) in ODBCSuccess);
  388. Result:=List.Count;
  389. end;
  390. function TODBCEnvironment.GetDriverNames(List : Tstrings): Integer;
  391. Var
  392. DriverName: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
  393. len : SQLSmallInt;
  394. begin
  395. List.Clear;
  396. CheckODBC(SQLDrivers(Handle, SQL_FETCH_FIRST, DriverName,
  397. SQL_MAX_OPTION_STRING_LENGTH, @len, Nil,0,Nil),SErrGettingDriverNames);
  398. Repeat
  399. List.Add(DriverName);
  400. Until Not (SQLDrivers(Handle, SQL_FETCH_NEXT, DriverName,
  401. SQL_MAX_OPTION_STRING_LENGTH, @len, Nil,0,Nil) in ODBCSuccess);
  402. Result:=List.Count;
  403. end;
  404. function TODBCEnvironment.GetDriverOptions(Driver : String;Options: Tstrings): Integer;
  405. Var
  406. DriverName,
  407. DriverOptions: array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
  408. lenn,leno : SQLSmallInt;
  409. Found : Boolean;
  410. P : PChar;
  411. S : string;
  412. begin
  413. CheckODBC(SQLDrivers(Handle, SQL_FETCH_FIRST, DriverName,
  414. SQL_MAX_OPTION_STRING_LENGTH, @lenn, DriverOptions,
  415. SQL_MAX_OPTION_STRING_LENGTH,@Leno),SErrGettingDriverOptions);
  416. Result:=0;
  417. Options.Clear;
  418. Repeat
  419. Found:=CompareText(Driver,DriverName)=0;
  420. If Found then
  421. begin
  422. P:=@DriverOptions[0];
  423. While P[0]<>#0 do
  424. begin
  425. S:=StrPas(P);
  426. options.Add(S);
  427. Inc(P,Length(S)+1);
  428. end;
  429. end;
  430. Until Not (SQLDrivers(Handle, SQL_FETCH_NEXT, DriverName,
  431. SQL_MAX_OPTION_STRING_LENGTH, @lenn, DriverOptions,
  432. SQL_MAX_OPTION_STRING_LENGTH,@Leno) in ODBCSuccess) or Found;
  433. Result:=Options.Count;
  434. end;
  435. function TODBCEnvironment.GetIntAttribute(const Attr: Integer): Integer;
  436. begin
  437. CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(@result),0),SErrSettingEnvAttribute);
  438. end;
  439. function TODBCEnvironment.GetNullTerminate: Boolean;
  440. begin
  441. Result:=(GetIntAttribute(SQL_ATTR_OUTPUT_NTS)=SQL_TRUE);
  442. end;
  443. function TODBCEnvironment.GetStringAttribute(const Attr: Integer): String;
  444. Var
  445. OldLen,Len: Integer;
  446. begin
  447. OldLen:=0;
  448. Repeat
  449. Inc(OldLen,255);
  450. SetLength(Result,OldLen);
  451. CheckODBC(SQLGetEnvAttr(Handle,Attr,SQLPointer(@result),OldLen,@Len),SErrGettingEnvAttribute);
  452. until (Len<=OldLen);
  453. SetLength(Result,Len);
  454. end;
  455. procedure TODBCEnvironment.SetIntAttribute(const Attr, Value: Integer);
  456. begin
  457. CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(Value),0),SErrSettingEnvAttribute);
  458. end;
  459. procedure TODBCEnvironment.SetNullTerminate(const Value: Boolean);
  460. begin
  461. If Value then
  462. SetIntAttribute(SQL_ATTR_OUTPUT_NTS,SQL_TRUE)
  463. else
  464. SetIntAttribute(SQL_ATTR_OUTPUT_NTS,SQL_FALSE);
  465. end;
  466. procedure TODBCEnvironment.SetODBCbehaviour(const Value: Integer);
  467. begin
  468. If (Value<>FODBCBehaviour) then
  469. begin
  470. If Not (Value in [SQL_OV_ODBC3,SQL_OV_ODBC2]) Then
  471. ODBCErrorFmt(SErrInvalidBehaviour,[Value]);
  472. SetIntAttribute(SQL_ATTR_ODBC_VERSION,Value);
  473. FODBCBehaviour := Value;
  474. end;
  475. end;
  476. procedure TODBCEnvironment.SetStringAttribute(const Attr: Integer;
  477. Value: String);
  478. begin
  479. CheckODBC(SQLSetEnvAttr(Handle,Attr,SQLPointer(Value),Length(Value)),SErrSettingEnvAttribute);
  480. end;
  481. { TODBCConnection }
  482. procedure TODBCConnection.CheckActive;
  483. begin
  484. If Not FActive then
  485. ODBCError(SErrNotConnected);
  486. end;
  487. procedure TODBCConnection.CheckInActive;
  488. begin
  489. If FActive then
  490. ODBCError(SErrConnected);
  491. end;
  492. procedure TODBCConnection.Connect;
  493. begin
  494. If Not FActive then
  495. begin
  496. If Assigned (FonBrowseConnection) then
  497. ConnectBrowsing
  498. else If (FDSN<>'') then
  499. ConnectToDSN
  500. else if FDriverName<>'' then
  501. ConnectToDriver
  502. else
  503. ODBCError(SNeedDSNOrDriver);
  504. FActive:=True;
  505. end;
  506. end;
  507. Function ListToBuf(List : Tstrings; Buf : PChar; Sep : Char; MaxLen : Integer) : Boolean;
  508. Var
  509. P : PChar;
  510. S : String;
  511. I,Len : Integer;
  512. begin
  513. P:=Buf;
  514. I:=0;
  515. Result:=True;
  516. While Result and (I<List.Count) do
  517. begin
  518. S:=List[i];
  519. If I<List.Count-1 then
  520. S:=S+Sep;
  521. Len:=Length(S);
  522. Result:=(Longint(P-Buf)+Len)<=MaxLen;
  523. If Result then
  524. begin
  525. Move(S[1],P^,Len);
  526. Inc(P,Len);
  527. end;
  528. Inc(i);
  529. end;
  530. P[0]:=#0;
  531. end;
  532. Function BufToList(Buf : PChar;MaxLen : Integer;List : Tstrings;Sep : Char) : Integer;
  533. Var
  534. S : String;
  535. P : PChar;
  536. Totlen,Len : Integer;
  537. begin
  538. List.Clear;
  539. Result:=0;
  540. P:=Buf;
  541. TotLen:=0;
  542. While (P[0]<>#0) or (totlen<Maxlen) do
  543. begin
  544. Len:=0;
  545. While Not (P[len] in [Sep,#0]) do
  546. Inc(len);
  547. SetLength(S,Len);
  548. List.Add(S);
  549. Move(P[0],S[1],Len);
  550. Inc(P,Len);
  551. If P[0]<>#0 then
  552. Inc(P,1);
  553. inc(Totlen,Len+1);
  554. end;
  555. Result:=List.Count;
  556. end;
  557. Procedure TODBCConnection.ConnectBrowsing;
  558. Var
  559. Inlist,OutList : TStringList;
  560. InStr,
  561. OutStr: Array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
  562. i,Res : Integer;
  563. olen : SQLSmallint;
  564. begin
  565. InList:=TStringList.Create;
  566. OutList:=TstringList.Create;
  567. try
  568. If FDSN<>'' then
  569. InList.Add('DSN='+FDSN)
  570. else If FDriverName<>'' then
  571. begin
  572. Inlist.Add('DRIVER='+FDriverName);
  573. For I:=0 to DriverParams.Count-1 do
  574. Inlist.Add(DriverParams[i]);
  575. end;
  576. Repeat
  577. ListToBuf(Inlist,Instr,';',SQL_MAX_OPTION_STRING_LENGTH);
  578. Res:=SQLBrowseConnect(Handle,Instr,SQL_NTS,Outstr,SQL_MAX_OPTION_STRING_LENGTH,Olen);
  579. If RES=SQL_NEED_DATA then
  580. begin
  581. OutList.Clear;
  582. BufToList(OutStr,Olen,OutList,';');
  583. FOnBrowseConnection(Self,InList,OutList);
  584. end
  585. Until (Res<>SQL_NEED_DATA);
  586. CheckODBC(Res,SErrBrowseConnecting);
  587. Finally
  588. Outlist.free;
  589. InList.Free;
  590. end;
  591. end;
  592. Procedure TODBCConnection.ConnectToDSN;
  593. begin
  594. CheckODBC(SQLConnect(Handle,PSQLChar(FDSN),SQL_NTS,
  595. PSQLChar(FUserName),SQL_NTS,
  596. PSQLChar(FPassword),SQL_NTS),SErrDSNConnect);
  597. end;
  598. Procedure TODBCConnection.ConnectToDriver;
  599. Var
  600. Instr,
  601. OutStr : Array[0..SQL_MAX_OPTION_STRING_LENGTH] of Char;
  602. OLen : SQLSmallint;
  603. InList : TStringList;
  604. begin
  605. InList:=TStringList.Create;
  606. Try
  607. Inlist.Assign(DriverParams);
  608. Inlist.Insert(0,'DRIVER={'+DRIVERNAME+'}');
  609. ListToBuf(Inlist,InStr,';',SQL_MAX_OPTION_STRING_LENGTH);
  610. Finally
  611. Inlist.Free;
  612. end;
  613. CheckODBC(SQLDriverConnect(Handle,FWindowHandle,
  614. Instr,SQL_NTS,
  615. OutStr,SQL_MAX_OPTION_STRING_LENGTH,
  616. Olen,FDriverCompletion),SErrDriverConnect);
  617. end;
  618. constructor TODBCConnection.Create(Aowner: TComponent);
  619. begin
  620. inherited;
  621. FHandleType:=SQL_HANDLE_DBC;
  622. FDriverParams:=TStringList.Create;
  623. FDriverCompletion:=SQL_DRIVER_NOPROMPT;
  624. end;
  625. destructor TODBCConnection.Destroy;
  626. begin
  627. Disconnect;
  628. inherited;
  629. end;
  630. procedure TODBCConnection.Disconnect;
  631. begin
  632. If FActive then
  633. begin
  634. CheckODBC(SQLDisconnect(Handle),SErrDisconnecting);
  635. Factive:=False;
  636. end;
  637. end;
  638. function TODBCConnection.GetDriverName: String;
  639. begin
  640. Result:=FDriverName;
  641. end;
  642. function TODBCConnection.GetDriverParams: TStrings;
  643. begin
  644. Result:=FDriverParams;
  645. end;
  646. function TODBCConnection.GetEnvironment: TODBCEnvironMent;
  647. begin
  648. If FEnvironment=Nil then
  649. result:=DefaultEnvironment
  650. else
  651. Result:=FEnvironment;
  652. end;
  653. procedure TODBCConnection.SetActive(const Value: Boolean);
  654. begin
  655. If Value then
  656. Connect
  657. else
  658. Disconnect;
  659. end;
  660. procedure TODBCConnection.SetDriverName(const Value: String);
  661. begin
  662. CheckInactive;
  663. FDSN:='';
  664. If CompareText(FDriverName,Value)<>0 then
  665. begin
  666. FDriverName:=Value;
  667. FDriverParams.Clear;
  668. end;
  669. end;
  670. procedure TODBCConnection.SetDriverParams(const Value: TStrings);
  671. begin
  672. CheckInactive;
  673. FDriverParams.Assign(Value);
  674. end;
  675. procedure TODBCConnection.SetDSN(const Value: String);
  676. begin
  677. CheckInactive;
  678. FDSN := Value;
  679. end;
  680. procedure TODBCConnection.SetEnvironment(const Value: TODBCEnvironMent);
  681. begin
  682. CheckInactive;
  683. If (Value<>Environment) then // !! may be defaultenvironment...
  684. begin
  685. If HandleAllocated then
  686. FreeHandle;
  687. FEnvironment:=Value
  688. end;
  689. end;
  690. function TODBCConnection.ParentHandle: SQLHandle;
  691. begin
  692. Result:=Environment.Handle
  693. end;
  694. Const
  695. DefEnv : Pointer = Nil;
  696. Function DefaultEnvironment : TODBCEnvironment;
  697. begin
  698. If DefEnv=Nil then
  699. DefEnv:=TODBCEnvironment.Create(Nil);
  700. Result:=TODBCEnvironment(DefEnv);
  701. end;
  702. procedure TODBCConnection.GetTableNames(S: TStrings;
  703. SystemTables: Boolean);
  704. begin
  705. With TODBCTableList.Create(Self) do
  706. try
  707. GetTableNames(S,SystemTables);
  708. finally
  709. Free;
  710. end;
  711. end;
  712. procedure TODBCConnection.GetFieldNames(TableName: String; S: TStrings);
  713. begin
  714. With TODBCFieldNamesList.Create(Self) do
  715. try
  716. GetFieldNames(TableName,S);
  717. finally
  718. Free;
  719. end;
  720. end;
  721. procedure TODBCConnection.GetPrimaryKeyFields(TableName: String;
  722. S: TStrings);
  723. begin
  724. With TODBCPrimaryKeyFieldsList.Create(Self) do
  725. try
  726. GetPrimaryKeyFields(TableName,S);
  727. finally
  728. Free;
  729. end;
  730. end;
  731. procedure TODBCConnection.GetProcedureNames(S: TStrings);
  732. begin
  733. With TODBCProcedureList.Create(Self) do
  734. try
  735. GetProcedureList(S);
  736. Finally
  737. Free;
  738. end;
  739. end;
  740. procedure TODBCConnection.GetProcedureParams(ProcName: String;
  741. ParamTypes: TODBCParamTypes; S: TStrings);
  742. begin
  743. With TODBCProcedureParams.Create(Self) do
  744. Try
  745. GetProcedureParams(ProcName,Paramtypes,S);
  746. finally
  747. Free;
  748. end;
  749. end;
  750. { TODBCStatement }
  751. Type
  752. TODBCFieldBufRec = Record
  753. T{ype} : SQlSmallint;
  754. B{ufsize} : SQLInteger;
  755. {Buftyp}e : SQLSmallint;
  756. end;
  757. Const
  758. BufDescrCount = 26;
  759. BufDescr : Array[1..BufDescrCount] of TODBCFieldBufRec =
  760. { Type Bufsize Buftype }
  761. (
  762. (T:SQL_CHAR ;b:-1 ;e: SQL_CHAR),
  763. (T:SQL_NUMERIC ;b:sizeof(SQLDouble) ;e: SQL_DOUBLE),
  764. (T:SQL_DECIMAL ;b:sizeof(SQLDouble) ;e: SQL_DOUBLE),
  765. (T:SQL_INTEGER ;b:sizeof(SQLInteger) ;e: SQL_INTEGER),
  766. (T:SQL_SMALLINT ;b:sizeof(SQLSmallInt) ;e: SQL_SMALLINT),
  767. (T:SQL_FLOAT ;b:sizeof(SQLDOUBLE) ;e: SQL_DOUBLE),
  768. (T:SQL_REAL ;b:sizeof(SQLDOUBLE) ;e: SQL_DOUBLE),
  769. (T:SQL_DOUBLE ;b:Sizeof(SQLDOUBLE) ;e: SQL_DOUBLE),
  770. (T:SQL_DATE ;b:Sizeof(SQL_DATE_STRUCT) ;e: SQL_DATE),
  771. (T:SQL_TIME ;b:sizeof(SQL_TIME_STRUCT) ;e: SQL_TIME),
  772. (T:SQL_TIMESTAMP ;b:sizeof(SQL_TIMESTAMP_STRUCT) ;e: SQL_TIMESTAMP),
  773. (T:SQL_VARCHAR ;b:-1 ;e: SQL_CHAR),
  774. (T:SQL_UNKNOWN_TYPE ;b:0 ;e: SQL_UNKNOWN_TYPE),
  775. (T:SQL_LONGVARCHAR ;b:-1 ;e: SQL_CHAR),
  776. (T:SQL_BINARY ;b:-2 ;e: SQL_BINARY),
  777. (T:SQL_VARBINARY ;b:-2 ;e: SQL_BINARY),
  778. (T:SQL_LONGVARBINARY ;b:-2 ;e: SQL_BINARY),
  779. (T:SQL_BIGINT ;b:sizeOf(SQLDOUBLE) ;e: SQL_DOUBLE),
  780. (T:SQL_TINYINT ;b:Sizeof(SQLSMALLINT) ;e: SQL_SMALLINT),
  781. (T:SQL_BIT ;b:sizeof(SQL_CHAR) ;e: SQL_BIT),
  782. (T:SQL_WCHAR ;b:-1 ;e: SQL_CHAR),
  783. (T:SQL_WVARCHAR ;b:-1 ;e: SQL_CHAR),
  784. (T:SQL_WLONGVARCHAR ;b:-1 ;e: SQL_CHAR),
  785. (T:SQL_TYPE_DATE ;b:sizeof(SQL_DATE_STRUCT) ;e: SQL_TYPE_DATE),
  786. (T:SQL_TYPE_TIME ;b:sizeof(SQL_TIME_STRUCT) ;e: SQL_TYPE_TIME),
  787. (T:SQL_TYPE_TIMESTAMP;b:sizeof(SQL_TIMESTAMP_STRUCT) ;e: SQL_TYPE_TIMESTAMP)
  788. );
  789. { // template
  790. (T: ;b: ;e: ),
  791. }
  792. Function GetColSizeBufType (Coltype: SQLSmallint;
  793. Var BufSize : SQLInteger;
  794. Var BufType : SQLSmallInt) : Boolean;
  795. Var
  796. I : Integer;
  797. begin
  798. I:=0;
  799. BufSize:=0;
  800. BufType:=0;
  801. While (I<=BufDescrCount) and (BufDescr[i].t<>Coltype) do
  802. Inc(i);
  803. Result:=(i<=BufDescrCount);
  804. If Result then
  805. begin
  806. BufSize:=BufDescr[i].b;
  807. BufType:=BufDescr[i].e;
  808. end;
  809. end;
  810. procedure TODBCStatement.BindFields(RestrictList : TStrings);
  811. Var
  812. Count: SQLSmallInt;
  813. CName : Array[0..SQL_NAME_LEN] of Char;
  814. CSize : SQLUINTEGER;
  815. CDataType,CDecimals,CNullable,CNameLen: SQLSmallInt;
  816. I : integer;
  817. begin
  818. CheckODBC(SQLNumResultCols(Handle,Count),SErrColumnCount);
  819. For I:=1 to Count do
  820. begin
  821. CheckODBC(SQLDescribeCol(Handle,i,CName,SQL_NAME_LEN,CNameLen,
  822. CdataType,CSize, CDecimals,CNullable)
  823. ,SErrColDescription);
  824. If Not Assigned(RestrictList) or (RestrictList.IndexOf(Cname)<>-1) then
  825. With FFields.Add as TODBCField do
  826. begin
  827. FPosition:=I;
  828. FName:=Cname;
  829. FDataType:=CDataType;
  830. FSize:=CSize;
  831. FDecimalDigits:=CDecimals;
  832. FNullable:=(CNullable=SQL_TRUE);
  833. GetColsizeBufType(FDataType,FBufSize,FBufType);
  834. If FBufSize=-1 then
  835. FBufSize:=FSize;
  836. end;
  837. end;
  838. AllocBuffers;
  839. For I:=0 to Count-1 do
  840. With FFields.Items[i] as TODBCField do
  841. CheckODBC(SQLBindCol(Handle,FPosition,FBufType,GetData,FBufSize,FBuffer+FBuffOffset)
  842. ,SErrBindCol);
  843. end;
  844. procedure TODBCStatement.ClearFields;
  845. begin
  846. FFields.Clear;
  847. end;
  848. constructor TODBCStatement.Create(Aowner: TComponent);
  849. begin
  850. FHandleType:=SQL_HANDLE_STMT;
  851. inherited;
  852. If AOwner is TODBCConnection then
  853. Connection:=TODBCConnection(Aowner);
  854. FFields:=TODBCFieldList.Create(Self);
  855. end;
  856. function TODBCStatement.ParentHandle: SQLHandle;
  857. begin
  858. If (Connection=Nil) then
  859. ODBCError(SErrNoConnectionForStatement);
  860. Result:=Connection.Handle;
  861. end;
  862. procedure TODBCStatement.SetConnection(const Value: TODBCConnection);
  863. begin
  864. If Value<>FConnection then
  865. begin
  866. If HandleAllocated then
  867. FreeHandle;
  868. FConnection := Value;
  869. end;
  870. end;
  871. Function TODBCStatement.fetch : Boolean;
  872. Var
  873. res : SQLReturn;
  874. begin
  875. Res:=SQLFetch(Handle);
  876. Result:=(Res=SQL_SUCCESS);
  877. If Not Result and (Res<>SQL_NO_DATA) then
  878. CheckODBC(Res,SErrFetchingData);
  879. FBof:=False;
  880. If (Res=SQL_NO_DATA) then
  881. FEOF:=True;
  882. end;
  883. destructor TODBCStatement.Destroy;
  884. begin
  885. FFields.Free;
  886. inherited;
  887. end;
  888. { TODBCSQLStatement }
  889. procedure TODBCSQLStatement.GetFieldList(List : TStrings);
  890. Var
  891. Count: SQLSmallInt;
  892. CName : Array[0..SQL_NAME_LEN] of Char;
  893. CSize : SQLUINTEGER;
  894. CDataType,CDecimals,CNullable,CNameLen: SQLSmallInt;
  895. I : integer;
  896. begin
  897. if Not (FState in [ssPrepared,ssBound,ssOpen]) then
  898. ODBCError(SErrNotPrepared);
  899. List.Clear;
  900. CheckODBC(SQLNumResultCols(Handle,Count),SErrColumnCount);
  901. For I:=1 to Count do
  902. begin
  903. CheckODBC(SQLDescribeCol(Handle,i,CName,SQL_NAME_LEN,CNameLen,
  904. CdataType,CSize, CDecimals,CNullable)
  905. ,SErrColDescription);
  906. List.Add(CName);
  907. end;
  908. end;
  909. procedure TODBCSQLStatement.Unprepare;
  910. begin
  911. Case FState of
  912. ssBound,ssOpen :
  913. begin
  914. ClearFields;
  915. FreeStatement(SQL_CLOSE);
  916. end;
  917. ssPrepared : begin
  918. FreeStatement(SQL_CLOSE);
  919. end;
  920. end;
  921. FState:=ssInactive;
  922. end;
  923. procedure TODBCSQLStatement.FreeStatement(Option : SQLUSMALLINT);
  924. begin
  925. SQLFreeStmt(Handle,SQL_CLOSE);
  926. end;
  927. procedure TODBCSQLStatement.Close;
  928. begin
  929. if FState<>ssInactive then
  930. begin
  931. Unprepare;
  932. FreeStatement(SQL_CLOSE);
  933. FState:=ssInactive;
  934. end;
  935. end;
  936. constructor TODBCSQLStatement.Create(Aowner: TComponent);
  937. begin
  938. inherited;
  939. FSQL:=TStringList.Create;
  940. end;
  941. destructor TODBCSQLStatement.Destroy;
  942. begin
  943. if FState=ssOpen then
  944. Close
  945. else If FState<>ssInactive then
  946. Unprepare;
  947. FSQL.Free;
  948. inherited;
  949. end;
  950. procedure TODBCSQLStatement.ExecSQL;
  951. begin
  952. Case FState of
  953. ssPrepared,ssBound : ExecutePrepared;
  954. ssInactive : ExecuteDirect;
  955. else
  956. Raise Exception.Create(SErrStatementActive)
  957. end;
  958. end;
  959. procedure TODBCSQLStatement.ExecuteDirect;
  960. Var
  961. S : String;
  962. begin
  963. if FState<>ssInactive then
  964. ODBCError(SErrStatementActive);
  965. S:=SQL.Text;
  966. CheckODBC(SQLExecDirect(Handle,PChar(S),SQL_NTS),SErrExecuting);
  967. end;
  968. procedure TODBCSQLStatement.ExecutePrepared;
  969. begin
  970. if Not (FState in [ssPrepared,ssBound]) then
  971. ODBCError(SErrNotPrepared);
  972. CheckODBC(SQLExecute(Handle),SErrExecutingPrepared);
  973. end;
  974. function TODBCSQLStatement.GetActive: Boolean;
  975. begin
  976. Result:=(FState=ssOpen);
  977. end;
  978. procedure TODBCSQLStatement.Open;
  979. begin
  980. if (FState<>ssOpen) then
  981. begin
  982. Writeln('Preparing');
  983. If FState=ssInactive then
  984. Prepare;
  985. Writeln('Bind fields');
  986. if FState=ssPrepared then
  987. BindFields(Nil);
  988. Writeln('Executing');
  989. ExecSQL;
  990. Writeln('Fetching');
  991. If FState=ssBound then
  992. Fetch;
  993. FState:=ssOpen;
  994. FBOF:=True;
  995. end;
  996. end;
  997. procedure TODBCSQLStatement.Prepare;
  998. Var
  999. S : String;
  1000. begin
  1001. If FState<>ssInactive then
  1002. ODBCError(SErrNotInactive);
  1003. If (FSQL.Count=0) then
  1004. ODBCError(SErrNoSQLStatement);
  1005. S:=FSQL.Text;
  1006. CheckODBC(SQLPrepare(Handle,PChar(S),SQL_NTS),SErrPreparing);
  1007. FState:=ssPrepared;
  1008. end;
  1009. procedure TODBCSQLStatement.SetActive(const Value: Boolean);
  1010. begin
  1011. If Value then
  1012. Open
  1013. else
  1014. Close;
  1015. end;
  1016. procedure TODBCSQLStatement.SetSQL(const Value: TStrings);
  1017. begin
  1018. FSQL.Assign(Value);
  1019. end;
  1020. procedure TODBCSQLStatement.BindFields(RestrictList: TStrings);
  1021. begin
  1022. inherited;
  1023. FState:=ssBound;
  1024. end;
  1025. procedure TODBCStatement.AllocBuffers;
  1026. Var
  1027. I,TotalSize,AddSize : Integer;
  1028. begin
  1029. TotalSize:=0;
  1030. For i:=0 to FFields.Count-1 do
  1031. With (FFields.Items[i] as TODBCField) do
  1032. begin
  1033. AddSize:=FBufSize;
  1034. If FBufSize=-2 then // Blob.
  1035. AddSize:=0
  1036. else if FBufSize=-1 then
  1037. AddSize:=FSize+1; // some Char variant.
  1038. // Store offset temporarily in FData
  1039. FBuffOffset:=TotalSize;
  1040. Inc(TotalSize,AddSize+SizeOf(SQLinteger));
  1041. end;
  1042. FBuffer:=GetMem(TotalSize);
  1043. TotalSize:=0;
  1044. For i:=0 to FFields.Count-1 do
  1045. With (FFields.Items[i] as TODBCField) do
  1046. FBuffer:=Self.FBuffer;
  1047. end;
  1048. { TODBCTableList }
  1049. procedure TODBCTableList.GetTableNames(S: TStrings; SystemTables : Boolean);
  1050. var
  1051. TName,
  1052. TType: array[0..SQL_NAME_LEN+1] of char;
  1053. NL,TL: SQLINTEGER;
  1054. Res: SQLRETURN;
  1055. begin
  1056. S.Clear;
  1057. Res:=CheckODBC(SQLTables(handle, nil,0,nil,0,nil,0,nil,0),SErrGettingTableNames);
  1058. if Res=SQL_SUCCESS then
  1059. begin
  1060. // Must bind by colno, because names changed between ODBC 2.0 and 3.0 !!
  1061. SQLBindCol(handle,3,SQL_CHAR,@TName,SQL_NAME_LEN,@NL);
  1062. SQLBindCol(handle,4,SQL_CHAR,@TType,SQL_NAME_LEN,@TL);
  1063. While Fetch do
  1064. if SystemTables or (CompareText(TType,'SYSTEM TABLE')<>0) then
  1065. S.Add(TName);
  1066. end;
  1067. end;
  1068. { TODBCFieldNamesList }
  1069. procedure TODBCFieldNamesList.GetFieldNames(TableName: String;
  1070. S: TStrings);
  1071. var
  1072. FName : array[0..SQL_NAME_LEN+1] of char;
  1073. NF : SQLINTEGER;
  1074. Res: SQLRETURN;
  1075. begin
  1076. S.Clear;
  1077. Res:=CheckODBC(SQLColumns(handle, nil, 0, nil, 0, pchar(TableName), SQL_NTS, nil, 0),SErrFieldNames);
  1078. if Res=SQL_SUCCESS then
  1079. begin
  1080. SQLBindCol(handle, 4, SQL_CHAR, @FNAme, SQL_NAME_LEN, @NF);
  1081. While Fetch do
  1082. S.Add(FName);
  1083. end;
  1084. end;
  1085. { TODBCPrimaryKeyFieldsList }
  1086. procedure TODBCPrimaryKeyFieldsList.GetPrimaryKeyFields(TableName: String;
  1087. S: TStrings);
  1088. var
  1089. FName : array[0..SQL_NAME_LEN+1] of char;
  1090. NF : SQLINTEGER;
  1091. Res: SQLRETURN;
  1092. begin
  1093. S.Clear;
  1094. Res:=CheckODBC(SQLPrimaryKeys(handle, nil, 0, nil, 0, pchar(TableName), SQL_NTS),SErrPrimaryKeys);
  1095. if Res=SQL_SUCCESS then
  1096. begin
  1097. SQLBindCol(handle, 4, SQL_CHAR, @FNAme, SQL_NAME_LEN, @NF);
  1098. While Fetch do
  1099. S.Add(FName);
  1100. end;
  1101. end;
  1102. { TODBCProcedureList }
  1103. procedure TODBCProcedureList.GetProcedureList(S: TStrings);
  1104. var
  1105. PName : array[0..SQL_NAME_LEN+1] of char;
  1106. NP : SQLINTEGER;
  1107. Res: SQLRETURN;
  1108. begin
  1109. S.Clear;
  1110. Res:=CheckODBC(SQLProcedures(handle, nil, 0, nil, 0, Nil, 0),SErrProcedureNames);
  1111. if Res=SQL_SUCCESS then
  1112. begin
  1113. SQLBindCol(handle, 3, SQL_CHAR, @PNAme, SQL_NAME_LEN, @NP);
  1114. While Fetch do
  1115. S.Add(PName);
  1116. end;
  1117. end;
  1118. { TODBCProcedureParams }
  1119. procedure TODBCProcedureParams.GetProcedureParams(ProcName: String;
  1120. ParamTypes: TODBCParamTypes; S: TStrings);
  1121. var
  1122. PName : array[0..SQL_NAME_LEN+1] of char;
  1123. NP,NT : SQLINTEGER;
  1124. Ptype : SQLSmallInt;
  1125. Res: SQLRETURN;
  1126. begin
  1127. S.Clear;
  1128. Res:=CheckODBC(SQLProcedureColumns(handle, nil, 0, nil, 0, PChar(ProcName),SQL_NTS,Nil, 0),SErrProcedureNames);
  1129. if Res=SQL_SUCCESS then
  1130. begin
  1131. SQLBindCol(handle, 4, SQL_CHAR, @PName, SQL_NAME_LEN, @NP);
  1132. SQLBindCol(handle, 5, SQL_SMALLINT, @PType, SizeOf(SQLSmallInt), @NT);
  1133. While Fetch do
  1134. begin
  1135. If TODBCParamType(PType) in ParamTypes then
  1136. S.Add(PName);
  1137. end;
  1138. end;
  1139. end;
  1140. { TODBCFieldList }
  1141. constructor TODBCFieldList.Create(Statement: TODBCStatement);
  1142. begin
  1143. FStatement:=Statement;
  1144. Inherited Create(TODBCField);
  1145. end;
  1146. { TODBCField }
  1147. function TODBCField.GetAsString: String;
  1148. begin
  1149. If IsNull then
  1150. Result:=''
  1151. else
  1152. Case FBufType of
  1153. SQL_Smallint : Result:=IntToStr(PSQLSmallInt(Data)^);
  1154. SQL_Integer : Result:=IntToStr(PSQLINTEGER(Data)^);
  1155. SQL_BIT : Result:=IntToStr(PByte(Data)^);
  1156. SQL_CHAR : Result:=StrPas(Data);
  1157. SQL_DOUBLE : Result:=FloatToStr(GetAsDouble);
  1158. SQL_DATE : result:=DateToStr(AsDateTime);
  1159. SQL_TIME : Result:=TimeToStr(AsDateTime);
  1160. SQL_TIMESTAMP : result:=datetimeToStr(AsDateTime);
  1161. SQL_TYPE_DATE : result:=dateToStr(AsDateTime);
  1162. SQL_TYPE_TIMESTAMP : result:=datetimeToStr(AsDateTime);
  1163. SQL_TYPE_TIME : Result:=TimeToStr(AsDateTime);
  1164. else
  1165. ODBCError(SErrInvalidConversion)
  1166. end;
  1167. end;
  1168. function TODBCField.GetData : Pchar;
  1169. begin
  1170. Result:=FBuffer+FBuffOffset+SizeOf(SQLinteger);
  1171. end;
  1172. function TODBCField.GetIsNull : boolean;
  1173. begin
  1174. Result:=PSQLinteger(FBuffer+FBuffOffset)^=SQL_NULL_DATA;
  1175. end;
  1176. Function TODBCField.GetAsInteger : Integer;
  1177. begin
  1178. If IsNull then
  1179. Result:=0
  1180. else
  1181. Case FBufType of
  1182. SQL_Smallint : Result:=PSQLSmallInt(Data)^;
  1183. SQL_Integer : Result:=PSQLINTEGER(Data)^;
  1184. SQL_BIT : Result:=PByte(Data)^;
  1185. SQL_CHAR : Result:=StrToInt(GetAsString);
  1186. SQL_DOUBLE : Result:=Round(GetAsDouble);
  1187. SQL_DATE,
  1188. SQL_TIME,
  1189. SQL_TIMESTAMP,
  1190. SQL_TYPE_DATE,
  1191. SQL_TYPE_TIMESTAMP,
  1192. SQL_TYPE_TIME : Result:=Round(AsDateTime);
  1193. else
  1194. ODBCError(SErrInvalidConversion)
  1195. end;
  1196. end;
  1197. Function TODBCField.GetAsBoolean : Boolean;
  1198. begin
  1199. If IsNull then
  1200. Result:=False
  1201. else
  1202. Case FBufType of
  1203. SQL_Smallint : Result:=PSQLSmallInt(Data)^=0;
  1204. SQL_Integer : Result:=PSQLINTEGER(Data)^=0;
  1205. SQL_BIT : Result:=PBYTE(Data)^=0;
  1206. SQL_CHAR : Result:=(StrToInt(GetAsString)=0);
  1207. SQL_DOUBLE : Result:=Round(GetAsDouble)=0;
  1208. SQL_DATE,
  1209. SQL_TIME,
  1210. SQL_TIMESTAMP,
  1211. SQL_TYPE_DATE,
  1212. SQL_TYPE_TIMESTAMP,
  1213. SQL_TYPE_TIME : Result:=Round(AsDateTime)=0;
  1214. else
  1215. ODBCError(SErrInvalidConversion)
  1216. end;
  1217. end;
  1218. Function TODBCField.GetAsDouble : Double;
  1219. begin
  1220. If IsNull then
  1221. Result:=0
  1222. else
  1223. Case FBufType of
  1224. SQL_Smallint : Result:=PSQLSmallInt(Data)^;
  1225. SQL_Integer : Result:=PSQLINTEGER(Data)^;
  1226. SQL_BIT : Result:=PBYTE(Data)^;
  1227. SQL_CHAR : Result:=StrToFloat(GetAsString);
  1228. SQL_DOUBLE : Result:=PSQLDOUBLE(GetData)^;
  1229. SQL_DATE,
  1230. SQL_TIME,
  1231. SQL_TIMESTAMP,
  1232. SQL_TYPE_DATE,
  1233. SQL_TYPE_TIMESTAMP,
  1234. SQL_TYPE_TIME : Result:=AsDateTime;
  1235. else
  1236. ODBCError(SErrInvalidConversion)
  1237. end;
  1238. end;
  1239. {
  1240. function DateStructToDateTime( b:PSQL_DATE_STRUCT):TDateTime;
  1241. function DateTimeToDateStruct( b:TDateTime):SQL_DATE_STRUCT;
  1242. procedure DateTime2TimeStampStruct( var Value:SQL_TIMESTAMP_STRUCT; b:TDateTime);
  1243. }
  1244. Function TODBCField.GetAsDateTime : TDateTime;
  1245. begin
  1246. If IsNull then
  1247. Result:=0
  1248. else
  1249. Case FBufType of
  1250. SQL_Smallint : Result:=PSQLSmallInt(Data)^;
  1251. SQL_Integer : Result:=PSQLINTEGER(Data)^;
  1252. SQL_BIT : Result:=PBYTE(Data)^;
  1253. SQL_CHAR : Result:=StrToInt(GetAsString);
  1254. SQL_DOUBLE : Result:=PSQLDOUBLE(GetData)^;
  1255. SQL_DATE : Result:=DateStructToDateTime(PSQL_DATE_STRUCT(Data));
  1256. SQL_TIME : Result:=TimeStructToDateTime(PSQL_TIME_STRUCT(Data));
  1257. SQL_TIMESTAMP : Result:=TimeStampStructToDateTime(PSQL_TIMESTAMP_STRUCT(Data));
  1258. SQL_TYPE_DATE : Result:=DateStructToDateTime(PSQL_DATE_STRUCT(Data));
  1259. SQL_TYPE_TIMESTAMP : Result:=TimeStampStructToDateTime(PSQL_TIMESTAMP_STRUCT(Data));
  1260. SQL_TYPE_TIME : Result:=TimeStructToDateTime(PSQL_TIME_STRUCT(Data));
  1261. else
  1262. ODBCError(SErrInvalidConversion)
  1263. end;
  1264. end;
  1265. Finalization
  1266. If Assigned(DefEnv) then
  1267. TODBCEnvironment(DefEnv).Free;
  1268. end.