5 Replies Latest reply on Sep 14, 2018 8:08 PM by Branislav

    Using OCCI with gcc 7.x

    andrem

      Hi all,

       

      I am trying to create a C++14 application with OCCI (11,12,18, all lead to the same issue) using gcc 7.1. The application compiles and runs fine with gcc 4.8.5 unter RHEL7, but throws an error "ORA-24960: the attribute  OCI_ATTR_USERNAME is greater than the maximum allowable length of 255" when compiled with g++7.1. In this particular case, there seems to be a problem with std::string, but I am not sure what exactly goes wrong. I am stuck and would appreciate any help.

       

      Here's an MCVE/SSCCE:

       

      #include <string>

      #include <occi.h>

       

      using namespace oracle::occi;

      using namespace std;

       

      int main ()

      {

        const string url = "//server:1234/ID";

        const string username = "user";

        const string password = "password";

       

        auto env = Environment::createEnvironment();

        try {

          auto conn = env->createConnection(username, password, url);

          std::cout << "Connection to " << url << " successfully established." << std::endl;

         

          env->terminateConnection(conn);

          std::cout << "Connection closed." << std::endl;

        }

        catch (const SQLException& ex) {

          std::cerr << "Error: " << ex.what() << endl;

        }

        Environment::terminateEnvironment (env);

      }

       

      Regards

      André

        • 1. Re: Using OCCI with gcc 7.x
          Kmohan-Oracle

          What does your 'g++ -v' say?

          • 2. Re: Using OCCI with gcc 7.x
            andrem

            $ g++ -v

            Using built-in specs.

            COLLECT_GCC=/opt/gcc_7.1/linux70_64/bin/g++

            COLLECT_LTO_WRAPPER=/opt/gcc_7.1/linux70_64/libexec/gcc/x86_64-pc-linux-gnu/7.1.0/lto-wrapper

            Target: x86_64-pc-linux-gnu

            Configured with: ./configure --prefix=/opt/gcc_7.1/linux70_64 --datadir=/opt/gcc_7.1/linux70_64/share --infodir=/opt/gcc_7.1/linux70_64/info --mandir=/opt/gcc_7.1/linux70_64/man --with-as=/opt/gcc_7.1/linux70_64/bin/as --enable-shared --enable-threads=posix --enable-languages=c,c++,fortran --without-local-prefix --with-pic --enable-targets=all --build=x86_64-pc-linux-gnu --host=x86_64-pc-linux-gnu --target=x86_64-pc-linux-gnu --with-ld=/opt/gcc_7.1/linux70_64/bin/ld

            Thread model: posix

            gcc version 7.1.0 (GCC)

            • 3. Re: Using OCCI with gcc 7.x
              Kmohan-Oracle

              Yes, OCCI is built with gcc4 ABI. You may try with g++ built with this option:

              --with-default-libstdcxx-abi=gcc4-compatible

              • 4. Re: Using OCCI with gcc 7.x
                andrem

                Unfortunately, that's not a viable option for me. I have already chosen another library to access the database.

                Any plans on upgrading to a more recent ABI in the future?

                 

                Thanks,

                André

                • 5. Re: Using OCCI with gcc 7.x
                  Branislav

                  Hello andrem,

                   

                  could you please share your wisdom on which library did you use? I was currently using OCILIB, but there I stumbled upon a multiple performance issues. I was able to solve them by setting fetch size to 2000 rows and using cursors, however that resulted in 110 MB memory usage for 15 MB of data. I checked heap profiler, the data got copied 3 times while assigning to string...this was the reason why I was trying to switch to something native so I could avoid copying of strings and assign the memory just once. My code got inspired by test_fetch function in documentation - https://vrogier.github.io/ocilib/doc/html/group___ocilib_cpp_api_main_demo_application.html .

                   

                  Could you please tell me if you were able to solve this issue as well?

                   

                  The code is as follows:

                  vector<string> Oracle::execute_binded_query(string &sql, string out_cursor_name, bool replace_spaces)

                  {

                      //replace multiple spaces in row with just one space

                      string::iterator new_end = std::unique(sql.begin(), sql.end(), [](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); });

                      sql.erase(new_end, sql.end());

                   

                      vector<string> result;

                      Statement stBind(conn);

                      stBind.SetFetchSize(2000); //set higher fetch size for faster processing

                   

                      Statement st(conn);

                      st.SetFetchSize(2000); //set higher fetch size for faster processing

                      st.Prepare(sql);

                      st.Bind(out_cursor_name, stBind, BindInfo::Out);

                      st.ExecutePrepared();

                   

                      Resultset rs = stBind.GetResultset();

                      while (rs)

                      {

                          rs.ForEach([&result, &replace_spaces](const Resultset &rs) -> bool {

                              stringstream ss;

                              uint32_t count = rs.GetColumnCount();

                              for (uint32_t i = 0; i < count; ++i)

                              {

                                  string column = rs.Get<string>(i + 1);

                                  //replace multiple spaces in row with just one space

                                  string::iterator new_end = std::unique(column.begin(), column.end(), [](char lhs, char rhs) { return (lhs == rhs) && (lhs == ' '); });

                                  column.erase(new_end, column.end());

                                  if (replace_spaces)

                                  {

                                      //replace spaces with #

                                      replace(column.begin(), column.end(), ' ', '#');

                                  }

                                  //remove newlines

                                  column.erase(remove(column.begin(), column.end(), '\n'), column.end());

                                  if (column != "")

                                  {

                                      ss << column;

                                  }

                                  else

                                  {

                                      ss << "NULL";

                                  }

                                  if (i < count - 1)

                                  {

                                      ss << " ";

                                  }

                              }

                              result.push_back(ss.str());

                              return true;

                          });

                   

                          rs = stBind.GetNextResultset();

                      }

                   

                      return result;

                  }

                   

                  Best regards,

                   

                  Branislav