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