/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2005,2008 Oracle. All rights reserved.
*
* $Id: query.c,v 1.17 2008/01/08 20:58:23 bostic Exp $
*/
#include "csv.h"
#include "csv_local.h"
#include "csv_extern.h"
static int query_by_field(char *);
static int query_fieldlist(char *);
static int query_help(char *);
static int query_usage(void);
typedef struct _cmdtab {
char *cmd; /* Command name */
int (*f)(char *); /* Underlying function. */
char *help; /* Help message. */
} CMDTAB;
static CMDTAB cmdtab[] = {
{ "?",
query_help,
"?\t\tDisplay help screen" },
{ "exit",
NULL,
"exit\t\tExit program" },
{ "fields",
query_fieldlist,
"fields\t\tDisplay list of field names" },
{ "help",
query_help,
"help\t\tDisplay help screen" },
{ "quit",
NULL,
"quit\t\tExit program" },
{ NULL,
query_by_field,
"field[op]value\tDisplay fields by value (=, !=, <, <=, >, >=, ~, !~)" },
{ NULL, NULL, NULL }
};
/*
* query_interactive --
* Allow the user to interactively query the database.
*/
int
query_interactive()
{
int done;
char *p, input[256];
for (;;) {
printf("Query: ");
(void)fflush(stdout);
if (fgets(input, sizeof(input), stdin) == NULL) {
printf("\n");
if (ferror(stdin)) {
dbenv->err(dbenv, errno,
"error occurred reading from stdin");
return (1);
}
break;
}
if ((p = strchr(input, '\n')) == NULL) {
dbenv->errx(dbenv, "input buffer too small");
return (1);
}
*p = '\0';
if (query(input, &done) != 0)
return (1);
if (done != 0)
break;
}
return (0);
}
/*
* query --
* Process a query.
*/
int
query(char *cmd, int *donep)
{
CMDTAB *p;
if (donep != NULL)
*donep = 0;
for (p = cmdtab; p->cmd != NULL; ++p)
if (p->cmd != NULL &&
strncasecmp(cmd, p->cmd, strlen(p->cmd)) == 0)
break;
if (p->cmd == NULL)
return (query_by_field(cmd));
if (p->f == NULL) {
if (donep != NULL)
*donep = 1;
return (0);
}
return (p->f(cmd));
}
/*
* query_by_field --
* Query the primary database by field.
*/
static int
query_by_field(char *input)
{
OPERATOR operator;
size_t len;
char *field, *op, *value;
/*
* We expect to see "field [op] value" -- figure it out.
*
* Skip leading whitespace.
*/
while (isspace(*input))
++input;
/*
* Find an operator, and it better not start the string.
*/
if ((len = strcspn(field = input, "<>!=~")) == 0)
return (query_usage());
op = field + len;
/* Figure out the operator, and find the start of the value. */
switch (op[0]) {
case '~':
operator = WC;
value = op + 1;
break;
case '!':
if (op[1] == '=') {
operator = NEQ;
value = op + 2;
break;
}
if (op[1] == '~') {
operator = NWC;
value = op + 2;
break;
}
return (query_usage());
case '<':
if (op[1] == '=') {
operator = LTEQ;
value = op + 2;
} else {
operator = LT;
value = op + 1;
}
break;
case '=':
operator = EQ;
if (op[1] == '=')
value = op + 2;
else
value = op + 1;
break;
case '>':
if (op[1] == '=') {
operator = GTEQ;
value = op + 2;
} else {
operator = GT;
value = op + 1;
}
break;
default:
return (query_usage());
}
/* Terminate the field name, and there better be a field name. */
while (--op > input && isspace(*op))
;
if (op == input)
return (query_usage());
op[1] = '\0';
/* Make sure there is a value field. */
while (isspace(*value))
++value;
if (*value == '\0')
return (query_usage());
return (DbRecord_search_field_name(field, value, operator));
}
/*
* query_fieldlist --
* Display list of field names.
*/
static int
query_fieldlist(char *input)
{
DbField *f;
input = input; /* Quiet compiler. */
for (f = fieldlist; f->name != NULL; ++f)
printf("field %3d: %s\n", f->fieldno, f->name);
return (0);
}
/*
* query_help --
* Query command list.
*/
static int
query_help(char *input)
{
CMDTAB *p;
input = input; /* Quiet compiler. */
printf("Query commands:\n");
for (p = cmdtab; p->help != NULL; ++p)
printf("\t%s\n", p->help);
return (0);
}
/*
* query_usage --
* Query usage message.
*/
static int
query_usage(void)
{
fprintf(stderr, "%s: query syntax error\n", progname);
return (query_help(NULL));
}
Copyright 2K16 - 2K18 Indonesian Hacker Rulez