Пример #1
0
/* Make
 *  make a column ref from an SColumn*
 */
rc_t VColumnRefMake ( VColumnRef **rp, const VSchema *schema, const SColumn *scol )
{
    char text [ 256 ];
    rc_t rc = VTypedeclToText ( & scol -> td, schema, text, sizeof text );
    if ( rc == 0 )
    {
        size_t tdsize = strlen ( text );
        const String *name = & scol -> name -> name;
        VColumnRef *cref = malloc ( sizeof * cref + name -> size + tdsize );
        if ( cref == NULL )
            rc = RC ( rcVDB, rcTable, rcListing, rcMemory, rcExhausted );
        else
        {
            strcpy ( cref -> typedecl, text );
            string_copy ( & cref -> typedecl [ tdsize + 1 ], name -> size + 1, name -> addr, name -> size );
            StringInit ( & cref -> name, & cref -> typedecl [ tdsize + 1 ], name -> size, name -> len );
            cref -> td = scol -> td;
            cref -> cid = scol -> cid;
            cref -> dflt = scol -> dflt;

            * rp = cref;
        }
    }

    return rc;
}
Пример #2
0
static
rc_t populate_cursors ( VTable *dtbl, VCursor *dcurs, const VCursor *scurs,
    vtblcp_column_map *cm, const Vector *v, uint32_t *rd_filt )
{
    uint32_t end = VectorLength ( v );
    uint32_t i = VectorStart ( v );

    BSTree stype_tbl, rftype_tbl;

    const VSchema *schema;
    rc_t rc = VTableOpenSchema ( dtbl, & schema );
    if ( rc != 0 )
    {
        LOGERR ( klogInt, rc, "failed to open destination table schema" );
        return rc;
    }

    /* populate sensitive type table */
    rc = populate_stype_tbl ( & stype_tbl, schema );
    if ( rc != 0 )
    {
        VSchemaRelease ( schema );
        return rc;
    }

    /* populate read filter type table */
    rc = populate_rdfilt_tbl ( & rftype_tbl, schema );
    if ( rc != 0 )
    {
        BSTreeWhack ( & stype_tbl, stype_id_whack, NULL );
        VSchemaRelease ( schema );
        return rc;
    }

    for ( end += i, rc = 0, * rd_filt = 0; i < end; ++ i )
    {
        VTypedecl td;
        char typedecl [ 128 ];

        const char *spec = ( const void* ) VectorGet ( v, i );

        /* request column in destination */
        rc = VCursorAddColumn ( dcurs, & cm [ i ] . wr, spec );
        if ( rc != 0 )
        {
            PLOGERR ( klogErr,  (klogErr, rc, "failed to add '$(spec)' to destination cursor", "spec=%s", spec ));
            break;
        }

        /* always retrieve data type */
        rc = VCursorDatatype ( dcurs, cm [ i ] . wr, & td, NULL );
        if ( rc != 0 )
        {
            PLOGERR ( klogInt,  (klogInt, rc, "failed to determine datatype of destination column '$(name)'", "name=%s", spec ));
            break;
        }

        /* mark column as sensitive or not */
        rc = mark_type_sensitivity ( & stype_tbl, schema, & td, & cm [ i ] );
        if ( rc != 0 )
            break;

        /* if spec is already typed, request it in source */
        if ( spec [ 0 ] == '(' )
        {
            rc = VCursorAddColumn ( scurs, & cm [ i ] . rd, spec );
            if ( rc != 0 )
            {
                PLOGERR ( klogErr,  (klogErr, rc, "failed to add '$(spec)' to source cursor", "spec=%s", spec ));
                break;
            }
        }
        else
        {
            rc = VTypedeclToText ( & td, schema, typedecl, sizeof typedecl );
            if ( rc != 0 )
            {
                PLOGERR ( klogInt,  (klogInt, rc, "failed to print datatype of destination column '$(name)'", "name=%s", spec ));
                break;
            }

            rc = VCursorAddColumn ( scurs, & cm [ i ] . rd, "(%s)%s", typedecl, spec );
            if ( rc != 0 )
            {
                PLOGERR ( klogErr,  (klogErr, rc, "failed to add '$(spec)' to source cursor", "spec=(%s)%s", typedecl, spec ));
                break;
            }
        }

        /* check if column is a read filter */
        cm [ i ] . rd_filter = false;
        if ( ! cm [ i ] . sensitive )
        {
            if ( BSTreeFind ( & rftype_tbl, & td, stype_id_cmp ) != NULL )
            {
                if ( * rd_filt != 0 )
                {
                    rc = RC ( rcExe, rcColumn, rcOpening, rcColumn, rcExists );
                    PLOGERR ( klogInt,  (klogInt, rc, "can't use column '$(name)' as read filter", "name=%s", spec ));
                    break;
                }

                * rd_filt = cm [ i ] . rd;
                cm [ i ] . rd_filter = true;
            }
        }
    }

    BSTreeWhack ( & rftype_tbl, stype_id_whack, NULL );
    BSTreeWhack ( & stype_tbl, stype_id_whack, NULL );
    VSchemaRelease ( schema );

    /* add read filter to input if not already there in some way */
    if ( * rd_filt == 0 )
    {
        rc = VCursorAddColumn ( scurs, rd_filt, "RD_FILTER" );
        if ( rc != 0 && GetRCState ( rc ) == rcNotFound )
            rc = 0;
    }

    return rc;
}
Пример #3
0
/* MakeTypedecl
 *  convert a VTypedecl into canonical text
 *
 *  "buffer" [ OUT ] and "bsize" [ IN ] - output buffer for
 *  NUL terminated type declaration string
 *
 *  "typedecl" [ IN ] - binary representation of typedecl
 */
LIB_EXPORT rc_t CC VDatatypesMakeTypedecl ( const VDatatypes *self,
    char *buffer, size_t bsize, const VTypedecl *typedecl )
{
    return VTypedeclToText ( typedecl, ( const VSchema* ) self, buffer, bsize );
}
Пример #4
0
rc_t VProdResolveExpr ( const VProdResolve *self,
    VProduction **out, VTypedesc *desc, VFormatdecl *fd,
    const SExpression *expr, bool casting )
{
    rc_t rc;
    VProduction *prod;

    if ( expr == NULL )
    {
        /* report NULL expression, but don't die */
        PLOGMSG ( klogWarn, ( klogWarn, "NULL expression in '$(tbl)' table schema"
                   , "tbl=%.*s"
                   , ( int ) self -> stbl -> name -> name . size
                   , self -> stbl -> name -> name . addr ));
        return 0;
    }

    prod = NULL;
    *out = NULL;

#if _DEBUGGING
    ++ indent_level;
    VDB_DEBUG (( "%*cresolving expression '%s'\n", indent_level, ' ',
                 VProdResolvePrintExpr ( self, expr ) ));
#endif

    switch ( expr -> var )
    {
    case eParamExpr:
        /* a script function is making reference to a parameter */
        rc = VProdResolveParamExpr ( self, & prod, ( ( const SSymExpr* ) expr ) -> _sym );
    assert (rc != -1);
        break;

    case eProdExpr:
        /* return a simple production */
        rc = VProdResolveProdExpr ( self, & prod, ( ( const SSymExpr* ) expr ) -> _sym );
    assert (rc != -1);
        break;

    case eFwdExpr:
        /* handle an implicit or overridden reference */
        rc = VProdResolveFwdExpr ( self, & prod, fd, ( const SSymExpr* ) expr, casting );
    assert (rc != -1);
        break;

    case eColExpr:
        /* return a column production */
        rc = VProdResolveColExpr ( self, & prod, fd, ( const SSymExpr* ) expr, casting );
    assert (rc != -1);
        break;

    case ePhysExpr:
        /* return a physical production */
        rc = VProdResolvePhysExpr ( self, & prod, ( ( const SSymExpr* ) expr ) -> _sym );
    assert (rc != -1);
        break;

    case eScriptExpr:
        /* create a script function */
        rc = VProdResolveScriptExpr ( self, & prod, fd, ( const SFuncExpr* ) expr );
    assert (rc != -1);
        break;

    case eFuncExpr:
        /* create an external function */
        rc = VProdResolveFuncExpr ( self, & prod, fd, ( const SFuncExpr* ) expr );
    assert (rc != -1);
        break;

    case eCastExpr:
        /* perform an explicit cast */
        rc = VProdResolveCastExpr ( self, & prod, ( const SBinExpr* ) expr );
    assert (rc != -1);
        break;
        
    case eCondExpr:
        /* run left and right expressions in order until exit condition */
        rc = VProdResolveExpr ( self, out, desc, fd, ( ( const SBinExpr* ) expr ) -> left, casting );
    assert (rc != -1);
        if ( ( rc == 0 && * out == NULL ) || self -> discover_writable_columns )
        {
            rc = VProdResolveExpr ( self, out, desc, fd, ( ( const SBinExpr* ) expr ) -> right, casting );
    assert (rc != -1);
        }
#if _DEBUGGING
        -- indent_level;
#endif
        return rc;

    default:
        /* report bad expression, but don't die */
        PLOGMSG ( klogWarn, ( klogWarn, "unrecognized expression in '$(tbl)' table schema"
                   , "tbl=%.*s"
                   , ( int ) self -> stbl -> name -> name . size
                   , self -> stbl -> name -> name . addr ));
#if _DEBUGGING
        -- indent_level;
#endif
        return 0;
    }

    /* guard against returns of NULL or FAILED_PRODUCTION */
    if ( rc == 0 && prod > FAILED_PRODUCTION )
    {
        VDB_DEBUG ( ("%*cresolved expression  '%s'\n", indent_level, ' ', VProdResolvePrintExpr ( self, expr ) ) );

        /* returned production must be on requested chain */
        if ( ( prod -> chain & self -> chain ) == 0 )
        {
            rc = RC ( rcVDB, rcProduction, rcResolving, rcSchema, rcInconsistent );
            VDB_DEBUG ( ( "%*cPRODUCTION RESOLVED ON WRONG FORK: %R\n", indent_level, ' ', rc ) );
        }
        else
        {
            /* fix uncommitted production chain */
            if ( prod -> chain == chainUncommitted )
                prod -> chain = self -> chain;

            /* test for type compatibility - modifies "fd" */
            if ( casting ?
                 VFormatdeclCommonAncestor ( & prod -> fd, self -> schema, fd, fd, NULL ) :
                 VFormatdeclToFormatdecl ( & prod -> fd, self -> schema, fd, fd, NULL ) )
            {
                /* if no type description is requested, we're done */
                if ( desc == NULL )
                    * out = prod;
                else
                {
                    /* otherwise, create a type description */
                    rc = VSchemaDescribeTypedecl ( self -> schema, desc, & fd -> td );
    assert (rc != -1);
                    if ( rc != 0 )
                        VDB_DEBUG ( ( "%*cREQUESTED TYPE CANNOT BE DESCRIBED: %R\n", indent_level, ' ', rc ) );
                    else
                        * out = prod;
                }
            }
            else
            {
#if _DEBUGGING
                char from [ 128 ] = "", to [ 128 ] = "";
                VTypedeclToText ( & prod -> fd . td, self -> schema, from, sizeof from );
                VTypedeclToText ( & fd -> td, self -> schema, to, sizeof to );
                VDB_DEBUG ( ( "%*cexpression '%s' cannot be %s from '%s' to '%s'\n"
                              , indent_level, ' '
                              , VProdResolvePrintExpr ( self, expr )
                              , casting ? "cast" : "typed"
                              , from
                              , to
                             )
                    );
#endif
            }
        }
    }
    else if ( rc != 0 )
    {
        VDB_DEBUG ( ( "failed to resolve expression '%s' prod %p %R\n", VProdResolvePrintExpr ( self, expr ), prod, rc ) );
    }
    else if ( prod == NULL )
    {
        VDB_DEBUG ( ( "expression '%s' was not resolved\n", VProdResolvePrintExpr ( self, expr ) ) );
    }
    else
    {
        VDB_DEBUG ( ( "expression '%s' returned FAILED_PRODUCTION\n", VProdResolvePrintExpr ( self, expr ) ) );
    }

#if _DEBUGGING
    -- indent_level;
#endif

    return rc;
}