fpodbc.pp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464
  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.