#include <ctype.h>
#include "db_sql_codegen.h"
static void
hc_warn(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "Warning: ");
vfprintf(stderr, fmt, ap);
fprintf(stderr, ", near line %d\n", line_number);
va_end(ap);
}
static char *
static_copy_minus_whitespace(in, len)
const char *in;
int len;
{
#define smw_bufsiz 10240
static char out[smw_bufsiz];
int in_i;
int out_i;
int in_quote;
in_quote = 0;
for (in_i = out_i = 0; in_i < len && in[in_i] != '\0'; in_i++) {
if (in[in_i] == '"') {
if (in_quote) in_quote = 0;
else in_quote = 1;
}
if (in_quote || ! isspace(in[in_i])) {
out[out_i++] = in[in_i];
assert(out_i < smw_bufsiz);
}
}
out[out_i] = '\0';
return out;
}
static char *
hint_comment_from_token(t)
Token *t;
{
int len;
char *p;
len = 0;
p = NULL;
if (t == NULL)
return NULL;
if (t->z[0] == '/') {
assert(t->n >= 4 &&
t->z[1] == '*' &&
t->z[t->n - 2] == '*' &&
t->z[t->n - 1] == '/');
p = ((char *)t->z) + 2;
len = t->n - 4;
} else if (t->z[0] == '-') {
assert(t->n >= 3 &&
t->z[1] == '-');
p = ((char *)t->z) + 2;
len = t->n - 2;
}
assert(p != NULL);
if (*p != '+')
return NULL;
return static_copy_minus_whitespace(p+1, len-1);
}
static char *
split(in, delimiter, rest)
char *in;
char delimiter;
char **rest;
{
char *p;
*rest = NULL;
for (p = in; ! (*p == delimiter || *p == '\0'); p++)
;
if (*p != '\0') {
*rest = p + 1;
*p = '\0';
}
return in;
}
static
unsigned long int parse_integer(s)
char *s;
{
unsigned long int x;
char *t;
x = strtoul(s, &t, 0);
if (s == t)
hc_warn("cannot parse integer string %s", s);
switch (*t) {
case '\0':
break;
case 'k':
case 'K':
x = x * KILO;
t++;
break;
case 'm':
case 'M':
x = x * MEGA;
t++;
break;
case 'g':
case 'G':
x = x * GIGA;
t++;
break;
}
if (*t != '\0')
hc_warn("unrecognized characters in integer string %s", s);
return x;
}
static void
apply_environment_property(key, value)
char *key;
char *value;
{
if (strcasecmp(key, "CACHESIZE") == 0) {
the_schema.environment.cache_size = parse_integer(value);
} else if (strcasecmp(key, "MODE") == 0) {
if (strcasecmp(value, "TRANSACTIONAL") == 0) {
the_schema.environment.transactional = 1;
} else if (strcasecmp(value, "NONTRANSACTIONAL") == 0) {
the_schema.environment.transactional = txnflag;
} else {
hc_warn("Unrecognized environment value %s", value);
}
} else {
hc_warn("Unrecognized environment property %s", key);
}
}
static void
set_dbtype(entity, value)
ENTITY *entity;
char *value;
{
if (strcasecmp(value, "btree") == 0) {
entity->dbtype = "DB_BTREE";
} else if (strcasecmp(value, "hash") == 0) {
entity->dbtype = "DB_HASH";
} else {
hc_warn(
"unknown DBTYPE %s for antecedent %s, using default of DB_BTREE",
value, entity->name);
entity->dbtype = "DB_BTREE";
}
}
static void
set_idx_dbtype(idx, value)
DB_INDEX *idx;
char *value;
{
if (strcasecmp(value, "btree") == 0) {
idx->dbtype = "DB_BTREE";
} else if (strcasecmp(value, "hash") == 0) {
idx->dbtype = "DB_HASH";
} else {
hc_warn(
"unknown DBTYPE %s for antecedent %s, using default of DB_BTREE",
value, idx->name);
idx->dbtype = "DB_BTREE";
}
}
static void
set_transactional(entity, value)
ENTITY *entity;
char *value;
{
if (strcasecmp(value, "TRANSACTIONAL") == 0) {
if (the_schema.environment.transactional) {
entity->transactional = 1;
} else {
hc_warn("Wrong entity value %s", value);
}
} else if (strcasecmp(value, "NONTRANSACTIONAL") == 0) {
entity->transactional = txnflag;
} else {
hc_warn("Unrecognized entity value %s", value);
}
}
static void
apply_entity_property(key, value, entity)
char *key;
char *value;
ENTITY *entity;
{
if (strcasecmp(key, "DBTYPE") == 0) {
set_dbtype(entity, value);
} else if (strcasecmp(key, "MODE") == 0) {
set_transactional(entity, value);
} else {
hc_warn("Unrecognized entity property %s", key);
}
}
static void
apply_index_property(key, value, idx)
char *key;
char *value;
DB_INDEX *idx;
{
if (strcasecmp(key, "DBTYPE") == 0) {
set_idx_dbtype(idx, value);
} else {
hc_warn("Unrecognized index property %s", key);
}
}
static void
apply_configuration_property(key, value)
char * key;
char *value;
{
switch (the_parse_progress.last_event) {
case PE_NONE:
hc_warn(
"Property setting (%s) with no antecedent SQL statement",
key);
break;
case PE_ENVIRONMENT:
apply_environment_property(key, value);
break;
case PE_ENTITY:
case PE_ATTRIBUTE:
apply_entity_property(key, value,
the_parse_progress.last_entity);
break;
case PE_INDEX:
apply_index_property(key, value, the_parse_progress.last_index);
}
}
void parse_hint_comment(t)
Token *t;
{
char *assignment, *key, *value;
char *comment;
comment = hint_comment_from_token(t);
if (comment == NULL)
return;
while (! (comment == NULL || *comment == '\0')) {
assignment = split(comment, ',', &comment);
key = split(assignment, '=', &value);
if (value == NULL) {
hc_warn("No value specified for property %s\n",
key);
break;
}
apply_configuration_property(key, value);
key = split(key, '=', &value);
if (value != NULL)
hc_warn(
"Warning: incorrect hint comment syntax with property %s",
key);
}
}