/* 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; }
/* 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; }
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; }