Logo ROOT  
Reference Guide
TOracleServer.cxx
Go to the documentation of this file.
1// @(#)root/oracle:$Id$
2// Author: Yan Liu and Shaowen Wang 23/11/04
3
4/*************************************************************************
5 * Copyright (C) 1995-2005, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TOracleServer //
15// //
16// This class implements an OCCI interface to Oracle data bases. //
17// It uses the instantclient10 software available from Oracle. //
18// To install this client software do: //
19// 1) Download Instant Client Packages (4 files) from: //
20// http://www.oracle.com/technology/software/tech/oci/instantclient/index.html
21// 2) Unzip the files into instantclient10_2 (Mac OS X example here): //
22// unzip instantclient-basic-macosx-10.2.0.4.zip //
23// unzip instantclient-sqlplus-macosx-10.2.0.4.zip //
24// unzip instantclient-sdk-macosx-10.2.0.4.zip //
25// unzip instantclient-jdbc-macosx-10.2.0.4.zip //
26// 3) Create two symbolic links for the files that have the version //
27// appended: //
28// ln -s libclntsh.dylib.10.1 libclntsh.dylib //
29// ln -s libocci.dylib.10.1 libocci.dylib //
30// 4) Add instantclient10_1 directory to your (DY)LD_LIBRARY_PATH //
31// in your .profile: //
32// export (DY)LD_LIBRARY_PATH="<pathto>/instantclient10_2" //
33// Use DY only on Mac OS X. //
34// 5) If you also want to use the sqlplus command line app add also //
35// export SQLPATH="<pathto>/instantclient10_2" //
36// 6) If you want to connect to a remote db server you will also need //
37// to create a tnsname.ora file which describes the local_name for //
38// the remote db servers (at CERN most public machines have this //
39// file in /etc). If it is not in /etc create TNS_ADMIN: //
40// export TNS_ADMIN="<path-to-dir-containing-tnsname.ora>" //
41// 7) Test it our with the sqlplus command line app: //
42// sqlplus [username][/password]@<local_name> //
43// or //
44// sqlplus [username][/password]@//[hostname][:port][/database] //
45// //
46//////////////////////////////////////////////////////////////////////////
47
48
49#include "TOracleServer.h"
50#include "TOracleResult.h"
51#include "TOracleStatement.h"
52#include "TSQLColumnInfo.h"
53#include "TSQLTableInfo.h"
54#include "TUrl.h"
55#include "TList.h"
56#include "TObjString.h"
57
59
60using namespace std;
61using namespace oracle::occi;
62
63const char* TOracleServer::fgDatimeFormat = "MM/DD/YYYY, HH24:MI:SS";
64
65
66// Reset error and check that server connected
67#define CheckConnect(method, res) \
68 ClearError(); \
69 if (!IsConnected()) { \
70 SetError(-1,"Oracle database is not connected",method); \
71 return res; \
72 }
73
74// catch Oracle exception after try block
75#define CatchError(method) \
76 catch (SQLException &oraex) { \
77 SetError(oraex.getErrorCode(), oraex.getMessage().c_str(), method); \
78 }
79
80////////////////////////////////////////////////////////////////////////////////
81/// Open a connection to a Oracle DB server. The db arguments should be
82/// of the form "oracle://connection_identifier[/<database>]", e.g.:
83/// "oracle://cmscald.fnal.gov/test". The uid is the username and pw
84/// the password that should be used for the connection.
85
86TOracleServer::TOracleServer(const char *db, const char *uid, const char *pw)
87{
88 if (gDebug>0) {
89 // this code is necessary to guarantee, that libclntsh.so will be
90 // linked to libOracle.so.
91 sword major_version(0), minor_version(0), update_num(0), patch_num(0), port_update_num(0);
92 OCIClientVersion(&major_version, &minor_version, &update_num, &patch_num, &port_update_num);
93 Info("TOracleServer","Oracle Call Interface version %u.%u.%u.%u.%u",
94 (unsigned) major_version, (unsigned) minor_version, (unsigned) update_num, (unsigned) patch_num, (unsigned) port_update_num);
95 }
96
97 TUrl url(db);
98
99 if (!url.IsValid()) {
100 TString errmsg = "Malformed db argument ";
101 errmsg+=db;
102 SetError(-1, errmsg.Data(), "TOracleServer");
103 MakeZombie();
104 return;
105 }
106
107 if (strncmp(url.GetProtocol(), "oracle", 6)) {
108 SetError(-1, "protocol in db argument should be oracle://", "TOracleServer");
109 MakeZombie();
110 return;
111 }
112
113 const char *conn_str = url.GetFile();
114 if (conn_str)
115 if (*conn_str == '/') conn_str++; //skip leading "/" if appears
116
117 try {
118 // found out whether to use objet mode
119 TString options = url.GetOptions();
120 Int_t pos = options.Index("ObjectMode");
121 // create environment accordingly
122 if (pos != kNPOS) {
123 fEnv = Environment::createEnvironment(Environment::OBJECT);
124 } else {
125 fEnv = Environment::createEnvironment();
126 }
127 fConn = fEnv->createConnection(uid, pw, conn_str ? conn_str : "");
128
129 fType = "Oracle";
130 fHost = url.GetHost();
131 fDB = conn_str;
132 fPort = url.GetPort();
133 fPort = (fPort>0) ? fPort : 1521;
134 return;
135
136 } CatchError("TOracleServer")
137
138 MakeZombie();
139}
140
141////////////////////////////////////////////////////////////////////////////////
142/// Close connection to Oracle DB server.
143
145{
146 if (IsConnected())
147 Close();
148}
149
150
151////////////////////////////////////////////////////////////////////////////////
152/// Close connection to Oracle DB server.
153
155{
156 ClearError();
157
158 try {
159 if (fConn)
160 fEnv->terminateConnection(fConn);
161 if (fEnv)
162 Environment::terminateEnvironment(fEnv);
163 } CatchError("Close")
164
165 fPort = -1;
166}
167
168////////////////////////////////////////////////////////////////////////////////
169
171{
172 CheckConnect("Statement",0);
173
174 if (!sql || !*sql) {
175 SetError(-1, "no query string specified","Statement");
176 return nullptr;
177 }
178
179 try {
180 oracle::occi::Statement *stmt = fConn->createStatement(sql);
181
182 Blob parblob(fConn);
183
184 return new TOracleStatement(fEnv, fConn, stmt, niter, fErrorOut);
185
186 } CatchError("Statement")
187
188 return nullptr;
189}
190
191////////////////////////////////////////////////////////////////////////////////
192/// Execute SQL command. Result object must be deleted by the user.
193/// Returns a pointer to a TSQLResult object if successful, 0 otherwise.
194
196{
197 CheckConnect("Query",0);
198
199 if (!sql || !*sql) {
200 SetError(-1, "no query string specified","Query");
201 return nullptr;
202 }
203
204 try {
205 oracle::occi::Statement *stmt = fConn->createStatement();
206
207 // NOTE: before special COUNT query was executed to define number of
208 // rows in result set. Now it is not required, while TOracleResult class
209 // will automatically fetch all rows from result set when
210 // GetRowCount() will be called first time.
211 // It is better do not use GetRowCount() to avoid unnecessary memory usage.
212
213 stmt->setSQL(sql);
214 stmt->setPrefetchRowCount(1000);
215 stmt->setPrefetchMemorySize(1000000);
216 stmt->execute();
217
218 TOracleResult *res = new TOracleResult(fConn, stmt);
219 return res;
220 } CatchError("Query")
221
222 return nullptr;
223}
224
225////////////////////////////////////////////////////////////////////////////////
226/// Execute sql command which does not produce any result set.
227/// Return kTRUE if successful
228
230{
231 CheckConnect("Exec", kFALSE);
232
233 if (!sql || !*sql) {
234 SetError(-1, "no query string specified","Exec");
235 return kFALSE;
236 }
237
238 oracle::occi::Statement *stmt = nullptr;
239
240 Bool_t res = kFALSE;
241
242 try {
243 stmt = fConn->createStatement(sql);
244 stmt->execute();
245 res = kTRUE;
246 } CatchError("Exec")
247
248 try {
249 fConn->terminateStatement(stmt);
250 } CatchError("Exec")
251
252 return res;
253}
254
255////////////////////////////////////////////////////////////////////////////////
256/// List all tables in the specified database. Wild is for wildcarding
257/// "t%" list all tables starting with "t".
258/// Returns a pointer to a TSQLResult object if successful, 0 otherwise.
259/// The result object must be deleted by the user.
260
261TSQLResult *TOracleServer::GetTables(const char *dbname, const char * /*wild*/)
262{
263 // In Oracle 9 and above, table is accessed in schema.table format.
264 // GetTables returns tables in all schemas accessible for the user.
265 // Assumption: table ALL_OBJECTS is accessible for the user, which is true in Oracle 10g
266 // The returned TSQLResult has two columns: schema_name, table_name
267 // "dbname": if specified, return table list of this schema, or return all tables
268 // "wild" is not used in this implementation
269
270 CheckConnect("GetTables",0);
271
272 TString sqlstr("SELECT object_name,owner FROM ALL_OBJECTS WHERE object_type='TABLE'");
273 if (dbname && dbname[0])
274 sqlstr = sqlstr + " AND owner='" + dbname + "'";
275
276 return Query(sqlstr.Data());
277}
278
279////////////////////////////////////////////////////////////////////////////////
280
282{
283 CheckConnect("GetTablesList",0);
284
285 TString cmd("SELECT table_name FROM user_tables");
286 if ((wild!=0) && (*wild!=0))
287 cmd+=Form(" WHERE table_name LIKE '%s'", wild);
288
289 TSQLStatement* stmt = Statement(cmd);
290 if (!stmt) return nullptr;
291
292 TList *lst = nullptr;
293
294 if (stmt->Process()) {
295 stmt->StoreResult();
296 while (stmt->NextResultRow()) {
297 const char* tablename = stmt->GetString(0);
298 if (!tablename) continue;
299 if (!lst) {
300 lst = new TList;
301 lst->SetOwner(kTRUE);
302 }
303 lst->Add(new TObjString(tablename));
304 }
305 }
306
307 delete stmt;
308
309 return lst;
310}
311
312////////////////////////////////////////////////////////////////////////////////
313/// Produces SQL table info
314/// Object must be deleted by user
315
317{
318 CheckConnect("GetTableInfo",0);
319
320 if (!tablename || (*tablename==0)) return nullptr;
321
322 TString table(tablename);
323 table.ToUpper();
324 TString sql;
325 sql.Form("SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, NULLABLE, CHAR_COL_DECL_LENGTH FROM user_tab_columns WHERE table_name = '%s' ORDER BY COLUMN_ID", table.Data());
326
327 TSQLStatement* stmt = Statement(sql.Data(), 10);
328 if (!stmt) return nullptr;
329
330 if (!stmt->Process()) {
331 delete stmt;
332 return nullptr;
333 }
334
335 TList *lst = nullptr;
336
337 stmt->StoreResult();
338
339 while (stmt->NextResultRow()) {
340 const char* columnname = stmt->GetString(0);
341 TString data_type = stmt->GetString(1);
342 Int_t data_length = stmt->GetInt(2); // this is size in bytes
343 Int_t data_precision = stmt->GetInt(3);
344 Int_t data_scale = stmt->GetInt(4);
345 const char* nstr = stmt->GetString(5);
346 Int_t char_col_decl_length = stmt->GetInt(6);
347 Int_t data_sign = -1; // no info about sign
348
349 Int_t sqltype = kSQL_NONE;
350
351 if (data_type=="NUMBER") {
352 sqltype = kSQL_NUMERIC;
353 if (data_precision<=0) {
354 data_precision = -1;
355 data_scale = -1;
356 } else
357 if (data_scale<=0)
358 data_scale = -1;
359 data_sign = 1;
360 } else
361
362 if (data_type=="CHAR") {
363 sqltype = kSQL_CHAR;
364 data_precision = char_col_decl_length;
365 data_scale = -1;
366 } else
367
368 if ((data_type=="VARCHAR") || (data_type=="VARCHAR2")) {
369 sqltype = kSQL_VARCHAR;
370 data_precision = char_col_decl_length;
371 data_scale = -1;
372 } else
373
374 if (data_type=="FLOAT") {
375 sqltype = kSQL_FLOAT;
376 data_scale = -1;
377 if (data_precision==126) data_precision = -1;
378 data_sign = 1;
379 } else
380
381 if (data_type=="BINARY_FLOAT") {
382 sqltype = kSQL_FLOAT;
383 data_scale = -1;
384 data_precision = -1;
385 data_sign = 1;
386 } else
387
388 if (data_type=="BINARY_DOUBLE") {
389 sqltype = kSQL_DOUBLE;
390 data_scale = -1;
391 data_precision = -1;
392 data_sign = 1;
393 } else
394
395 if (data_type=="LONG") {
396 sqltype = kSQL_VARCHAR;
397 data_length = 0x7fffffff; // size of LONG 2^31-1
398 data_precision = -1;
399 data_scale = -1;
400 } else
401
402 if (data_type.Contains("TIMESTAMP")) {
403 sqltype = kSQL_TIMESTAMP;
404 data_precision = -1;
405 }
406
407 Bool_t IsNullable = kFALSE;
408 if (nstr!=0)
409 IsNullable = (*nstr=='Y') || (*nstr=='y');
410
411 TSQLColumnInfo* info =
412 new TSQLColumnInfo(columnname,
413 data_type,
414 IsNullable,
415 sqltype,
416 data_length,
417 data_precision,
418 data_scale,
419 data_sign);
420
421 if (!lst) lst = new TList;
422 lst->Add(info);
423 }
424
425 delete stmt;
426
427 return new TSQLTableInfo(tablename, lst);
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// List all columns in specified table in the specified database.
432/// Wild is for wildcarding "t%" list all columns starting with "t".
433/// Returns a pointer to a TSQLResult object if successful, 0 otherwise.
434/// The result object must be deleted by the user.
435
436TSQLResult *TOracleServer::GetColumns(const char * /*dbname*/, const char *tablename,
437 const char * wild)
438{
439 CheckConnect("GetColumns",0);
440
441// make no sense, while method is not implemented
442// if (SelectDataBase(dbname) != 0) {
443// SetError(-1, "Database is not connected","GetColumns");
444// return nullptr;
445// }
446
447 TString sql;
448 TString table(tablename);
449 table.ToUpper();
450 if (wild && wild[0])
451 sql.Form("select COLUMN_NAME, concat(concat(concat(data_type,'('),data_length),')') \"Type\" FROM user_tab_columns WHERE table_name like '%s' ORDER BY COLUMN_ID", wild);
452 else
453 sql.Form("select COLUMN_NAME, concat(concat(concat(data_type,'('),data_length),')') \"Type\" FROM user_tab_columns WHERE table_name = '%s' ORDER BY COLUMN_ID", table.Data());
454 return Query(sql);
455}
456
457////////////////////////////////////////////////////////////////////////////////
458/// Select a database. Returns 0 if successful, non-zero otherwise.
459/// NOT IMPLEMENTED.
460
461Int_t TOracleServer::SelectDataBase(const char * /*dbname*/)
462{
463 CheckConnect("SelectDataBase", -1);
464
465 // do nothing and return success code
466 return 0;
467}
468
469////////////////////////////////////////////////////////////////////////////////
470/// List all available databases. Wild is for wildcarding "t%" list all
471/// databases starting with "t".
472/// Returns a pointer to a TSQLResult object if successful, 0 otherwise.
473/// The result object must be deleted by the user.
474/// NOT IMPLEMENTED.
475
477{
478 CheckConnect("GetDataBases",0);
479
480 return nullptr;
481}
482
483////////////////////////////////////////////////////////////////////////////////
484/// Create a database. Returns 0 if successful, non-zero otherwise.
485/// NOT IMPLEMENTED.
486
487Int_t TOracleServer::CreateDataBase(const char * /*dbname*/)
488{
489 CheckConnect("CreateDataBase",-1);
490
491 return -1;
492}
493
494////////////////////////////////////////////////////////////////////////////////
495/// Drop (i.e. delete) a database. Returns 0 if successful, non-zero
496/// otherwise.
497/// NOT IMPLEMENTED.
498
499Int_t TOracleServer::DropDataBase(const char * /*dbname*/)
500{
501 CheckConnect("DropDataBase",-1);
502
503 return -1;
504}
505
506////////////////////////////////////////////////////////////////////////////////
507/// Reload permission tables. Returns 0 if successful, non-zero
508/// otherwise. User must have reload permissions.
509/// NOT IMPLEMENTED.
510
512{
513 CheckConnect("Reload", -1);
514
515 return -1;
516}
517
518////////////////////////////////////////////////////////////////////////////////
519/// Shutdown the database server. Returns 0 if successful, non-zero
520/// otherwise. User must have shutdown permissions.
521/// NOT IMPLEMENTED.
522
524{
525 CheckConnect("Shutdown", -1);
526
527 return -1;
528}
529
530////////////////////////////////////////////////////////////////////////////////
531/// Return Oracle server version info.
532
534{
535 CheckConnect("ServerInfo", 0);
536
537 fInfo = "Oracle";
538 TSQLStatement* stmt = Statement("select * from v$version");
539 if (stmt!=0) {
541 if (stmt->Process()) {
542 fInfo = "";
543 stmt->StoreResult();
544 while (stmt->NextResultRow()) {
545 if (fInfo.Length()>0) fInfo += "\n";
546 fInfo += stmt->GetString(0);
547 }
548 }
549 delete stmt;
550 }
551
552 return fInfo.Data();
553}
554
555////////////////////////////////////////////////////////////////////////////////
556/// Call Commit() to submit all chanes, done before.
557/// Commit() ot Rollback() must be used to complete submitted actions or cancel them
558
560{
561 return Commit();
562}
563
564////////////////////////////////////////////////////////////////////////////////
565/// Commits all changes made since the previous Commit() or Rollback()
566/// Return kTRUE if OK
567
569{
570 CheckConnect("Commit", kFALSE);
571
572 try {
573 fConn->commit();
574 return kTRUE;
575 } CatchError("Commit")
576
577 return kFALSE;
578}
579
580////////////////////////////////////////////////////////////////////////////////
581/// Drops all changes made since the previous Commit() or Rollback()
582/// Return kTRUE if OK
583
585{
586 CheckConnect("Rollback", kFALSE);
587
588 try {
589 fConn->rollback();
590 return kTRUE;
591 } CatchError("Rollback")
592
593 return kFALSE;
594}
595
596////////////////////////////////////////////////////////////////////////////////
597/// set format for converting timestamps or date field into string
598/// default value is "MM/DD/YYYY, HH24:MI:SS"
599
601{
602 if (fmt==0) fmt = "MM/DD/YYYY, HH24:MI:SS";
603 fgDatimeFormat = fmt;
604}
605
606////////////////////////////////////////////////////////////////////////////////
607/// return value of actul convertion format from timestamps or date to string
608
610{
611 return fgDatimeFormat;
612}
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
const Bool_t kFALSE
Definition: RtypesCore.h:90
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
#define CatchError(method)
#define CheckConnect(method, res)
char * Form(const char *fmt,...)
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
Collectable string class.
Definition: TObjString.h:28
void MakeZombie()
Definition: TObject.h:49
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
static void SetDatimeFormat(const char *fmt="MM/DD/YYYY, HH24:MI:SS")
set format for converting timestamps or date field into string default value is "MM/DD/YYYY,...
oracle::occi::Connection * fConn
Definition: TOracleServer.h:31
TSQLResult * GetTables(const char *dbname, const char *wild=nullptr) final
List all tables in the specified database.
Int_t DropDataBase(const char *dbname) final
Drop (i.e.
Int_t Shutdown() final
Shutdown the database server.
TSQLResult * GetColumns(const char *dbname, const char *table, const char *wild=nullptr) final
List all columns in specified table in the specified database.
static const char * fgDatimeFormat
Definition: TOracleServer.h:34
TSQLStatement * Statement(const char *sql, Int_t niter=100) final
Bool_t StartTransaction() final
Call Commit() to submit all chanes, done before.
~TOracleServer()
Close connection to Oracle DB server.
Bool_t Commit() final
Commits all changes made since the previous Commit() or Rollback() Return kTRUE if OK.
void Close(Option_t *opt="") final
Close connection to Oracle DB server.
Bool_t Rollback() final
Drops all changes made since the previous Commit() or Rollback() Return kTRUE if OK.
const char * ServerInfo() final
Return Oracle server version info.
TSQLResult * Query(const char *sql) final
Execute SQL command.
Bool_t Exec(const char *sql) final
Execute sql command which does not produce any result set.
TList * GetTablesList(const char *wild=nullptr) final
Return list of user tables Parameter wild specifies wildcard for table names.
TSQLTableInfo * GetTableInfo(const char *tablename) final
Produces SQL table info Object must be deleted by user.
Int_t CreateDataBase(const char *dbname) final
Create a database.
TSQLResult * GetDataBases(const char *wild=nullptr) final
List all available databases.
static const char * GetDatimeFormat()
return value of actul convertion format from timestamps or date to string
oracle::occi::Environment * fEnv
Definition: TOracleServer.h:30
TOracleServer(const char *db, const char *uid, const char *pw)
format for converting date and time stamps into string
Bool_t IsConnected() const final
Definition: TOracleServer.h:44
Int_t Reload() final
Reload permission tables.
Int_t SelectDataBase(const char *dbname) final
Select a database.
void ClearError()
reset error fields
Definition: TSQLServer.cxx:119
TString fHost
Definition: TSQLServer.h:45
void SetError(Int_t code, const char *msg, const char *method=nullptr)
set new values for error fields if method is specified, displays error message
Definition: TSQLServer.cxx:129
Int_t fPort
Definition: TSQLServer.h:47
Bool_t fErrorOut
Definition: TSQLServer.h:50
TString fDB
Definition: TSQLServer.h:46
TString fType
Definition: TSQLServer.h:44
@ kSQL_VARCHAR
Definition: TSQLServer.h:63
@ kSQL_TIMESTAMP
Definition: TSQLServer.h:69
@ kSQL_NUMERIC
Definition: TSQLServer.h:67
virtual void EnableErrorOutput(Bool_t on=kTRUE)
virtual const char * GetString(Int_t)
Definition: TSQLStatement.h:87
virtual Bool_t NextResultRow()=0
virtual Int_t GetInt(Int_t)
Definition: TSQLStatement.h:81
virtual Bool_t Process()=0
virtual Bool_t StoreResult()=0
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
const char * Data() const
Definition: TString.h:364
void ToUpper()
Change string to upper case.
Definition: TString.cxx:1138
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2289
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
This class represents a WWW compatible URL.
Definition: TUrl.h:35
const char * GetFile() const
Definition: TUrl.h:71
Bool_t IsValid() const
Definition: TUrl.h:81
const char * GetHost() const
Definition: TUrl.h:69
const char * GetOptions() const
Definition: TUrl.h:73
const char * GetProtocol() const
Definition: TUrl.h:66
Int_t GetPort() const
Definition: TUrl.h:80