Code Monkey home page Code Monkey logo

Comments (4)

vrogier avatar vrogier commented on June 19, 2024

Hi,

I understand the issue.
Bujt you will get the same problem with all (at least 99%) Oracle OCI based libraries and even with the Java thin driver.
Even Sql*Plus cannot handle these situations, nor print these values.

If you were using the OCILIB C++ API, I would tell you to add you own template specialization for Statement::Bind() using a custom container
But apparently you are using the C API.

Maybe you could trick OCILIB by callingOCI_BindSetDataSize() with the "real size" beyond the null character.

I have to check if it could work. but even if it works for inserting, it will not work for selecting.

Instead of introducing a new type, i would rather try to find a way to give applications a way to indicate and retrieve the real length of a string bind/selected column row data.
If I can't find a good solution, I will think about adding a new type...

Best regards,

Vincent

from ocilib.

dbpm avatar dbpm commented on June 19, 2024

Technically it could be something like RAW datatype, but existing API does not allow us to reuse OCI_GetRaw() call over varchars.

Though I don’t have objection to have OCI_GetVarchar2 as near 1:1 copy of OCI_GetRaw, the same could be true for binds, why not?

from ocilib.

vrogier avatar vrogier commented on June 19, 2024

Hi,

Regarding your issue:
-binding in and out is not a problem
-gathering the real lenght on select can be addressed with a new function OCI_GetDataSize

unsigned int OCI_API OCI_GetDataSize
(
    OCI_Resultset *rs,
    unsigned int   index
)
{
    OCI_Define *def = NULL;

    OCI_LIB_CALL_ENTER(unsigned int , 0)

    OCI_CHECK_PTR(OCI_IPC_RESULTSET, rs)
    OCI_CHECK_BOUND(rs->stmt->con, index, 1, rs->nb_defs)

    def = OCI_GetDefine(rs, index);

    if (def && OCI_DefineIsDataNotNull(def))
    {
        ub2* lens = (ub2 *)def->buf.lens;

        call_retval = lens[rs->row_cur - 1];

        if (OCI_CDT_TEXT == def->col.datatype)
        {
            call_retval /= sizeof(otext);
        }
    }

    OCI_LIB_CALL_EXIT()
}

Here is a complete sample code and its output:

int main()
{
    OCI_Connection *cn;
    OCI_Statement  *st;
    OCI_Resultset  *rs;
    otext buf[128] = "";

    if (!OCI_Initialize(err_handler, NULL, OCI_ENV_DEFAULT))
        return EXIT_FAILURE;

    cn = OCI_ConnectionCreate("db12c", "usr", "pwd", OCI_SESSION_DEFAULT);
    st = OCI_StatementCreate(cn);

    OCI_ExecuteStmt(st, "SELECT value, LENGTH(VALUE), dump(VALUE) FROM (SELECT 'test' || chr(0) || 'me' VALUE FROM dual)");
    rs = OCI_GetResultset(st);
    while (OCI_FetchNext(rs))
    {
        printf("%s (size=%d) | %s (size=%d) | %s (size=%d)\n",
            OCI_GetString(rs, 1), OCI_GetDataSize(rs, 1),
            OCI_GetString(rs, 2), OCI_GetDataSize(rs, 2),
            OCI_GetString(rs, 3), OCI_GetDataSize(rs, 3));
    }

    OCI_Prepare(st, "begin :1 := 'test' || chr(0) || 'me'; end;");
    OCI_BindString(st, ":1", buf, sizeof(buf));
    OCI_Execute(st);

    printf("%s (size=%d), buf+5=%s\n", buf, OCI_BindGetDataSize(OCI_GetBind(st, 1)), buf + strlen(buf) + 1);

    OCI_ExecuteStmt(st, "create table temp(value varchar2(50))");
    OCI_ExecuteStmt(st, "insert into temp values( 'test' || chr(0) || 'me')");
    OCI_ExecuteStmt(st, " select value from temp");
    rs = OCI_GetResultset(st);
    while (OCI_FetchNext(rs))
    {
        char *s = OCI_GetString(rs, 1);
        printf("%s (size=%d), buf+5=%s\n", s, OCI_GetDataSize(rs, 1), s + strlen(s) + 1);
    }

    OCI_ExecuteStmt(st, "drop table temp");

    OCI_Cleanup();

    return EXIT_SUCCESS;
}

Output:

test (size=7) | 7 (size=2) | Typ=1 Len=7: 116,101,115,116,0,109,101 (size=38)
test (size=7), buf+5=me
test (size=7), buf+5=me

Is that sounds okay for you ?

from ocilib.

dbpm avatar dbpm commented on June 19, 2024

OCI_GetDataSize() - it's a brilliant solution, I much satisfied, thank you.
Separate OCI_Varchar2 datatype could be unreasonably complex solution, indeed.

So simple function call fully resolves our case. I also tested Direct Path API - it handles the 0x0 char in the middle of the string properly.

Please close the issue.

from ocilib.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.