Skip to content

Commit

Permalink
Fixed CORE-2607 - Introducer (_charset) problems with monitoring and …
Browse files Browse the repository at this point in the history
…persistent modules
  • Loading branch information
asfernandes committed Aug 30, 2009
1 parent 4c9f54b commit f590889
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 19 deletions.
54 changes: 54 additions & 0 deletions src/dsql/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "../dsql/Parser.h"
#include "../jrd/jrd.h"

using namespace Firebird;
using namespace Jrd;


Expand All @@ -33,6 +34,8 @@ Parser::Parser(MemoryPool& pool, USHORT aClientDialect, USHORT aDbDialect, USHOR
client_dialect(aClientDialect),
db_dialect(aDbDialect),
parser_version(aParserVersion),
transformedString(pool),
introducerMarks(pool),
stmt_ambiguous(false)
{
yyps = 0;
Expand All @@ -48,6 +51,7 @@ Parser::Parser(MemoryPool& pool, USHORT aClientDialect, USHORT aDbDialect, USHOR
yylexp = 0;
yylexemes = 0;

lex.start = string;
lex.line_start = lex.ptr = string;
lex.end = string + length;
lex.lines = 1;
Expand Down Expand Up @@ -90,6 +94,56 @@ Parser::YYSTYPE Parser::parse()
if (parseAux() != 0)
return NULL;

transformString(lex.start, lex.end - lex.start, transformedString);

return DSQL_parse;
}


// Transform strings (or substrings) prefixed with introducer (_charset) to ASCII equivalent.
void Parser::transformString(const char* start, unsigned length, string& dest)
{
const static char HEX_DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'};

unsigned fromBegin = start - lex.start;
HalfStaticArray<char, 256> buffer;
const char* pos = start;

for (size_t i = 0; i < introducerMarks.getCount(); ++i)
{
const IntroducerMark& mark = introducerMarks[i];

if (mark.pos < fromBegin)
continue;
else if (mark.pos >= fromBegin + length)
break;

const char* s = lex.start + mark.pos;
buffer.add(pos, s - pos);

size_t count = buffer.getCount();
buffer.grow(count + 2 + mark.textLength * 2 + 1);
char* p = buffer.begin() + count;

*p++ = 'X';
*p++ = '\'';

const char* s2 = lex.start + mark.textPos;

for (const char* end = lex.start + mark.textPos + mark.textLength; s2 < end; ++s2)
{
*p++ = HEX_DIGITS[UCHAR(*s2) >> 4];
*p++ = HEX_DIGITS[UCHAR(*s2) & 0xF];
}

*p = '\'';

pos = s + mark.length;
}

fb_assert(start + length - pos >= 0);
buffer.add(pos, start + length - pos);

dest = string(buffer.begin(), MIN(string::max_length(), buffer.getCount()));
}
19 changes: 19 additions & 0 deletions src/dsql/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Parser : public Firebird::PermanentStorage
const TEXT* ptr;
const TEXT* end;
const TEXT* last_token;
const TEXT* start;
const TEXT* line_start;
const TEXT* last_token_bk;
const TEXT* line_start_bk;
Expand All @@ -86,6 +87,14 @@ class Parser : public Firebird::PermanentStorage
USHORT param_number;
};

struct IntroducerMark
{
unsigned pos;
unsigned length;
unsigned textPos;
unsigned textLength;
};

public:
Parser(MemoryPool& pool, USHORT aClientDialect, USHORT aDbDialect, USHORT aParserVersion,
const TEXT* string, USHORT length, SSHORT characterSet);
Expand All @@ -94,11 +103,19 @@ class Parser : public Firebird::PermanentStorage
public:
YYSTYPE parse();

const Firebird::string& getTransformedString()
{
return transformedString;
}

bool isStmtAmbiguous() const
{
return stmt_ambiguous;
}

private:
void transformString(const char* start, unsigned length, Firebird::string& dest);

// start - defined in btyacc_fb.ske
private:
static void yySCopy(YYSTYPE* to, YYSTYPE* from, int size);
Expand Down Expand Up @@ -134,6 +151,8 @@ class Parser : public Firebird::PermanentStorage
USHORT db_dialect;
USHORT parser_version;

Firebird::string transformedString;
Firebird::Array<IntroducerMark> introducerMarks;
bool stmt_ambiguous;
YYSTYPE DSQL_parse;

Expand Down
3 changes: 2 additions & 1 deletion src/dsql/dsql.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2540,7 +2540,6 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti
statement->req_dbb = database;
statement->req_transaction = transaction;
statement->req_client_dialect = client_dialect;
statement->req_sql_text = FB_NEW(pool) RefString(pool, Firebird::string(pool, string, string_length));
statement->req_traced = true;

trace.setStatement(statement);
Expand All @@ -2554,6 +2553,8 @@ static dsql_req* prepare(thread_db* tdbb, dsql_dbb* database, jrd_tra* transacti

dsql_nod* node = parser.parse();

statement->req_sql_text = FB_NEW(pool) RefString(pool, parser.getTransformedString());

if (!node)
{
// CVC: Apparently, dsql_ypparse won't return if the command is incomplete,
Expand Down
19 changes: 11 additions & 8 deletions src/dsql/dsql.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,21 @@ namespace Jrd {
//! generic data type used to store strings
class dsql_str : public pool_alloc_rpt<char, dsql_type_str>
{
public:
enum Type
{
TYPE_SIMPLE = 0,
TYPE_HEXA,
TYPE_DELIMITED
};

public:
const char* str_charset; // ASCIIZ Character set identifier for string
//USHORT str_flags;
bool delimited_id;
ULONG str_length; // length of string in BYTES
char str_data[2]; // one for ALLOC and one for the NULL
Type type;
ULONG str_length; // length of string in BYTES
char str_data[2]; // one for ALLOC and one for the NULL
};

// values used in str_flags

//const USHORT STR_delimited_id = 0x1L;

// blocks used to cache metadata

//! Database Block
Expand Down
2 changes: 1 addition & 1 deletion src/dsql/gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ void GEN_statement( CompiledStatement* statement, dsql_nod* node)
{
stuff(statement, blr_exception);
}
if (!string->delimited_id)
if (string->type != dsql_str::TYPE_DELIMITED)
{
ULONG id_length = string->str_length;
for (TEXT* p = string->str_data; *p && id_length; ++p, --id_length)
Expand Down
36 changes: 27 additions & 9 deletions src/dsql/parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -2121,7 +2121,9 @@ begin_trigger :
end_trigger :
{
const TEXT* start = lex.beginnings.pop();
$$ = (dsql_nod*) MAKE_string(start, lex_position() - start);
string str;
transformString(start, lex_position() - start, str);
$$ = (dsql_nod*) MAKE_string(str.c_str(), str.length());
}
;

Expand Down Expand Up @@ -4407,12 +4409,28 @@ internal_info : CURRENT_CONNECTION
MAKE_const_slong (internal_rows_affected)); }
;

sql_string : STRING /* string in current charset */
{ $$ = $1; }
| INTRODUCER STRING /* string in specific charset */
{ ((dsql_str*) $2)->str_charset = (TEXT*) $1;
$$ = $2; }
;
sql_string
: STRING // string in current charset
{ $$ = $1; }
| INTRODUCER STRING // string in specific charset
{
dsql_str* str = (dsql_str*) $2;
str->str_charset = (TEXT*) $1;
if (str->type == dsql_str::TYPE_SIMPLE)
{
IntroducerMark mark;
mark.pos = lex.last_token - lex.start;
mark.length = lex.ptr - lex.last_token;
mark.textLength = str->str_length;

fb_assert(mark.length - mark.textLength == 2);
mark.textPos = mark.pos + 1;

introducerMarks.push(mark);
}
$$ = $2;
}
;

signed_short_integer : nonneg_short_integer
| '-' neg_short_integer
Expand Down Expand Up @@ -5639,8 +5657,7 @@ int Parser::yylexAux()
}
yylval = (dsql_nod*) MAKE_string(buffer, p - buffer);
dsql_str* delimited_id_str = (dsql_str*) yylval;
//delimited_id_str->str_flags |= STR_delimited_id;
delimited_id_str->delimited_id = true;
delimited_id_str->type = dsql_str::TYPE_DELIMITED;
if (buffer != string)
gds__free (buffer);
return SYMBOL;
Expand Down Expand Up @@ -5768,6 +5785,7 @@ int Parser::yylexAux()
}

dsql_str* string = MAKE_string(temp.c_str(), temp.length());
string->type = dsql_str::TYPE_HEXA;
string->str_charset = "BINARY";
yylval = (dsql_nod*) string;

Expand Down

0 comments on commit f590889

Please sign in to comment.