Change the parser to convert SQL "position" and "substring" syntax to

position() and substring() functions, so that it works transparently for
bit types as well.  Alias the text functions appropriately.

Add position() for bit types.

Add new constant node T_BitString that represents literals of the form
B'1001 and pass those to zpbit type.
This commit is contained in:
Peter Eisentraut 2000-10-31 10:22:13 +00:00
parent d397c1c8a2
commit 73874a06f0
14 changed files with 214 additions and 47 deletions

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.127 2000/10/26 21:35:47 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.128 2000/10/31 10:22:10 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -2511,6 +2511,7 @@ _copyValue(Value *from)
break;
case T_Float:
case T_String:
case T_BitString:
newnode->val.str = pstrdup(from->val.str);
break;
default:
@ -2703,6 +2704,7 @@ copyObject(void *from)
case T_Integer:
case T_Float:
case T_String:
case T_BitString:
retval = _copyValue(from);
break;
case T_List:

View File

@ -20,7 +20,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.77 2000/10/18 16:16:04 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.78 2000/10/31 10:22:10 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -1719,6 +1719,7 @@ _equalValue(Value *a, Value *b)
return a->val.ival == b->val.ival;
case T_Float:
case T_String:
case T_BitString:
return strcmp(a->val.str, b->val.str) == 0;
default:
break;
@ -1874,6 +1875,7 @@ equal(void *a, void *b)
case T_Integer:
case T_Float:
case T_String:
case T_BitString:
retval = _equalValue(a, b);
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.35 2000/10/05 19:11:27 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.36 2000/10/31 10:22:10 petere Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
@ -70,6 +70,23 @@ makeString(char *str)
return v;
}
/*
* makeBitString
*
* Caller is responsible for passing a palloc'd string.
*/
Value *
makeBitString(char *str)
{
Value *v = makeNode(Value);
v->type = T_BitString;
v->val.str = str;
return v;
}
/*
* lcons
*

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.129 2000/10/26 21:35:48 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.130 2000/10/31 10:22:10 petere Exp $
*
* NOTES
* Every (plan) node in POSTGRES has an associated "out" routine which
@ -20,10 +20,10 @@
* representation plus some other information (string length, etc.)
*
*/
#include <ctype.h>
#include "postgres.h"
#include <ctype.h>
#include "access/heapam.h"
#include "access/htup.h"
#include "catalog/pg_type.h"
@ -1352,6 +1352,9 @@ _outValue(StringInfo str, Value *value)
_outToken(str, value->val.str);
appendStringInfo(str, "\" ");
break;
case T_BitString:
appendStringInfo(str, " B%s ", value->val.str);
break;
default:
elog(NOTICE, "_outValue: don't know how to print type %d ",
value->type);

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.23 2000/06/14 18:17:32 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/read.c,v 1.24 2000/10/31 10:22:10 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -17,11 +17,11 @@
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include <ctype.h>
#include <errno.h>
#include "postgres.h"
#include "nodes/pg_list.h"
#include "nodes/readfuncs.h"
@ -184,7 +184,7 @@ debackslash(char *token, int length)
* nodeTokenType -
* returns the type of the node token contained in token.
* It returns one of the following valid NodeTags:
* T_Integer, T_Float, T_String
* T_Integer, T_Float, T_String, T_BitString
* and some of its own:
* RIGHT_PAREN, LEFT_PAREN, PLAN_SYM, AT_SYMBOL, ATOM_TOKEN
*
@ -236,6 +236,8 @@ nodeTokenType(char *token, int length)
retval = AT_SYMBOL;
else if (*token == '\"' && length > 1 && token[length - 1] == '\"')
retval = T_String;
else if (*token == 'B')
retval = T_BitString;
else
retval = ATOM_TOKEN;
return retval;
@ -346,6 +348,15 @@ nodeRead(bool read_car_only)
this_value = (Node *) makeString(debackslash(token + 1, tok_len - 2));
make_dotted_pair_cell = true;
break;
case T_BitString:
{
char * val = palloc(tok_len);
/* skip leading 'B'*/
strncpy(val, token + 1, tok_len - 1);
val[tok_len - 1] = '\0';
this_value = (Node *) makeBitString(val);
break;
}
default:
elog(ERROR, "nodeRead: Bad type %d", type);
this_value = NULL; /* keep compiler happy */

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.201 2000/10/29 16:11:33 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.202 2000/10/31 10:22:10 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -353,7 +353,7 @@ static void doNegateFloat(Value *v);
%token UNIONJOIN
/* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT, FCONST, SCONST, Op
%token <str> IDENT, FCONST, SCONST, BITCONST, Op
%token <ival> ICONST, PARAM
/* these are not real. they are here so that they get generated as #define's*/
@ -1798,6 +1798,10 @@ TriggerFuncArg: ICONST
{
$$ = makeString($1);
}
| BITCONST
{
$$ = makeString($1);
}
| ColId
{
$$ = makeString($1);
@ -4786,8 +4790,9 @@ c_expr: attr
}
| POSITION '(' position_list ')'
{
/* position(A in B) is converted to position(B, A) */
FuncCall *n = makeNode(FuncCall);
n->funcname = "strpos";
n->funcname = "position";
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@ -4795,8 +4800,10 @@ c_expr: attr
}
| SUBSTRING '(' substr_list ')'
{
/* substring(A from B for C) is converted to
* substring(A, B, C) */
FuncCall *n = makeNode(FuncCall);
n->funcname = "substr";
n->funcname = "substring";
n->args = $3;
n->agg_star = FALSE;
n->agg_distinct = FALSE;
@ -5201,6 +5208,13 @@ AexprConst: Iconst
n->val.val.str = $1;
$$ = (Node *)n;
}
| BITCONST
{
A_Const *n = makeNode(A_Const);
n->val.type = T_BitString;
n->val.val.str = $1;
$$ = (Node *)n;
}
/* This rule formerly used Typename,
* but that causes reduce conflicts with subscripted column names.
* Now, separate into ConstTypename and ConstInterval,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.47 2000/09/29 18:21:36 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.48 2000/10/31 10:22:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,6 +31,7 @@
#include "parser/parse_target.h"
#include "parser/parse_type.h"
#include "utils/builtins.h"
#include "utils/varbit.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@ -473,6 +474,16 @@ make_const(Value *value)
typebyval = false;
break;
case T_BitString:
val = DirectFunctionCall3(zpbit_in,
CStringGetDatum(strVal(value)),
ObjectIdGetDatum(InvalidOid),
Int32GetDatum(-1));
typeid = ZPBITOID;
typelen = -1;
typebyval = false;
break;
default:
elog(NOTICE, "make_const: unknown type %d", nodeTag(value));
/* FALLTHROUGH */

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.79 2000/10/30 17:54:16 petere Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/scan.l,v 1.80 2000/10/31 10:22:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -93,25 +93,25 @@ static void addlit(char *ytext, int yleng);
* We use exclusive states for quoted strings, extended comments,
* and to eliminate parsing troubles for numeric strings.
* Exclusive states:
* <xb> binary numeric string - thomas 1997-11-16
* <xbit> bit string literal
* <xc> extended C-style comments - thomas 1997-07-12
* <xd> delimited identifiers (double-quoted identifiers) - thomas 1997-10-27
* <xh> hexadecimal numeric string - thomas 1997-11-16
* <xq> quoted strings - thomas 1997-07-30
*/
%x xb
%x xbit
%x xc
%x xd
%x xh
%x xq
/* Binary number
/* Bit string
*/
xbstart [bB]{quote}
xbstop {quote}
xbinside [^']+
xbcat {quote}{whitespace_with_newline}{quote}
xbitstart [bB]{quote}
xbitstop {quote}
xbitinside [^']*
xbitcat {quote}{whitespace_with_newline}{quote}
/* Hexadecimal number
*/
@ -279,30 +279,27 @@ other .
<xc><<EOF>> { elog(ERROR, "Unterminated /* comment"); }
{xbstart} {
BEGIN(xb);
{xbitstart} {
BEGIN(xbit);
startlit();
}
<xb>{xbstop} {
char* endptr;
<xbit>{xbitstop} {
BEGIN(INITIAL);
errno = 0;
yylval.ival = strtol(literalbuf, &endptr, 2);
if (*endptr != '\0' || errno == ERANGE)
elog(ERROR, "Bad binary integer input '%s'",
if (literalbuf[strspn(literalbuf, "01")] != '\0')
elog(ERROR, "invalid bit string input: '%s'",
literalbuf);
return ICONST;
yylval.str = literalbuf;
return BITCONST;
}
<xh>{xhinside} |
<xb>{xbinside} {
<xbit>{xbitinside} {
addlit(yytext, yyleng);
}
<xh>{xhcat} |
<xb>{xbcat} {
<xbit>{xbitcat} {
/* ignore */
}
<xb><<EOF>> { elog(ERROR, "Unterminated binary integer"); }
<xbit><<EOF>> { elog(ERROR, "unterminated bit string literal"); }
{xhstart} {
BEGIN(xh);

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.9 2000/08/26 21:53:41 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.10 2000/10/31 10:22:11 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -1053,8 +1053,8 @@ bitshiftright(PG_FUNCTION_ARGS)
/* Negative shift is a shift to the left */
if (shft < 0)
PG_RETURN_DATUM(DirectFunctionCall2(bitshiftleft,
VarBitPGetDatum(arg),
Int32GetDatum(-shft)));
VarBitPGetDatum(arg),
Int32GetDatum(-shft)));
result = (VarBit *) palloc(VARSIZE(arg));
VARATT_SIZEP(result) = VARSIZE(arg);
@ -1146,3 +1146,99 @@ bittoint4(PG_FUNCTION_ARGS)
PG_RETURN_INT32(result);
}
/* Determines the position of S2 in the bitstring S1 (1-based string).
* If S2 does not appear in S1 this function returns 0.
* If S2 is of length 0 this function returns 1.
*/
Datum
bitposition(PG_FUNCTION_ARGS)
{
VarBit *substr = PG_GETARG_VARBIT_P(1);
VarBit *arg = PG_GETARG_VARBIT_P(0);
int substr_length,
arg_length,
i,
is;
bits8 *s, /* pointer into substring */
*p; /* pointer into arg */
bits8 cmp, /* shifted substring byte to compare */
mask1, /* mask for substring byte shifted right */
mask2, /* mask for substring byte shifted left */
end_mask, /* pad mask for last substring byte */
arg_mask; /* pad mask for last argument byte */
bool is_match;
/* Get the substring length */
substr_length = VARBITLEN(substr);
arg_length = VARBITLEN(arg);
/* Argument has 0 length or substring longer than argument, return 0 */
if (arg_length == 0 || substr_length > arg_length)
PG_RETURN_INT32(0);
/* 0-length means return 1 */
if (substr_length == 0)
PG_RETURN_INT32(1);
/* Initialise the padding masks */
end_mask = BITMASK << VARBITPAD(substr);
arg_mask = BITMASK << VARBITPAD(arg);
for (i = 0; i < VARBITBYTES(arg) - VARBITBYTES(substr) + 1; i++)
{
for (is = 0; is < BITS_PER_BYTE; is++) {
is_match = true;
p = VARBITS(arg) + i;
mask1 = BITMASK >> is;
mask2 = ~mask1;
for (s = VARBITS(substr);
is_match && s < VARBITEND(substr); s++)
{
cmp = *s >> is;
if (s == VARBITEND(substr) - 1)
{
mask1 &= end_mask >> is;
if (p == VARBITEND(arg) - 1) {
/* Check that there is enough of arg left */
if (mask1 & ~arg_mask) {
is_match = false;
break;
}
mask1 &= arg_mask;
}
}
is_match = ((cmp ^ *p) & mask1) == 0;
if (!is_match)
break;
// Move on to the next byte
p++;
if (p == VARBITEND(arg)) {
mask2 = end_mask << (BITS_PER_BYTE - is);
is_match = mask2 == 0;
elog(NOTICE,"S. %d %d em=%2x sm=%2x r=%d",
i,is,end_mask,mask2,is_match);
break;
}
cmp = *s << (BITS_PER_BYTE - is);
if (s == VARBITEND(substr) - 1)
{
mask2 &= end_mask << (BITS_PER_BYTE - is);
if (p == VARBITEND(arg) - 1) {
if (mask2 & ~arg_mask) {
is_match = false;
break;
}
mask2 &= arg_mask;
}
}
is_match = ((cmp ^ *p) & mask2) == 0;
}
/* Have we found a match */
if (is_match)
PG_RETURN_INT32(i*BITS_PER_BYTE + is + 1);
}
}
PG_RETURN_INT32(0);
}

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.53 2000/10/24 03:34:15 tgl Exp $
* $Id: catversion.h,v 1.54 2000/10/31 10:22:12 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200010233
#define CATALOG_VERSION_NO 200010310
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.170 2000/10/24 20:15:45 petere Exp $
* $Id: pg_proc.h,v 1.171 2000/10/31 10:22:12 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -2097,6 +2097,11 @@ DESCR("trim both ends of string");
DATA(insert OID = 885 ( btrim PGUID 14 f t t t 1 f 25 "25" 100 0 0 100 "select btrim($1, \' \')" - ));
DESCR("trim both ends of string");
DATA(insert OID = 936 ( substring PGUID 12 f t t t 3 f 25 "25 23 23" 100 0 0 100 text_substr - ));
DESCR("return portion of string");
DATA(insert OID = 937 ( substring PGUID 14 f t t t 2 f 25 "25 23" 100 0 0 100 "select \042substring\042($1, $2, -1)" - ));
DESCR("return portion of string");
/* for multi-byte support */
DATA(insert OID = 1039 ( getdatabaseencoding PGUID 12 f t f t 0 f 19 "0" 100 0 0 100 getdatabaseencoding - ));
DESCR("encoding name of current database");
@ -2172,8 +2177,8 @@ DATA(insert OID = 1678 ( bitshiftright PGUID 12 f t t t 2 f 1560 "1560 23" 100
DESCR("bitwise right shift");
DATA(insert OID = 1679 ( bitcat PGUID 12 f t t t 2 f 1560 "1560 1560" 100 0 0 100 bitcat - ));
DESCR("bitwise concatenation");
DATA(insert OID = 1680 ( bitsubstr PGUID 12 f t t t 3 f 1560 "1560 23 23" 100 0 0 100 bitsubstr - ));
DESCR("bitwise field");
DATA(insert OID = 1680 ( substring PGUID 12 f t t t 3 f 1560 "1560 23 23" 100 0 0 100 bitsubstr - ));
DESCR("return portion of bitstring");
DATA(insert OID = 1681 ( length PGUID 12 f t t t 1 f 23 "1560" 100 0 0 100 bitlength - ));
DESCR("bitstring length");
DATA(insert OID = 1682 ( octet_length PGUID 12 f t t t 1 f 23 "1560" 100 0 0 100 bitoctetlength - ));
@ -2192,6 +2197,12 @@ DESCR("adjust varbit() to typmod length");
DATA(insert OID = 1688 ( _varbit PGUID 12 f t t t 2 f 1563 "1563 23" 100 0 0 100 _varbit - ));
DESCR("adjust varbit()[] to typmod length");
DATA(insert OID = 1698 ( position PGUID 12 f t t t 2 f 23 "1560 1560" 100 0 0 100 bitposition - ));
DESCR("return position of sub-bitstring");
DATA(insert OID = 1699 ( substring PGUID 14 f t t t 2 f 1560 "1560 23" 100 0 0 100 "select \042substring\042($1, $2, -1)" - ));
DESCR("return portion of bitstring");
/* for mac type support */
DATA(insert OID = 436 ( macaddr_in PGUID 12 f t t t 1 f 829 "0" 100 0 0 100 macaddr_in - ));
DESCR("(internal)");

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodes.h,v 1.80 2000/10/26 21:38:12 tgl Exp $
* $Id: nodes.h,v 1.81 2000/10/31 10:22:12 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -140,6 +140,7 @@ typedef enum NodeTag
T_Integer,
T_Float,
T_String,
T_BitString,
T_Null,
/*---------------------

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_list.h,v 1.21 2000/10/05 19:11:36 tgl Exp $
* $Id: pg_list.h,v 1.22 2000/10/31 10:22:12 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -118,6 +118,7 @@ extern bool intMember(int datum, List *list);
extern Value *makeInteger(long i);
extern Value *makeFloat(char *numericStr);
extern Value *makeString(char *str);
extern Value *makeBitString(char *str);
extern List *lappend(List *list, void *datum);
extern List *lappendi(List *list, int datum);
extern List *lremove(void *elem, List *list);

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: varbit.h,v 1.7 2000/08/26 21:53:40 tgl Exp $
* $Id: varbit.h,v 1.8 2000/10/31 10:22:13 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -87,5 +87,6 @@ extern Datum bitlength(PG_FUNCTION_ARGS);
extern Datum bitoctetlength(PG_FUNCTION_ARGS);
extern Datum bitfromint4(PG_FUNCTION_ARGS);
extern Datum bittoint4(PG_FUNCTION_ARGS);
extern Datum bitposition(PG_FUNCTION_ARGS);
#endif