* nodeRead - * Slightly higher-level reader. * * This routine applies some semantic knowledge on top of the purely * lexical tokenizer pg_strtok(). It can read * * Value token nodes (integers, floats, or strings); * * General nodes (via parseNodeString() from readfuncs.c); * * Lists of the above; * * Lists of integers or OIDs. * The return value is declared void *, not Node *, to avoi
| 341 | * this should only be invoked from within a stringToNode operation). |
| 342 | */ |
| 343 | void * |
| 344 | nodeRead(const char *token, int tok_len) |
| 345 | { |
| 346 | Node *result; |
| 347 | NodeTag type; |
| 348 | |
| 349 | if (token == NULL) /* need to read a token? */ |
| 350 | { |
| 351 | token = pg_strtok(&tok_len); |
| 352 | |
| 353 | if (token == NULL) /* end of input */ |
| 354 | return NULL; |
| 355 | } |
| 356 | |
| 357 | type = nodeTokenType(token, tok_len); |
| 358 | |
| 359 | switch ((int) type) |
| 360 | { |
| 361 | case LEFT_BRACE: |
| 362 | result = parseNodeString(); |
| 363 | token = pg_strtok(&tok_len); |
| 364 | |
| 365 | /* |
| 366 | * CDB: Check for extra fields left over following the ones that |
| 367 | * were consumed by the node reader function. If this tree was |
| 368 | * read from the catalog, it might have been stored by a future |
| 369 | * release which may have added fields that we don't know about. |
| 370 | */ |
| 371 | while (token && |
| 372 | token[0] == ':') |
| 373 | { |
| 374 | /* |
| 375 | * Check for special :prereq tag that a future release may have |
| 376 | * inserted to tell us that the node's semantics are not |
| 377 | * downward compatible. The node reader function should have |
| 378 | * consumed any such tags for features that it supports. If a |
| 379 | * :prereq is left to be seen here, that means its feature isn't |
| 380 | * implemented in this release and we must reject the statement. |
| 381 | * The tag should be followed by a concise feature name or |
| 382 | * release id that can be shown to the user in an error message. |
| 383 | */ |
| 384 | if (tok_len == 7 && |
| 385 | memcmp(token, ":prereq", 7) == 0) |
| 386 | { |
| 387 | token = pg_strtok(&tok_len); |
| 388 | token = debackslash(token, tok_len); |
| 389 | ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 390 | errmsg("This operation requires a feature " |
| 391 | "called \"%.*s\" which is not " |
| 392 | "supported in this version of %s.", |
| 393 | tok_len, token, PACKAGE_NAME) |
| 394 | )); |
| 395 | } |
| 396 | |
| 397 | /* |
| 398 | * Other extra fields can safely be ignored. They are assumed |
| 399 | * downward compatible unless a :prereq tag tells us otherwise. |
| 400 | */ |
no test coverage detected