#include "postgres.h"#include <ctype.h>#include "nodes/pg_list.h"#include "nodes/readfuncs.h"#include "nodes/value.h"
Go to the source code of this file.
Defines | |
| #define | RIGHT_PAREN (1000000 + 1) |
| #define | LEFT_PAREN (1000000 + 2) |
| #define | LEFT_BRACE (1000000 + 3) |
| #define | OTHER_TOKEN (1000000 + 4) |
Functions | |
| void * | stringToNode (char *str) |
| char * | pg_strtok (int *length) |
| char * | debackslash (char *token, int length) |
| static NodeTag | nodeTokenType (char *token, int length) |
| void * | nodeRead (char *token, int tok_len) |
Variables | |
| static char * | pg_strtok_ptr = NULL |
| #define LEFT_BRACE (1000000 + 3) |
Definition at line 186 of file read.c.
Referenced by nodeRead().
| #define LEFT_PAREN (1000000 + 2) |
Definition at line 185 of file read.c.
Referenced by nodeRead().
| #define OTHER_TOKEN (1000000 + 4) |
Definition at line 187 of file read.c.
Referenced by nodeRead().
| #define RIGHT_PAREN (1000000 + 1) |
Definition at line 184 of file read.c.
Referenced by nodeRead().
| char* debackslash | ( | char * | token, | |
| int | length | |||
| ) |
| void* nodeRead | ( | char * | token, | |
| int | tok_len | |||
| ) |
Definition at line 278 of file read.c.
References debackslash(), elog, ERROR, lappend(), lappend_int(), lappend_oid(), LEFT_BRACE, LEFT_PAREN, makeBitString(), makeFloat(), makeInteger(), makeString(), nodeRead(), nodeTokenType(), NULL, OTHER_TOKEN, palloc(), parseNodeString(), pg_strtok(), RIGHT_PAREN, T_BitString, T_Float, T_Integer, T_String, and val.
Referenced by nodeRead(), and stringToNode().
{
Node *result;
NodeTag type;
if (token == NULL) /* need to read a token? */
{
token = pg_strtok(&tok_len);
if (token == NULL) /* end of input */
return NULL;
}
type = nodeTokenType(token, tok_len);
switch ((int) type)
{
case LEFT_BRACE:
result = parseNodeString();
token = pg_strtok(&tok_len);
if (token == NULL || token[0] != '}')
elog(ERROR, "did not find '}' at end of input node");
break;
case LEFT_PAREN:
{
List *l = NIL;
/*----------
* Could be an integer list: (i int int ...)
* or an OID list: (o int int ...)
* or a list of nodes/values: (node node ...)
*----------
*/
token = pg_strtok(&tok_len);
if (token == NULL)
elog(ERROR, "unterminated List structure");
if (tok_len == 1 && token[0] == 'i')
{
/* List of integers */
for (;;)
{
int val;
char *endptr;
token = pg_strtok(&tok_len);
if (token == NULL)
elog(ERROR, "unterminated List structure");
if (token[0] == ')')
break;
val = (int) strtol(token, &endptr, 10);
if (endptr != token + tok_len)
elog(ERROR, "unrecognized integer: \"%.*s\"",
tok_len, token);
l = lappend_int(l, val);
}
}
else if (tok_len == 1 && token[0] == 'o')
{
/* List of OIDs */
for (;;)
{
Oid val;
char *endptr;
token = pg_strtok(&tok_len);
if (token == NULL)
elog(ERROR, "unterminated List structure");
if (token[0] == ')')
break;
val = (Oid) strtoul(token, &endptr, 10);
if (endptr != token + tok_len)
elog(ERROR, "unrecognized OID: \"%.*s\"",
tok_len, token);
l = lappend_oid(l, val);
}
}
else
{
/* List of other node types */
for (;;)
{
/* We have already scanned next token... */
if (token[0] == ')')
break;
l = lappend(l, nodeRead(token, tok_len));
token = pg_strtok(&tok_len);
if (token == NULL)
elog(ERROR, "unterminated List structure");
}
}
result = (Node *) l;
break;
}
case RIGHT_PAREN:
elog(ERROR, "unexpected right parenthesis");
result = NULL; /* keep compiler happy */
break;
case OTHER_TOKEN:
if (tok_len == 0)
{
/* must be "<>" --- represents a null pointer */
result = NULL;
}
else
{
elog(ERROR, "unrecognized token: \"%.*s\"", tok_len, token);
result = NULL; /* keep compiler happy */
}
break;
case T_Integer:
/*
* we know that the token terminates on a char atol will stop at
*/
result = (Node *) makeInteger(atol(token));
break;
case T_Float:
{
char *fval = (char *) palloc(tok_len + 1);
memcpy(fval, token, tok_len);
fval[tok_len] = '\0';
result = (Node *) makeFloat(fval);
}
break;
case T_String:
/* need to remove leading and trailing quotes, and backslashes */
result = (Node *) makeString(debackslash(token + 1, tok_len - 2));
break;
case T_BitString:
{
char *val = palloc(tok_len);
/* skip leading 'b' */
memcpy(val, token + 1, tok_len - 1);
val[tok_len - 1] = '\0';
result = (Node *) makeBitString(val);
break;
}
default:
elog(ERROR, "unrecognized node type: %d", (int) type);
result = NULL; /* keep compiler happy */
break;
}
return (void *) result;
}
| static NodeTag nodeTokenType | ( | char * | token, | |
| int | length | |||
| ) | [static] |
Definition at line 200 of file read.c.
Referenced by nodeRead().
{
NodeTag retval;
char *numptr;
int numlen;
/*
* Check if the token is a number
*/
numptr = token;
numlen = length;
if (*numptr == '+' || *numptr == '-')
numptr++, numlen--;
if ((numlen > 0 && isdigit((unsigned char) *numptr)) ||
(numlen > 1 && *numptr == '.' && isdigit((unsigned char) numptr[1])))
{
/*
* Yes. Figure out whether it is integral or float; this requires
* both a syntax check and a range check. strtol() can do both for us.
* We know the token will end at a character that strtol will stop at,
* so we do not need to modify the string.
*/
long val;
char *endptr;
errno = 0;
val = strtol(token, &endptr, 10);
(void) val; /* avoid compiler warning if unused */
if (endptr != token + length || errno == ERANGE
#ifdef HAVE_LONG_INT_64
/* if long > 32 bits, check for overflow of int4 */
|| val != (long) ((int32) val)
#endif
)
return T_Float;
return T_Integer;
}
/*
* these three cases do not need length checks, since pg_strtok() will
* always treat them as single-byte tokens
*/
else if (*token == '(')
retval = LEFT_PAREN;
else if (*token == ')')
retval = RIGHT_PAREN;
else if (*token == '{')
retval = LEFT_BRACE;
else if (*token == '\"' && length > 1 && token[length - 1] == '\"')
retval = T_String;
else if (*token == 'b')
retval = T_BitString;
else
retval = OTHER_TOKEN;
return retval;
}
| char* pg_strtok | ( | int * | length | ) |
Definition at line 107 of file read.c.
References pg_strtok_ptr.
Referenced by _readBitmapset(), _readBoolExpr(), _readConst(), nodeRead(), parseNodeString(), and readDatum().
{
char *local_str; /* working pointer to string */
char *ret_str; /* start of token to return */
local_str = pg_strtok_ptr;
while (*local_str == ' ' || *local_str == '\n' || *local_str == '\t')
local_str++;
if (*local_str == '\0')
{
*length = 0;
pg_strtok_ptr = local_str;
return NULL; /* no more tokens */
}
/*
* Now pointing at start of next token.
*/
ret_str = local_str;
if (*local_str == '(' || *local_str == ')' ||
*local_str == '{' || *local_str == '}')
{
/* special 1-character token */
local_str++;
}
else
{
/* Normal token, possibly containing backslashes */
while (*local_str != '\0' &&
*local_str != ' ' && *local_str != '\n' &&
*local_str != '\t' &&
*local_str != '(' && *local_str != ')' &&
*local_str != '{' && *local_str != '}')
{
if (*local_str == '\\' && local_str[1] != '\0')
local_str += 2;
else
local_str++;
}
}
*length = local_str - ret_str;
/* Recognize special case for "empty" token */
if (*length == 2 && ret_str[0] == '<' && ret_str[1] == '>')
*length = 0;
pg_strtok_ptr = local_str;
return ret_str;
}
| void* stringToNode | ( | char * | str | ) |
Definition at line 38 of file read.c.
References nodeRead(), NULL, and pg_strtok_ptr.
Referenced by AddRelationNewConstraints(), build_column_default(), ExecRelCheck(), fetch_function_defaults(), func_get_detail(), generateClonedIndexStmt(), get_relation_constraints(), get_typdefault(), GetDomainConstraints(), make_ruledef(), make_viewdef(), MergeAttributes(), MergeWithExistingConstraint(), pg_get_constraintdef_worker(), pg_get_expr_worker(), pg_get_indexdef_worker(), pg_get_triggerdef_worker(), print_function_arguments(), ProcedureCreate(), RelationBuildRuleLock(), RelationGetIndexExpressions(), RelationGetIndexPredicate(), transformTableLikeClause(), TriggerEnabled(), TypeCreate(), validateCheckConstraint(), and validateDomainConstraint().
{
char *save_strtok;
void *retval;
/*
* We save and restore the pre-existing state of pg_strtok. This makes the
* world safe for re-entrant invocation of stringToNode, without incurring
* a lot of notational overhead by having to pass the next-character
* pointer around through all the readfuncs.c code.
*/
save_strtok = pg_strtok_ptr;
pg_strtok_ptr = str; /* point pg_strtok at the string to read */
retval = nodeRead(NULL, 0); /* do the reading */
pg_strtok_ptr = save_strtok;
return retval;
}
char* pg_strtok_ptr = NULL [static] |
Definition at line 30 of file read.c.
Referenced by pg_strtok(), and stringToNode().
1.7.1