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