K2InformaticsGmbH / oranif

Oracle OCI driver using dirty NIF
Apache License 2.0
4 stars 2 forks source link

Missing support for DPI_NATIVE_TYPE_ROWID #117

Closed acautin closed 5 years ago

acautin commented 5 years ago

Support for this type is required for dderl as we use it as the base for data manipulation.

c-bik commented 5 years ago

These are an example call sequence for retrieving and using RowIDs using DPI:

Get Row ID

    // perform first query to get rowid
    if (dpiTestCase_getConnection(testCase, &conn) < 0)
        return DPI_FAILURE;
    if (dpiConn_prepareStmt(conn, 0, sqlQuery1, strlen(sqlQuery1), NULL, 0,
            &stmt1) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiStmt_execute(stmt1, 0, NULL) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiStmt_fetch(stmt1, &found, &bufferRowIndex) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (!found)
        return dpiTestCase_setFailed(testCase,
                "row not found for first query!");
    if (dpiStmt_getQueryValue(stmt1, 1, &nativeTypeNum, &queryValue) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiRowid_getStringValue(queryValue->value.asRowid, &rowidAsString,
            &rowidAsStringLength) < 0)
        return dpiTestCase_setFailedFromError(testCase);

Use Row ID

    // perform second query to get row using rowid
    if (dpiConn_prepareStmt(conn, 0, sqlQuery2, strlen(sqlQuery2), NULL, 0,
            &stmt2) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    dpiData_setBytes(&bindValue, (char*) rowidAsString, rowidAsStringLength);
    if (dpiStmt_bindValueByPos(stmt2, 1, DPI_NATIVE_TYPE_BYTES,
            &bindValue) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiStmt_execute(stmt2, 0, NULL) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiStmt_fetch(stmt2, &found, &bufferRowIndex) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (!found)
        return dpiTestCase_setFailed(testCase,
                "row not found for second query!");
    if (dpiStmt_getQueryValue(stmt2, 1, &nativeTypeNum, &queryValue) < 0)
        return dpiTestCase_setFailedFromError(testCase);
    if (dpiTestCase_expectUintEqual(testCase, queryValue->value.asInt64,
            7) < 0)
        return dpiTestCase_setFailedFromError(testCase);

@acautin can you please remark if it can be implemented this way for oranif?

acautin commented 5 years ago

@c-bik certainly it would be possible to implement it like that, but it would be simpler if it can be added to the switch case here https://github.com/K2InformaticsGmbH/oranif/blob/master/c_src/dpiData_nif.c#L276 to make the interface in dderloci more transparent regarding types. Is that not supported on the odpi side ?

c-bik commented 5 years ago

@KarlKeiser Will this work?

case DPI_NATIVE_TYPE_ROWID:
    {
        const char *rowidAsString;
        uint32_t rowidAsStringLength;
        RAISE_EXCEPTION_ON_DPI_ERROR(
            context,        
            dpiRowid_getStringValue(data->value.asRowid, &rowidAsString, , &rowidAsString, &rowidAsStringLength)
        );
        ErlNifBinary bin;
        enif_alloc_binary(rowidAsStringLength, &bin);
        memcpy(bin.data, rowidAsString, rowidAsStringLength);
        dataRet = enif_make_binary(env, &bin);
    }
    break;
c-bik commented 5 years ago

@acautin Can you use ROWIDTOCHAR when you are injecting Row ID into statements instead? For example:

select * from test1

will transform into

select ROWIDTOCHAR(rowid), t.* from test1 t

image

It looks the same and no rowID datatype transformation necessary as it is already a string!

acautin commented 5 years ago

@c-bik this workaround will solve our usage of rowid injections and will use it for now to continue, but nothing is preventing the users from typing select rowid, somecol from sometable in a query window so we still need to support it.