Ejemplo n.º 1
0
/* ProdExpr
 *  resolve a simple production by name
 *  create/return a VSimpleProd object
 */
rc_t VProdResolveSProduction ( const VProdResolve *self, VProduction **out, const SProduction *sprod )
{
    rc_t rc;
    VFormatdecl fd;

    /* check cache */
    VProduction *vprod = VCursorCacheGet ( self -> cache, & sprod -> cid );
    if ( vprod != NULL )
    {
        /* return valid or failed production */
        * out = vprod;
        return 0;
    }

    /* pre-fail */
    rc = VCursorCacheSet ( self -> cache, & sprod -> cid, FAILED_PRODUCTION );
    if ( rc == 0 )
    {
        /* resolve production type */
        if ( sprod -> trigger )
            memset ( & fd, 0, sizeof fd );
        else
        {
            rc = STypeExprResolveAsFormatdecl
                ( ( const STypeExpr* ) sprod -> fd, self -> schema, & fd );
        }
    }
    if ( rc == 0 )
    {
        /* resolve assignment expression */
        VTypedesc desc;
        rc = VProdResolveExpr ( self, out, & desc,
            & fd, sprod -> expr, false );
        if ( rc == 0 && * out != NULL )
        {
            const char *name = sprod -> name -> name . addr;
            assert ( name [ sprod -> name -> name . size ] == 0 );
            rc = VSimpleProdMake ( out, self -> owned, self -> curs, prodSimpleCast, 
                name, & fd, & desc, & sprod -> cid, * out, self -> chain );
            if ( rc == 0 )
            {
                void *ignore;
                rc = VCursorCacheSwap ( self -> cache, & sprod -> cid, * out, & ignore );
            }
        }
    }

    return rc;
}
Ejemplo n.º 2
0
/* ParamExpr
 *  resolve a simple parameter by name
 */
LIB_EXPORT rc_t CC VProdResolveParamExpr ( const VProdResolve *self, VProduction **out, const KSymbol *sym )
{
    const SProduction *sprod = sym -> u . obj;
    VProduction *vprod = VCursorCacheGet ( self -> cache, & sprod -> cid );
    if ( vprod != NULL )
    {
        * out = vprod;
        return 0;
    }

    PLOGMSG ( klogWarn, ( klogWarn, "unknown parameter '$(param)' used in expression"
                          , "param=%.*s"
                          , ( int ) sprod -> name -> name . size
                          , sprod -> name -> name . addr ));
    return 0;
}
Ejemplo n.º 3
0
/* PhysExpr
 */
rc_t VProdResolveSPhysMember ( const VProdResolve *self,
    VProduction **out, const SPhysMember *smbr )
{
    rc_t rc;
    VCursor *curs;
    VPhysical *phys;

    curs = self -> curs;
    phys = VCursorCacheGet ( & curs -> phys, & smbr -> cid );
    if ( phys != NULL )
    {
        /* this guy should be readable, but it is not guaranteed */
        if ( phys != FAILED_PHYSICAL )
            * out = phys -> out;
        return 0;
    }

    /* pre-fail */
    rc = VCursorCacheSet ( & curs -> phys, & smbr -> cid, FAILED_PHYSICAL );
    if ( rc == 0 )
    {
        /* create physical object */
        rc = VPhysicalMake ( & phys, curs, smbr );
        if ( rc == 0 )
        {
            /* build physical */
            rc = VProdResolvePhysical ( self, phys );
            if ( rc == 0 && phys -> out > FAILED_PRODUCTION && phys -> b2p > FAILED_PRODUCTION )
            {
                /* set success */
                void *ignore;
                rc = VCursorCacheSwap ( & curs -> phys, & smbr -> cid, phys, & ignore );
                if ( rc == 0 )
                {
                    * out = phys -> out;
                    return 0;
                }
            }
            if ( GetRCState ( rc ) == rcUndefined )
                rc = 0;

            VPhysicalWhack ( phys, NULL );
        }
    }

    return rc;
}
Ejemplo n.º 4
0
/* AddSColumn
 */
static
rc_t
VViewCursorAddSColumn ( VViewCursor *      p_self,
                        uint32_t *         p_idx,
                        const SColumn *    p_scol,
                        const VTypedecl *  p_cast,
                        Vector *           p_cx_bind )
{
    rc_t rc = 0;
    VColumn *col;

    /* must be readable */
    if ( p_scol -> read == NULL )
    {
        return RC ( rcVDB, rcCursor, rcUpdating, rcColumn, rcWriteonly );
    }

    /* must not already be there - benign error */
    col = VCursorCacheGet ( & p_self -> dad . col, & p_scol -> cid );
    if ( col != NULL )
    {
        * p_idx = col -> ord;
        rc = RC ( rcVDB, rcCursor, rcUpdating, rcColumn, rcExists );
    }
    else
    {
        /* make object */
        rc = VColumnMake ( & col, p_self -> view -> schema, p_scol );
        if ( rc == 0 )
        {
#if 0
            /* open column if cursor open or type unknown */
            if ( self -> dad . state >= vcReady || scol -> td . type_id == 0 )
            {
                rc = RC ( rcVDB, rcCursor, rcUpdating, rcColumn, ?? );
            }
            else
            {   /* check cast of SColumn against requested type
                this is to handle the case where the column
                was created incomplete, i.e. with unknown type */
                if ( cast != NULL && | VTypedeclToTypedecl ( & scol -> td,
                        self -> schema, cast, & col -> td, NULL ) )
                {
                    rc = RC ( rcVDB, rcCursor, rcUpdating, rcColumn, ?? );
                }
            }
Ejemplo n.º 5
0
/* ResolveColumn
 *  resolves a column using read/write expression
 */
rc_t VProdResolveColumnRoot ( const VProdResolve *self,
    VProduction **out, const SColumn *scol )
{
    rc_t rc;
    WColumn *wcol;
    VTypedesc desc;
    const char *name;
    VCursor *curs = self -> curs;
    VProduction * in;

    * out = NULL;

    /* decide upon behavior */
    if ( curs -> read_only )
    {
        rc = VProdResolveColumnRead ( self, out, scol );
        if ( rc == 0 && * out <= FAILED_PRODUCTION )
            return RC ( rcVDB, rcCursor, rcOpening, rcColumn, rcUndefined );
        return rc;
    }

    /* write-only cursor must have existing column */
    wcol = VCursorCacheGet ( & curs -> col, & scol -> cid );
    if ( wcol == NULL )
        return 0;

    /* not intended to be reentrant */
    assert ( wcol -> val == NULL );

    /* evaluate input expression */
    if ( scol -> validate == NULL )
    {
        /* use normal read expression */
        rc = VProdResolveColumnRead ( self, &in, scol );
    }
    else
    {
        VFormatdecl fd;
        
        /* create fmtdecl from typedecl */
        memset ( & fd, 0, sizeof fd );

        VDB_DEBUG ( ( "resolving column '%N' validate expression.\n", scol -> name ) );

        /* use validation expression */
        rc = VProdResolveExpr ( self, &in, & desc, & fd, scol -> validate, false );
    }

    /* check failures */
    if ( rc != 0 )
    {
        VDB_DEBUG ( ( "failed to resolve column '%N' - %R.\n", scol -> name, rc ) );
        return rc;
    }
    if ( in <= FAILED_PRODUCTION )
    {
        VDB_DEBUG ( ( "failed to resolve column '%N' - NULL or failed production.\n", scol -> name ) );
        return RC ( rcVDB, rcCursor, rcOpening, rcColumn, rcUndefined );
    }

    /* column name */
    name = scol -> name -> name . addr;

    /* pick up production */
    if ( scol -> validate != NULL )
    {
        rc = VSimpleProdMake ( & wcol -> val, self -> owned,
            prodSimpleCast, name, NULL, NULL, NULL, in, chainDecoding );
        if ( rc != 0 )
            return rc;
    }

    /* create implicit comparison function */
    else
    {
        /* need an output production */
        if ( wcol -> out == NULL )
        {
            rc = VColumnProdMake ( & wcol -> out, self -> owned,
                & wcol -> dad, prodColumnOut, name );
            if ( rc != 0 )
                return rc;
        }

        /* create comparison func */
        rc = VFunctionProdMakeBuiltInComp ( & wcol -> val, self -> owned,
            name, self, wcol -> out, in );
        if ( rc != 0 )
            return rc;
    }

    /* install trigger */
    rc = VectorAppend ( & curs -> trig, NULL, wcol -> val );
    if ( rc == 0 )
        * out = wcol -> val;

    return rc;
}
Ejemplo n.º 6
0
rc_t VProdResolveColumn ( const VProdResolve *self,
    VProduction **out, const SColumn *scol, bool alt )
{
    rc_t rc;
    VColumn *vcol;
    WColumn *wcol;
    VCursor *curs = self -> curs;

    /* decide upon behavior */
    if ( curs -> read_only )
    {
        if ( alt )
        {
            /* TODO: Generate warning message */
            return RC ( rcVDB, rcCursor, rcOpening, rcSchema, rcInvalid );
        }
        vcol = VCursorCacheGet ( & curs -> col, & scol -> cid );
        if ( vcol == NULL )
        {
            rc = VCursorMakeColumn ( curs, & vcol, scol );
            if ( rc != 0 )
                return rc;

#if OPEN_COLUMN_ALTERS_ROW
            rc = VectorAppend ( & curs -> row, & vcol -> ord, vcol );
            if ( rc != 0 )
            {
                VColumnWhack ( vcol, NULL );
                return rc;
            }
#endif
            rc = VCursorCacheSet ( & curs -> col, & scol -> cid, vcol );
            if ( rc != 0 )
            {
#if OPEN_COLUMN_ALTERS_ROW
                void *ignore;
                VectorSwap ( & curs -> row, vcol -> ord, NULL, & ignore );
                vcol -> ord = 0;
#endif
                VColumnWhack ( vcol, NULL );
                return rc;
            }
        }

        return VProdResolveColumnRead ( self, out, scol );
    }

    /* write cursor but read side */
    if ( self -> chain == chainDecoding )
    {
        if ( alt )
        {
            /* TODO: Generate warning message */
            return RC ( rcVDB, rcCursor, rcOpening, rcSchema, rcInvalid );
        }

        return VProdResolveColumnRead ( self, out, scol );
    }

    /* get existing column */
    wcol = VCursorCacheGet ( & curs -> col, & scol -> cid );
    if ( wcol == NULL )
    {
        /* normally write-only cursor must have existing column */
        if ( ! self -> discover_writable_columns )
            return 0;

        /* auto-create writable column for purposes of discovery */
        if ( scol -> read_only )
            return 0;
        rc = VCursorMakeColumn ( curs, & vcol, scol );
        if ( rc != 0 )
            return rc;

        /* add it to the row as if user had done it */
        rc = VectorAppend ( & curs -> row, & vcol -> ord, vcol );
        if ( rc == 0 )
        {
            /* add it to the indexed vector */
            rc = VCursorCacheSet ( & curs -> col, & scol -> cid, vcol );
            if ( rc != 0 )
            {
                void *ignore;
                VectorSwap ( & curs -> row, vcol -> ord, NULL, & ignore );
                vcol -> ord = 0;
            }
        }

        if ( rc != 0 )
        {
            VColumnWhack ( vcol, NULL );
            return rc;
        }

        wcol = ( WColumn* ) vcol;
    }

    /* create output production as required */
    if ( wcol -> out == NULL )
    {
        const char *name = scol -> name -> name . addr;
        rc = VColumnProdMake ( & wcol -> out, self -> owned,
            & wcol -> dad, prodColumnOut, name );
        if ( rc != 0 )
            return rc;
    }
    if ( alt )
    {
        * out = wcol -> dad . in;
        assert ( * out != NULL );
    }
    else
    {
        * out = wcol -> out;
    }
    return 0;
}
Ejemplo n.º 7
0
/* ResolveColumn
 *  resolves a column from read/validate expression
 */
rc_t VProdResolveColumnRead ( const VProdResolve *self,
    VProduction **out, const SColumn *scol )
{
    rc_t rc;
    VFormatdecl fd;
    const char *name;
    VCursor *curs;
    VColumn *vcol;

    VDB_DEBUG ( ( "resolving column '%N' read expression.\n", scol -> name ) );

    /* potential error if self is NULL */
    curs = self -> curs;
    if ( out == NULL )
    {
        rc =  RC(rcVDB, rcProduction, rcResolving, rcParam, rcNull);
        VDB_DEBUG ( ( "result NULL for column '%N'; no output can be produced by '%s' rc %R\n",
                      scol -> name, __func__, rc ) );
        return rc;
    }
    
    /* fetch the column */
    vcol = VCursorCacheGet ( & curs -> col, & scol -> cid );
    if ( vcol == NULL )
    {
        VDB_DEBUG ( ( "failed to fetch NULL for column '%N'; no output was produced by '%s'\n",
                      scol -> name, __func__ ) );
        return 0;
    }

    /* if the read production is in place, return it */
    if ( vcol -> in != NULL )
    {
        if ( vcol -> in != FAILED_PRODUCTION )
            * out = vcol -> in;
        return 0;
    }

    /* pre-fail */
    vcol -> in = FAILED_PRODUCTION;

    /* production resolution works with fmtdecl */
    fd . td = scol -> td;
    fd . fmt = 0;

    /* resolve the expression */
    rc = VProdResolveExpr ( self, out, & vcol -> desc, & fd, scol -> read, false );
    assert (rc != -1);

    if ( rc != 0 || *out == NULL )
        return rc;

    /* repair incomplete column declarations */
    if ( scol -> td . type_id == 0 )
    {
        if ( fd . td . type_id == 0 )
        {
            rc = RC ( rcVDB, rcColumn, rcResolving, rcType, rcUndefined );
            VDB_DEBUG (("failed to repair incomplete declaration for column '%N' rc %R\n",
                        scol -> name, rc));
            return rc;
        }
        ( ( SColumn* ) scol ) -> td = fd . td;
    }

    /* create a simple prod to manage fd and desc */
    name = scol -> name -> name . addr;
    assert ( name [ scol -> name -> name . size ] == 0 );
    rc = VSimpleProdMake ( out, self -> owned, self->curs, prodSimpleCast,
        name, & fd, & vcol -> desc, NULL, * out, self -> chain );

    assert (rc != -1);
    if ( rc != 0 )
    {
        VDB_DEBUG (("failed to create a simple prod to manage fd and desc for column '%N', rc %R\n",
                    scol -> name, rc));
        return rc;
    }

    /* return column input - this is input to the column
       that is intended to be read from the cursor */
    vcol -> in = * out;
    return rc;
}