OCCI small program example, occi small program

Source: Internet
Author: User

OCCI small program example, occi small program
1. Introduction 1.1. Background

This article continues the article "installation and configuration of OCCI Development Environment" to build an available OCCI development environment. As an environment verification, this article provides a small example to obtain the system time Applet of the Oracle database and develop and run it in the OCCI environment.

At the same time, summarize all the problems encountered during the test and the knowledge used, not limited to OCCI, including IDE, compiler, operating system (Linux ).

1.2. System Environment

Database: Oracle12c

Client: instantclient_12_2

Operating System: Ubuntu16.04.3 Linux kernel 4.4.0-112-generic

IDE: Eclipse Oxygen.2 Release (4.7.2) Build id: 20171218-0600

Compiler: gcc 4.8.5

2. program code 2.1. Main Program

Main. cpp

 1 #include <string> 2 #include <iostream> 3 #include "CMyDatabase.h" 4   5 Int main (int argc, char * argv[]) 6  7 { 8  9   CMyDatabase stdb;10   std::string user = "system";11   std::string passwd = "Oracle123";12   std::string connStr = "storcdb";13  14   stdb.connect (user, passwd, connStr);15   stdb.getSystemDateFromDatabase ();16 17   return 0;18 19 }

The main program is very simple. The CMyDatabase class is the class for accessing the encapsulated Oracle database. In the main program, we only need to know That we connect to the database through this class (connect ), in addition, you can obtain the time (getSystemDateFromDatabase) of the database system ).

When connecting to a database, we need to provide the user name and password for accessing the database, as well as the network service name or database connection string that identifies the database. You can refer to section 4.1 in "installation and configuration of OCCI Development Environment" and the section about using sqlplus to test database connection at the end of section 4.2.

2.2. CMyDatabase

The CMyDatabase class mainly encapsulates Oracle's Environment and Connection classes. Because these two classes (other classes in OCCI, such as the Statement class, also exist) are created and returned as pointers, the Resource class needs to be destroyed. Therefore, this type of resource class is encapsulated in the management class. In this example, CMyDatabase is responsible for creating and destroying instances of the Environment and Connection classes, so as to ensure the correct use of resources, create and destroy.

CMyDatabase. h

 1 #ifndef CMYDATABASE_H_ 2 #define CMYDATABASE_H_ 3  4 #include <string> 5 #include <iostream> 6 #include <occi.h> 7 using namespace oracle::occi; 8  9 class CMyDatabase10 {11 public:12     CMyDatabase() : m_env(NULL), m_conn(NULL)13     {14     }15     virtual ~CMyDatabase();16     void connect(const std::string & user, const std::string & passwd,17         const std::string & connStr);18     void getSystemDateFromDatabase();19 private:20     Environment * m_env;21     Connection * m_conn;22 };23 24 #endif /* CMYDATABASE_H_ */

 

CMyDatabase. cpp

 1 #include "CMyDatabase.h" 2  3 CMyDatabase::~CMyDatabase() 4 { 5     if (NULL != m_conn) 6     { 7         m_env->terminateConnection(m_conn); 8         m_conn = NULL; 9     }10     if (NULL != m_env)11         Environment::terminateEnvironment(m_env);12 }13 14 void CMyDatabase::connect(const std::string & user, const std::string & passwd,15     const std::string & connStr)16 {17     try18     {19         m_env = Environment::createEnvironment();20         m_conn = m_env->createConnection(user, passwd, connStr);21     }22     catch (SQLException & e)23     {24         std::cout << "using " << user << "/" << passwd << "@" << connStr25                 << " connect to database." << std::endl;26         std::cout << "*** " << e.getErrorCode() << ": " << e.getMessage()27                 << std::endl;28     }29 }30 31 void CMyDatabase::getSystemDateFromDatabase()32 {33     Statement * stmt = m_conn->createStatement();34     ResultSet * rs = stmt->executeQuery(35             "select to_char(sysdate, 'YYYY-MM-DD HH:MI:SS') from dual");36     rs->next();37     std::cout << rs->getString(1) << std::endl;38     stmt->closeResultSet(rs);39     m_conn->terminateStatement(stmt);40 }

Create a Statement object in the void CMyDatabase: getSystemDateFromDatabase (); function and execute an SQL Statement to obtain the database system time. After execution, a ResultSet (result set) is returned ), before accessing the result set, you must call the next () function. In fact, only this function returns Status: DATA_AVAILABLE (if it is stream-type data, the returned value is Statue: STREAM_DATA_AVAILABLE) only when there is data, you can obtain the data in the result set. In addition, the use of database functions should be put into the exception capture code block, just as written in the CMyDatabase: connect function. Here I omitRequiredIn the official code, do not forget.

 

3. Problem Analysis

This article does not explain how to use Eclipse to create this C ++ project. I believe there is a lot of information, and I believe that you are an experienced person, even if you are a beginner, I think you can quickly create a project correctly by exploring it. We are all programmers with this IQ.

Therefore, this chapter mainly describes some problems encountered in this example and hopes to help you.

3.1. Install Ubuntu16.04

If you need to install a brand new Ubuntu16.04, I suggest you go directly to the official website to download the latest version of ubuntu161124.3 (ubuntu-16.04.3-desktop-amd64.iso), of course, you can also try a later version. There is a problem in the initial 16.04 installation package. When executing the system update (sudo apt-get update), it will crash. You need to clear the libappstream3 package (sudo apt-get purge libappstream3) you can also manually download the libappstream package to install it.

3.2. Why g ++-4.8

If you have installed Ubuntu16.04 or a later version, the g ++ version installed by your system by default or after sudo apt-get install g ++ is later than 5.0. Since the OCCI library is compiled under the gcc-4, program execution crashes after compilation on the gcc-5 (not tested in version 5 or later. I still don't know the specific cause. I guess it is related to the std: string implementation of the two versions.

For the above reason, we need to install g ++-4.8 for the system:

sudo apt-get install g++-4.8

If it is a program compiled through g ++ 5.4, A ORA-24960 exception will be received while connecting to the database, and the program crash dump. The error details are as follows:

ORA-24960: the attribute OCI_ATTR_USERNAME is greater than the maximum allowable length of 255

......

 

 

 

If makefile is used for compilation, you can set the compilation and link tool to g ++-4.8. If Eclipse is used for compilation, you also need to configure the compilation and link tool as g ++-4.8. Right-click the project and choose Properties --> C/C ++ Build --> Settings. Modify the position marked as g ++-4.8.

 

3.3. 'std: string' is ambiguous'

After g ++-4.8 is installed in the system, because multiple gcc versions exist, Eclipse will find the header files of multiple gcc versions, eclipse will prompt ambiguous for the type you use, for example, std: string.

When you right-click to view the definition, a window for selecting a specific header file is displayed, as shown in.

Just like configuring g ++-4.8, right-click the Eclipse project and choose Properties> C/C ++ Build> Settings, and set "ambiguous" header file reference according to the example.

 

For this "include files" setting, in addition to solving the ambiguity of the header file selection, is there any other function?

4. Knowledge extension 4.1. SONAME

In the previous article "installation and configuration of OCCI development environment", I mentioned whether to establish a symbolic link without a version number in the dynamic library libclntshcore. so.12.1. You can obtain the answer by analyzing the SONAME of the dynamic library.

Use readelf to view the SONAME of the dynamic library. We will find that the soname of the libcclntshcore. so.12.1 dynamic library is "libclntshcore. so.12.1", for example:

Readelf-d/opt/oracle/instantclient_12_2/libclntshcore. soDynamic section at offset 0x3b8f80 contains 30 entries: tag type name/value 0x0000000000000001 (NEEDED) Shared Library: [libdl. so.2] 0x0000000000000001 (NEEDED) Shared Library: [libm. so.6] 0x0000000000000001 (NEEDED) Shared Library: [libpthread. so.0] 0x0000000000000001 (NEEDED) Shared Library: [libnsl. so.1] 0x0000000000000001 (NEEDED) Shared Library: [librt. so.1] 0x0000000000000001 (NEEDED) Shared Library: [libaio. so.1] 0x0000000000000001 (NEEDED) Shared Library: [libresolv. so.2] 0x0000000000000001 (NEEDED) Shared Library: [libc. so.6] 0x0000000000000001 (NEEDED) Shared Library: [ld-linux-x86-64.so.2] 0x0000000000000001 (NEEDED) Shared Library: [libgcc_s.so.1]0x000000000000000e (SONAME) Library soname: [libclntshcore. so.12.1]......

When our code does not directly reference this dynamic library, we do not need to define a symbolic link without a version number, because other programs using the dynamic library will directly find the dynamic library using the name defined by SONAME. For example, we can use readelf to check the dynamic library reference of libclntsh. so.12.1:

Readelf-d/opt/oracle/instantclient_12_2/libclntsh. soDynamic section at offset 0x0000bc0 contains 35 entries: tag type name/value 0x0000000000000001 (NEEDED) Shared Library: [libmql1.so] 0x0000000000000001 (NEEDED) Shared Library: [libipc1.so] 0x0000000000000001 (NEEDED) Shared Library: [libnnz12.so] 0x0000000000000001 (NEEDED) Shared Library: [libons. so] 0x0000000000000001 (NEEDED) Shared Library: [libdl. so.2] 0x0000000000000001 (NEEDED) Shared Library: [libm. so.6] 0x0000000000000001 (NEEDED) Shared Library: [libpthread. so.0] 0x0000000000000001 (NEEDED) Shared Library: [libnsl. so.1] 0x0000000000000001 (NEEDED) Shared Library: [librt. so.1] 0x0000000000000001 (NEEDED) Shared Library: [libaio. so.1] 0x0000000000000001 (NEEDED) Shared Library: [libresolv. so.2] 0x0000000000000001 (NEEDED) Shared Library: [libc. so.6] 0x0000000000000001 (NEEDED) Shared Library: [ld-linux-x86-64.so.2]0x0000000000000001 (NEEDED) Shared Library: [libclntshcore. so.12.1]0x0000000000000001 (NEEDED) Shared Library: [libgcc_s.so.1]0x000000000000000e (SONAME) Library soname: [libclntsh. so.12.1]

 

From the command results, libclntsh. so.12.1 uses libclntshcore. so.12.1, which can be found through SONAME.

For libclntsh. so.12.1, We need to reference the dynamic library in the program. Therefore, we need to create a symbolic link for the dynamic library file so that the compiler can find the file.

This method uses SONAME to determine the specific dynamic library, making it possible to have multiple versions of the same dynamic library on the same operating system, this satisfies the dependency requirements of different applications on different versions of dynamic libraries.

SONAME is specified during dynamic library compilation. The name and file name can be different.

Previous Article installation and configuration of OCCI Development Environment

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.