1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <vdb/extern.h>
28
29 #include <klib/symtab.h>
30 #include <klib/rc.h>
31 #include <klib/symbol.h>
32
33 #include "schema-priv.h"
34 #include "schema-parse.h"
35
36 /* Cmp
37 * Sort
38 */
39 int64_t
SViewOverridesCmp(const void * item,const void * n)40 SViewOverridesCmp ( const void *item, const void *n )
41 {
42 const uint32_t *a = item;
43 const SViewOverrides *b = n;
44
45 return ( int64_t ) * a - ( int64_t ) b -> ctx;
46 }
47
48 static
49 int64_t
SViewOverridesSort(const void * item,const void * n)50 SViewOverridesSort ( const void *item, const void *n )
51 {
52 const SViewOverrides *a = item;
53 const SViewOverrides *b = n;
54
55 return ( int64_t ) a -> ctx - ( int64_t ) b -> ctx;
56 }
57
58 /* Whack
59 */
60 static
61 void
SViewOverridesWhack(void * item,void * ignore)62 SViewOverridesWhack ( void *item, void *ignore )
63 {
64 SViewOverrides *self = item;
65 VectorWhack ( & self -> by_parent, NULL, NULL );
66 free ( self );
67 }
68
69 /* Make
70 */
71 rc_t
SViewOverridesMake(Vector * parents,const SView * dad,const Vector * overrides)72 SViewOverridesMake ( Vector *parents, const SView *dad, const Vector *overrides )
73 {
74 rc_t rc;
75 SViewOverrides *to;
76
77 /* first question is whether parent exists */
78 if ( VectorFind ( parents, & dad -> id, NULL, SViewOverridesCmp ) != NULL )
79 return SILENT_RC ( rcVDB, rcSchema, rcParsing, rcTable, rcExists );
80
81 /* create a new override object */
82 to = malloc ( sizeof * to );
83 if ( to == NULL )
84 return RC ( rcVDB, rcSchema, rcParsing, rcMemory, rcExhausted );
85
86 /* shallow clone */
87 rc = VectorCopy ( overrides, & to -> by_parent );
88 if ( rc != 0 )
89 {
90 free ( to );
91 return rc;
92 }
93 to -> dad = dad;
94 to -> ctx = dad -> id;
95
96 /* insert into parent override vector */
97 rc = VectorInsert ( parents, to, NULL, SViewOverridesSort );
98 if ( rc != 0 )
99 {
100 SViewOverridesWhack ( to, NULL );
101 return rc;
102 }
103
104 return 0;
105 }
106
107 /* SView
108 */
109 void
SViewWhack(void * item,void * ignore)110 SViewWhack ( void * item, void *ignore )
111 {
112 SView *self = item;
113
114 /* whack components */
115 VectorWhack ( & self -> params, NULL, NULL );
116 VectorWhack ( & self -> parents, SViewInstanceWhack, NULL );
117
118 VectorWhack ( & self -> col, SColumnWhack, NULL );
119 VectorWhack ( & self -> cname, SNameOverloadWhack, NULL );
120
121 VectorWhack ( & self -> prod, SProductionWhack, NULL );
122 VectorWhack ( & self -> vprods, NULL, NULL );
123 VectorWhack ( & self -> syms, ( void ( CC * ) ( void*, void* ) ) KSymbolWhack, NULL );
124
125 VectorWhack ( & self -> overrides, SViewOverridesWhack, NULL );
126
127 BSTreeWhack ( & self -> scope, KSymbolWhack, NULL );
128
129 free ( self );
130 }
131
132 /* Cmp
133 * Sort
134 */
135 int64_t
SViewCmp(const void * item,const void * n)136 SViewCmp ( const void *item, const void *n )
137 {
138 const uint32_t *a = item;
139 const SView *b = n;
140
141 if ( * a > b -> version )
142 return 1;
143 return ( int64_t ) ( * a >> 24 ) - ( int64_t ) ( b -> version >> 24 );
144 }
145
146 int64_t
SViewSort(const void * item,const void * n)147 SViewSort ( const void *item, const void *n )
148 {
149 const SView *a = item;
150 const SView *b = n;
151
152 return ( int64_t ) ( a -> version >> 24 ) - ( int64_t ) ( b -> version >> 24 );
153 }
154
155 /*
156 * push-view-scope
157 * pop-view-scope
158 */
159 void
pop_view_scope(struct KSymTable * tbl,const SView * view)160 pop_view_scope ( struct KSymTable * tbl, const SView * view )
161 {
162 uint32_t i, count = VectorLength ( & view -> overrides );
163 for ( ++ count, i = 0; i < count; ++ i )
164 KSymTablePopScope ( tbl );
165 }
166
167 rc_t
push_view_scope(struct KSymTable * tbl,const SView * view)168 push_view_scope ( struct KSymTable * tbl, const SView * view )
169 {
170 rc_t rc;
171 uint32_t i = VectorStart ( & view -> overrides );
172 uint32_t count = VectorLength ( & view -> overrides );
173 for ( count += i; i < count; ++ i )
174 {
175 const SViewOverrides *to = ( const void* ) VectorGet ( & view -> overrides, i );
176 rc = KSymTablePushScope ( tbl, ( BSTree* ) & to -> dad -> scope );
177 if ( rc != 0 )
178 {
179 for ( count = VectorStart ( & view -> overrides ); i > count; -- i )
180 KSymTablePopScope ( tbl );
181 return rc;
182 }
183 }
184
185 rc = KSymTablePushScope ( tbl, ( BSTree* ) & view -> scope );
186 if ( rc != 0 )
187 {
188 for ( i = VectorStart ( & view -> overrides ); i < count; ++ i )
189 KSymTablePopScope ( tbl );
190 }
191
192 return rc;
193 }
194
195 bool
view_fwd_scan(BSTNode * n,void * data)196 view_fwd_scan ( BSTNode *n, void *data )
197 {
198 SViewScanData *pb = data;
199 KSymbol *sym = ( KSymbol* ) n;
200 SView *self = pb -> self;
201
202 /* process forwarded symbols */
203 if ( sym -> type == eForward )
204 {
205 /* this symbol was introduced in THIS view */
206 sym -> u . fwd . ctx = self -> id;
207
208 /* add it to the introduced virtual productions and make it virtual */
209 pb -> rc = VectorAppend ( & self -> vprods, & sym -> u . fwd . id, sym );
210 if ( pb -> rc != 0 )
211 return true;
212 sym -> type = eVirtual;
213 }
214 /* symbols other than fwd or virtual are ignored */
215 else if ( sym -> type != eVirtual )
216 {
217 return false;
218 }
219
220 /* add symbol to vector to track ownership */
221 pb -> rc = VectorAppend ( & self -> syms, NULL, sym );
222 if ( pb -> rc != 0 )
223 return true;
224
225 /* remove from symbol table */
226 BSTreeUnlink ( & self -> scope, & sym -> n );
227 return false;
228 }
229
230 static
column_set_context(void * item,void * data)231 void column_set_context ( void *item, void *data )
232 {
233 SColumn *self = item;
234 self -> cid . ctx = * ( const uint32_t* ) data;
235 }
236
237 static
name_set_context(void * item,void * data)238 void name_set_context ( void *item, void *data )
239 {
240 SNameOverload *self = item;
241 if ( ( int32_t ) self -> cid . ctx < 0 )
242 self -> cid . ctx = * ( const uint32_t* ) data;
243 }
244
245 static
production_set_context(void * item,void * data)246 void production_set_context ( void *item, void *data )
247 {
248 SProduction *self = item;
249 self -> cid . ctx = * ( const uint32_t* ) data;
250 }
251
252 static
symbol_set_context(void * item,void * data)253 void symbol_set_context ( void *item, void *data )
254 {
255 KSymbol *self = item;
256 self -> u . fwd . ctx = * ( const uint32_t* ) data;
257 }
258
view_set_context(SView * self,uint32_t p_ctxId)259 void CC view_set_context ( SView *self, uint32_t p_ctxId )
260 {
261 VectorForEach ( & self -> col, false, column_set_context, & p_ctxId );
262 VectorForEach ( & self -> cname, false, name_set_context, & p_ctxId );
263 VectorForEach ( & self -> prod, false, production_set_context, & p_ctxId );
264 VectorForEach ( & self -> vprods, false, symbol_set_context, & p_ctxId );
265 }
266
267 static
view_prod_syntax(void * item,void * data)268 bool view_prod_syntax ( void *item, void *data )
269 {
270 rc_t *rc = data;
271 const SProduction *prod = ( const SProduction* ) item;
272
273 * rc = eval_expr_syntax ( prod -> fd );
274 if ( * rc == 0 )
275 * rc = eval_expr_syntax ( prod -> expr );
276
277 return ( * rc != 0 ) ? true : false;
278 }
279
280 static
view_stmt_syntax(const SView * view)281 rc_t view_stmt_syntax ( const SView * view )
282 {
283 rc_t rc = 0;
284 VectorDoUntil ( & view -> prod, false, view_prod_syntax, & rc );
285 return rc;
286 }
287
288 static
view_typed_column_syntax(void * item,void * data)289 bool view_typed_column_syntax ( void *item, void *data )
290 {
291 rc_t *rc = data;
292 const SColumn *col = ( const SColumn* ) item;
293
294 if ( col -> read != NULL )
295 * rc = eval_expr_syntax ( col -> read );
296 if ( * rc == 0 && col -> validate != NULL )
297 * rc = eval_expr_syntax ( col -> validate );
298 if ( * rc == 0 && col -> limit != NULL )
299 * rc = eval_expr_syntax ( col -> limit );
300
301 return ( * rc != 0 ) ? true : false;
302 }
303
304 static
view_column_syntax(const SView * view)305 rc_t view_column_syntax ( const SView *view )
306 {
307 rc_t rc = 0;
308 VectorDoUntil ( & view -> col, false, view_typed_column_syntax, & rc );
309 return rc;
310 }
311
312 rc_t
view_fix_forward_refs(const SView * view)313 view_fix_forward_refs ( const SView * view )
314 {
315 rc_t rc = view_stmt_syntax ( view );
316 if ( rc == 0 )
317 rc = view_column_syntax ( view );
318 return rc;
319 }
320
321 void
SViewInstanceWhack(void * item,void * ignore)322 CC SViewInstanceWhack ( void *item, void *ignore )
323 {
324 SViewInstance * self = ( SViewInstance * ) item;
325 VectorWhack ( & self -> params, NULL, NULL );
326 free ( self );
327 }
328
329
330 /*
331 * init-tbl-symtab
332 * initializes "tbl"
333 * places table in scope
334 * must be balanced by KSymTableWhack
335 */
336 static
337 rc_t
init_view_symtab(KSymTable * p_tbl,const VSchema * p_schema,const SView * p_view)338 init_view_symtab ( KSymTable * p_tbl, const VSchema * p_schema, const SView * p_view )
339 {
340 rc_t rc = init_symtab ( p_tbl, p_schema );
341 if ( rc == 0 )
342 {
343 rc = push_view_scope ( p_tbl, p_view );
344 if ( rc == 0 )
345 {
346 return 0;
347 }
348
349 KSymTableWhack ( p_tbl );
350 }
351
352 return rc;
353 }
354
355
356 /* Find
357 * generic object find within view scope
358 *
359 * "td" [ OUT, NULL OKAY ] - returns cast type expression
360 * if given or "any" if not
361 *
362 * "name" [ OUT ] - returns list of overloaded objects if found
363 *
364 * "type" [ OUT ] - returns object type id, e.g.:
365 * eDatatype, eTypeset, eFormat, eFunction, ePhysical, eTable, ...
366 *
367 * "expr" [ IN ] - NUL terminated name expression identifying object
368 *
369 * "ctx" [ IN ] - NUL terminated context string for evaluation,
370 * substitutes for filename in logging reports
371 *
372 * "dflt" [ IN ] - if true, resolve default value
373 *
374 * returns principal object identified. if NULL but "name" is not
375 * NULL, then the object was only partially identified.
376 */
377 const void *
SViewFind(const SView * p_self,const VSchema * p_schema,VTypedecl * p_td,const SNameOverload ** p_name,uint32_t * p_type,const char * p_expr,const char * p_ctx,bool p_dflt)378 SViewFind ( const SView * p_self,
379 const VSchema * p_schema,
380 VTypedecl * p_td,
381 const SNameOverload ** p_name,
382 uint32_t * p_type,
383 const char * p_expr,
384 const char * p_ctx,
385 bool p_dflt )
386 {
387 rc_t rc;
388 KSymTable tbl;
389
390 /* initialize to not-found */
391 const void *obj = NULL;
392 * p_name = NULL;
393 * p_type = 0;
394
395 /* build a symbol table for view */
396 rc = init_view_symtab ( & tbl, p_schema, p_self );
397 if ( rc == 0 )
398 {
399 obj = resolve_object ( & tbl, p_schema, p_td, p_name, p_type, p_expr, p_ctx, p_dflt );
400 KSymTableWhack ( & tbl );
401 }
402
403 return obj;
404 }
405
406 /* FindOverride
407 * finds an inherited or introduced overridden symbol
408 */
409 const struct KSymbol *
SViewFindOverride(const SView * p_self,const VCtxId * p_cid)410 SViewFindOverride ( const SView * p_self, const VCtxId * p_cid )
411 {
412 const SViewOverrides *to;
413
414 /* it may be on the existing view */
415 if ( p_cid -> ctx == p_self -> id )
416 {
417 return VectorGet ( & p_self -> vprods, p_cid -> id );
418 }
419
420 to = ( const void* ) VectorFind ( & p_self -> overrides, & p_cid -> ctx, NULL, SViewOverridesCmp );
421 if ( to == NULL )
422 {
423 return NULL;
424 }
425
426 return VectorGet ( & to -> by_parent, p_cid -> id );
427 }
428