1
0
Fork 0

free string memory

This commit is contained in:
Jan Steemann 2014-07-25 11:43:19 +02:00
parent 6b8ac46cca
commit 92d42168a5
8 changed files with 196 additions and 59 deletions

View File

@ -60,7 +60,6 @@ namespace triagens {
double _double;
bool _bool;
char const* _string;
// void* _data; // TODO: decide if still needed
} value;
AstNodeValueType type;
};

View File

@ -47,6 +47,7 @@ Parser::Parser (Query* query)
_remainingLength(query->queryLength()),
_offset(0),
_marker(nullptr),
_subQueryCount(0),
_uniqueId(0),
_stack() {
@ -68,6 +69,41 @@ Parser::~Parser () {
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief set data for write queries
////////////////////////////////////////////////////////////////////////////////
bool Parser::configureWriteQuery (QueryType type,
AstNode const* collectionNode,
AstNode* optionNode) {
TRI_ASSERT(type != AQL_QUERY_READ);
// check if we currently are in a subquery
if (isInSubQuery()) {
// data modification not allowed in sub-queries
registerError(TRI_ERROR_QUERY_MODIFY_IN_SUBQUERY);
return false;
}
// check current query type
auto oldType = _query->type();
if (oldType != AQL_QUERY_READ) {
// already a data-modification query, cannot have two data-modification operations in one query
registerError(TRI_ERROR_QUERY_MULTI_MODIFY);
return false;
}
// now track which collection is going to be modified
ast()->setWriteCollection(collectionNode);
ast()->setWriteOptions(optionNode);
// register type
_query->type(type);
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief parse the query
////////////////////////////////////////////////////////////////////////////////
@ -95,7 +131,7 @@ char* Parser::generateName () {
int n = snprintf(buffer, sizeof(buffer) - 1, "_%d", (int) ++_uniqueId);
// register the string and return a copy of it
return registerString(buffer, static_cast<size_t>(n), false);
return ast()->registerString(buffer, static_cast<size_t>(n), false);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -117,6 +117,31 @@ namespace triagens {
return _query->ast();
}
////////////////////////////////////////////////////////////////////////////////
/// @brief start a subquery
////////////////////////////////////////////////////////////////////////////////
inline void startSubQuery () {
++_subQueryCount;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief end a subquery
////////////////////////////////////////////////////////////////////////////////
inline void endSubQuery () {
TRI_ASSERT(_subQueryCount > 0);
--_subQueryCount;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not we are in a subquery
////////////////////////////////////////////////////////////////////////////////
inline bool isInSubQuery () const {
return (_subQueryCount > 0);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief return the scanner
////////////////////////////////////////////////////////////////////////////////
@ -185,24 +210,12 @@ namespace triagens {
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
/// @brief set data for write queries
////////////////////////////////////////////////////////////////////////////////
char* registerString (char const* p,
size_t length,
bool mustEscape) {
// TODO: IMPLEMENT
// TODO: throw exception in case of OOM
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief set the query type
////////////////////////////////////////////////////////////////////////////////
void type (QueryType type) {
_query->type(type);
}
bool configureWriteQuery (QueryType,
AstNode const*,
AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief parse the query
@ -276,6 +289,7 @@ namespace triagens {
size_t _offset; // current parse position
char const* _marker; // a position used temporarily during parsing
size_t _subQueryCount; // number of active subqueries
size_t _uniqueId; // a counter to generate unique (temporary) variable names

View File

@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////////////////////////
#include "Aql/QueryAst.h"
#include "BasicsC/tri-strings.h"
#include "Utils/Exception.h"
using namespace triagens::aql;
@ -42,8 +43,11 @@ using namespace triagens::aql;
QueryAst::QueryAst ()
: _nodes(),
_strings(),
_scopes(),
_root(nullptr) {
_root(nullptr),
_writeCollection(nullptr),
_writeOptions(nullptr) {
_nodes.reserve(32);
_root = createNode(NODE_TYPE_ROOT);
@ -54,6 +58,12 @@ QueryAst::QueryAst ()
////////////////////////////////////////////////////////////////////////////////
QueryAst::~QueryAst () {
// free strings
for (auto it = _strings.begin(); it != _strings.end(); ++it) {
TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, const_cast<char*>(*it));
}
// free nodes
for (auto it = _nodes.begin(); it != _nodes.end(); ++it) {
delete (*it);
}
@ -73,6 +83,41 @@ void QueryAst::addOperation (AstNode* node) {
TRI_PushBackVectorPointer(&_root->members, (void*) node);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
////////////////////////////////////////////////////////////////////////////////
char* QueryAst::registerString (char const* p,
size_t length,
bool mustUnescape) {
if (p == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
char* copy = nullptr;
if (mustUnescape && length > 0) {
size_t outLength;
copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, p, length, &outLength);
}
else {
copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, p, length);
}
if (copy == nullptr) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
try {
_strings.push_back(copy);
}
catch (...) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
return copy;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope start node
////////////////////////////////////////////////////////////////////////////////
@ -167,9 +212,6 @@ AstNode* QueryAst::createNodeRemove (AstNode const* expression,
AstNode* node = createNode(NODE_TYPE_REMOVE);
node->addMember(expression);
/* TODO
SetWriteOperation(context, collection, TRI_AQL_QUERY_REMOVE, options);
*/
return node;
}
@ -182,9 +224,7 @@ AstNode* QueryAst::createNodeInsert (AstNode const* expression,
AstNode* options) {
AstNode* node = createNode(NODE_TYPE_INSERT);
node->addMember(expression);
/* TODO
SetWriteOperation(context, collection, TRI_AQL_QUERY_INSERT, options);
*/
return node;
}
@ -203,9 +243,6 @@ AstNode* QueryAst::createNodeUpdate (AstNode const* keyExpression,
node->addMember(keyExpression);
}
/* TODO
SetWriteOperation(context, collection, TRI_AQL_QUERY_UPDATE, options);
*/
return node;
}
@ -224,9 +261,6 @@ AstNode* QueryAst::createNodeReplace (AstNode const* keyExpression,
node->addMember(keyExpression);
}
/* TODO
SetWriteOperation(context, collection, TRI_AQL_QUERY_REPLACE, options);
*/
return node;
}

View File

@ -79,12 +79,38 @@ namespace triagens {
return &_scopes;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief track the write collection
////////////////////////////////////////////////////////////////////////////////
inline void setWriteCollection (AstNode const* node) {
TRI_ASSERT(node->type == NODE_TYPE_COLLECTION ||
node->type == NODE_TYPE_PARAMETER);
_writeCollection = node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief track the write query options
////////////////////////////////////////////////////////////////////////////////
inline void setWriteOptions (AstNode const* node) {
_writeOptions = node;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief add an operation to the root node
////////////////////////////////////////////////////////////////////////////////
void addOperation (AstNode*);
////////////////////////////////////////////////////////////////////////////////
/// @brief register a string
////////////////////////////////////////////////////////////////////////////////
char* registerString (char const*,
size_t,
bool);
////////////////////////////////////////////////////////////////////////////////
/// @brief create an AST scope start node
////////////////////////////////////////////////////////////////////////////////
@ -353,6 +379,12 @@ namespace triagens {
std::vector<AstNode*> _nodes;
////////////////////////////////////////////////////////////////////////////////
/// @brief all strings created in the AST - will be used for freeing them later
////////////////////////////////////////////////////////////////////////////////
std::vector<char const*> _strings;
////////////////////////////////////////////////////////////////////////////////
/// @brief all scopes used in the query
////////////////////////////////////////////////////////////////////////////////
@ -365,6 +397,18 @@ namespace triagens {
AstNode* _root;
////////////////////////////////////////////////////////////////////////////////
/// @brief which collection is going to be modified in the query
////////////////////////////////////////////////////////////////////////////////
AstNode const* _writeCollection;
////////////////////////////////////////////////////////////////////////////////
/// @brief which options are used for write queries
////////////////////////////////////////////////////////////////////////////////
AstNode const* _writeOptions;
};
}

View File

@ -52,8 +52,8 @@ void Aqlerror (YYLTYPE* locp,
/// @brief shortcut macro for signalling out of memory
////////////////////////////////////////////////////////////////////////////////
#define ABORT_OOM \
/* TODO: TRI_SetErrorContextAql(__FILE__, __LINE__, context, TRI_ERROR_OUT_OF_MEMORY, NULL); */ \
#define ABORT_OOM \
parser->registerError(TRI_ERROR_OUT_OF_MEMORY); \
YYABORT;
#define scanner parser->scanner()
@ -193,19 +193,14 @@ void Aqlerror (YYLTYPE* locp,
query:
optional_statement_block_statements return_statement {
parser->type(triagens::aql::AQL_QUERY_READ);
}
| optional_statement_block_statements remove_statement {
parser->type(triagens::aql::AQL_QUERY_REMOVE);
}
| optional_statement_block_statements insert_statement {
parser->type(triagens::aql::AQL_QUERY_INSERT);
}
| optional_statement_block_statements update_statement {
parser->type(triagens::aql::AQL_QUERY_UPDATE);
}
| optional_statement_block_statements replace_statement {
parser->type(triagens::aql::AQL_QUERY_REPLACE);
}
;
@ -369,6 +364,9 @@ in_or_into_collection:
remove_statement:
T_REMOVE expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_REMOVE, $3, $4)) {
YYABORT;
}
auto node = parser->ast()->createNodeRemove($2, $3, $4);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
@ -377,6 +375,9 @@ remove_statement:
insert_statement:
T_INSERT expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_INSERT, $3, $4)) {
YYABORT;
}
auto node = parser->ast()->createNodeInsert($2, $3, $4);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
@ -385,11 +386,17 @@ insert_statement:
update_statement:
T_UPDATE expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_UPDATE, $3, $4)) {
YYABORT;
}
auto node = parser->ast()->createNodeUpdate(nullptr, $2, $3, $4);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
}
| T_UPDATE expression T_WITH expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_UPDATE, $5, $6)) {
YYABORT;
}
auto node = parser->ast()->createNodeUpdate($2, $4, $5, $6);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
@ -398,11 +405,17 @@ update_statement:
replace_statement:
T_REPLACE expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_REPLACE, $3, $4)) {
YYABORT;
}
auto node = parser->ast()->createNodeReplace(nullptr, $2, $3, $4);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
}
| T_REPLACE expression T_WITH expression in_or_into_collection query_options {
if (! parser->configureWriteQuery(AQL_QUERY_REPLACE, $5, $6)) {
YYABORT;
}
auto node = parser->ast()->createNodeReplace($2, $4, $5, $6);
parser->ast()->addOperation(node);
parser->ast()->scopes()->endNested();
@ -415,13 +428,10 @@ expression:
}
| T_OPEN {
parser->ast()->scopes()->start(triagens::aql::AQL_SCOPE_SUBQUERY);
/* TODO: context->_subQueries++; */
parser->startSubQuery();
} query T_CLOSE {
/* TODO: context->_subQueries--; */
if (! parser->ast()->scopes()->endCurrent()) {
ABORT_OOM
}
parser->endSubQuery();
parser->ast()->scopes()->endCurrent();
auto subQuery = parser->ast()->createNodeSubquery();
parser->ast()->addOperation(subQuery);
@ -479,7 +489,7 @@ function_name:
std::string temp($1);
temp.append("::");
temp.append($3);
$$ = parser->registerString(temp.c_str(), temp.size(), false);
$$ = parser->ast()->registerString(temp.c_str(), temp.size(), false);
if ($$ == nullptr) {
ABORT_OOM

View File

@ -1284,7 +1284,7 @@ case 47:
YY_RULE_SETUP
{
/* unquoted string */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_STRING;
}
YY_BREAK
@ -1301,7 +1301,7 @@ YY_RULE_SETUP
{
/* end of backtick-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_STRING;
}
YY_BREAK
@ -1339,7 +1339,7 @@ YY_RULE_SETUP
{
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
YY_BREAK
@ -1377,7 +1377,7 @@ YY_RULE_SETUP
{
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
YY_BREAK
@ -1407,7 +1407,7 @@ case 63:
YY_RULE_SETUP
{
/* a numeric integer value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_INTEGER;
}
YY_BREAK
@ -1415,7 +1415,7 @@ case 64:
YY_RULE_SETUP
{
/* a numeric double value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_DOUBLE;
}
YY_BREAK
@ -1427,7 +1427,7 @@ YY_RULE_SETUP
{
/* bind parameters must start with a @
if followed by another @, this is a collection name parameter */
yylval->strval = yyextra->registerString(yytext + 1, yyleng - 1, false);
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
return T_PARAMETER;
}
YY_BREAK

View File

@ -259,7 +259,7 @@ namespace triagens {
([a-zA-Z][_a-zA-Z0-9]*|_+[a-zA-Z]+[_a-zA-Z0-9]*) {
/* unquoted string */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_STRING;
}
@ -272,7 +272,7 @@ namespace triagens {
<BACKTICK>` {
/* end of backtick-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_STRING;
}
@ -299,7 +299,7 @@ namespace triagens {
<DOUBLE_QUOTE>\" {
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
@ -326,7 +326,7 @@ namespace triagens {
<SINGLE_QUOTE>' {
/* end of quote-enclosed string */
BEGIN(INITIAL);
yylval->strval = yyextra->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
yylval->strval = yyextra->ast()->registerString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, true);
return T_QUOTED_STRING;
}
@ -347,13 +347,13 @@ namespace triagens {
(0|[1-9][0-9]*) {
/* a numeric integer value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_INTEGER;
}
(0|[1-9][0-9]*)(\.[0-9]+([eE]([\-\+])?[0-9]+)?) {
/* a numeric double value */
yylval->strval = yyextra->registerString(yytext, yyleng, false);
yylval->strval = yyextra->ast()->registerString(yytext, yyleng, false);
return T_DOUBLE;
}
@ -364,7 +364,7 @@ namespace triagens {
@@?[a-zA-Z0-9][a-zA-Z0-9_]* {
/* bind parameters must start with a @
if followed by another @, this is a collection name parameter */
yylval->strval = yyextra->registerString(yytext + 1, yyleng - 1, false);
yylval->strval = yyextra->ast()->registerString(yytext + 1, yyleng - 1, false);
return T_PARAMETER;
}