summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <msvensson@pilot.(none)>2007-06-01 12:04:05 +0200
committerunknown <msvensson@pilot.(none)>2007-06-01 12:04:05 +0200
commit2fdaa5931d07fd349ef45d7a440e50ad96491eff (patch)
treedc8ebea99a2e06e4e0e2e85a698cae63b8586954
parent6c789278885423044a526a7ce543b30bcb0e425f (diff)
parent5b0e66a752a780e93f35e7cc5ff063cc1110384d (diff)
downloadmariadb-git-2fdaa5931d07fd349ef45d7a440e50ad96491eff.tar.gz
Merge pilot.(none):/data/msvensson/mysql/bug28497/my41-bug28497-query_get_value
into pilot.(none):/data/msvensson/mysql/bug28497/my50-bug28497 client/mysqltest.c: Auto merged mysql-test/r/mysqltest.result: Auto merged mysql-test/t/mysqltest.test: Auto merged
-rw-r--r--client/mysqltest.c239
-rw-r--r--mysql-test/r/mysqltest.result39
-rw-r--r--mysql-test/t/mysqltest.test121
3 files changed, 365 insertions, 34 deletions
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 5640d0c24ba..665fa9c581e 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -1143,6 +1143,50 @@ void check_require(DYNAMIC_STRING* ds, const char *fname)
}
+/*
+ Remove surrounding chars from string
+
+ Return 1 if first character is found but not last
+*/
+static int strip_surrounding(char* str, char c1, char c2)
+{
+ char* ptr= str;
+
+ /* Check if the first non space character is c1 */
+ while(*ptr && my_isspace(charset_info, *ptr))
+ ptr++;
+ if (*ptr == c1)
+ {
+ /* Replace it with a space */
+ *ptr= ' ';
+
+ /* Last non space charecter should be c2 */
+ ptr= strend(str)-1;
+ while(*ptr && my_isspace(charset_info, *ptr))
+ ptr--;
+ if (*ptr == c2)
+ {
+ /* Replace it with \0 */
+ *ptr= 0;
+ }
+ else
+ {
+ /* Mismatch detected */
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+static void strip_parentheses(struct st_command *command)
+{
+ if (strip_surrounding(command->first_argument, '(', ')'))
+ die("%.*s - argument list started with '%c' must be ended with '%c'",
+ command->first_word_len, command->query, '(', ')');
+}
+
+
static byte *get_var_key(const byte* var, uint* len,
my_bool __attribute__((unused)) t)
{
@@ -1398,12 +1442,11 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
init_dynamic_string(&ds_query, 0, (end - query) + 32, 256);
do_eval(&ds_query, query, end, FALSE);
- if (mysql_real_query(mysql, ds_query.str, ds_query.length) ||
- !(res = mysql_store_result(mysql)))
- {
+ if (mysql_real_query(mysql, ds_query.str, ds_query.length))
die("Error running query '%s': %d %s", ds_query.str,
mysql_errno(mysql), mysql_error(mysql));
- }
+ if (!(res= mysql_store_result(mysql)))
+ die("Query '%s' didn't return a result set", ds_query.str);
dynstr_free(&ds_query);
if ((row = mysql_fetch_row(res)) && row[0])
@@ -1457,6 +1500,130 @@ void var_query_set(VAR *var, const char *query, const char** query_end)
}
+/*
+ Set variable from the result of a field in a query
+
+ This function is useful when checking for a certain value
+ in the output from a query that can't be restricted to only
+ return some values. A very good example of that is most SHOW
+ commands.
+
+ SYNOPSIS
+ var_set_query_get_value()
+
+ DESCRIPTION
+ let $variable= query_get_value(<query to run>,<column name>,<row no>);
+
+ <query to run> - The query that should be sent to the server
+ <column name> - Name of the column that holds the field be compared
+ against the expected value
+ <row no> - Number of the row that holds the field to be
+ compared against the expected value
+
+*/
+
+void var_set_query_get_value(struct st_command *command, VAR *var)
+{
+ ulong row_no;
+ int col_no= -1;
+ MYSQL_RES* res;
+ MYSQL* mysql= &cur_con->mysql;
+ LINT_INIT(res);
+
+ static DYNAMIC_STRING ds_query;
+ static DYNAMIC_STRING ds_col;
+ static DYNAMIC_STRING ds_row;
+ const struct command_arg query_get_value_args[] = {
+ "query", ARG_STRING, TRUE, &ds_query, "Query to run",
+ "column name", ARG_STRING, TRUE, &ds_col, "Name of column",
+ "row number", ARG_STRING, TRUE, &ds_row, "Number for row",
+ };
+
+ DBUG_ENTER("var_set_query_get_value");
+
+ strip_parentheses(command);
+ DBUG_PRINT("info", ("query: %s", command->query));
+ check_command_args(command, command->first_argument, query_get_value_args,
+ sizeof(query_get_value_args)/sizeof(struct command_arg),
+ ',');
+
+ DBUG_PRINT("info", ("query: %s", ds_query.str));
+ DBUG_PRINT("info", ("col: %s", ds_col.str));
+
+ /* Convert row number to int */
+ if (!str2int(ds_row.str, 10, (long) 0, (long) INT_MAX, &row_no))
+ die("Invalid row number: '%s'", ds_row.str);
+ DBUG_PRINT("info", ("row: %s, row_no: %ld", ds_row.str, row_no));
+ dynstr_free(&ds_row);
+
+ /* Remove any surrounding "'s from the query - if there is any */
+ if (strip_surrounding(ds_query.str, '"', '"'))
+ die("Mismatched \"'s around query '%s'", ds_query.str);
+
+ /* Run the query */
+ if (mysql_real_query(mysql, ds_query.str, ds_query.length))
+ die("Error running query '%s': %d %s", ds_query.str,
+ mysql_errno(mysql), mysql_error(mysql));
+ if (!(res= mysql_store_result(mysql)))
+ die("Query '%s' didn't return a result set", ds_query.str);
+
+ {
+ /* Find column number from the given column name */
+ uint i;
+ uint num_fields= mysql_num_fields(res);
+ MYSQL_FIELD *fields= mysql_fetch_fields(res);
+
+ for (i= 0; i < num_fields; i++)
+ {
+ if (strcmp(fields[i].name, ds_col.str) == 0 &&
+ strlen(fields[i].name) == ds_col.length)
+ {
+ col_no= i;
+ break;
+ }
+ }
+ if (col_no == -1)
+ {
+ mysql_free_result(res);
+ die("Could not find column '%s' in the result of '%s'",
+ ds_col.str, ds_query.str);
+ }
+ DBUG_PRINT("info", ("Found column %d with name '%s'",
+ i, fields[i].name));
+ }
+ dynstr_free(&ds_col);
+
+ {
+ /* Get the value */
+ MYSQL_ROW row;
+ ulong rows= 0;
+ const char* value= "No such row";
+
+ while ((row= mysql_fetch_row(res)))
+ {
+ if (++rows == row_no)
+ {
+
+ DBUG_PRINT("info", ("At row %ld, column %d is '%s'",
+ row_no, col_no, row[col_no]));
+ /* Found the row to get */
+ if (row[col_no])
+ value= row[col_no];
+ else
+ value= "NULL";
+
+ break;
+ }
+ }
+ eval_expr(var, value, 0);
+ }
+ dynstr_free(&ds_query);
+ mysql_free_result(res);
+
+ DBUG_VOID_RETURN;
+}
+
+
void var_copy(VAR *dest, VAR *src)
{
dest->int_val= src->int_val;
@@ -1480,26 +1647,47 @@ void var_copy(VAR *dest, VAR *src)
void eval_expr(VAR *v, const char *p, const char **p_end)
{
- static int MIN_VAR_ALLOC= 32; /* MASV why 32? */
- VAR *vp;
+
+ DBUG_ENTER("eval_expr");
+ DBUG_PRINT("enter", ("p: '%s'", p));
+
if (*p == '$')
{
+ VAR *vp;
if ((vp= var_get(p, p_end, 0, 0)))
- {
var_copy(v, vp);
- return;
- }
+ DBUG_VOID_RETURN;
}
- else if (*p == '`')
+
+ if (*p == '`')
{
var_query_set(v, p, p_end);
+ DBUG_VOID_RETURN;
}
- else
+
+ {
+ /* Check if this is a "let $var= query_get_value()" */
+ const char* get_value_str= "query_get_value";
+ const size_t len= strlen(get_value_str);
+ if (strncmp(p, get_value_str, len)==0)
+ {
+ struct st_command command;
+ memset(&command, 0, sizeof(command));
+ command.query= (char*)p;
+ command.first_word_len= len;
+ command.first_argument= command.query + len;
+ command.end= (char*)*p_end;
+ var_set_query_get_value(&command, v);
+ DBUG_VOID_RETURN;
+ }
+ }
+
{
int new_val_len = (p_end && *p_end) ?
(int) (*p_end - p) : (int) strlen(p);
if (new_val_len + 1 >= v->alloced_len)
{
+ static int MIN_VAR_ALLOC= 32;
v->alloced_len = (new_val_len < MIN_VAR_ALLOC - 1) ?
MIN_VAR_ALLOC : new_val_len + 1;
if (!(v->str_val =
@@ -1512,9 +1700,10 @@ void eval_expr(VAR *v, const char *p, const char **p_end)
memcpy(v->str_val, p, new_val_len);
v->str_val[new_val_len] = 0;
v->int_val=atoi(p);
+ DBUG_PRINT("info", ("atoi on '%s', returns: %d", p, v->int_val));
v->int_dirty=0;
}
- return;
+ DBUG_VOID_RETURN;
}
@@ -3453,7 +3642,6 @@ void do_connect(struct st_command *command)
int con_port= opt_port;
char *con_options;
bool con_ssl= 0, con_compress= 0;
- char *ptr;
static DYNAMIC_STRING ds_connection_name;
static DYNAMIC_STRING ds_host;
@@ -3481,20 +3669,7 @@ void do_connect(struct st_command *command)
DBUG_ENTER("do_connect");
DBUG_PRINT("enter",("connect: %s", command->first_argument));
- /* Remove parenteses around connect arguments */
- if ((ptr= strstr(command->first_argument, "(")))
- {
- /* Replace it with a space */
- *ptr= ' ';
- if ((ptr= strstr(command->first_argument, ")")))
- {
- /* Replace it with \0 */
- *ptr= 0;
- }
- else
- die("connect - argument list started with '(' must be ended with ')'");
- }
-
+ strip_parentheses(command);
check_command_args(command, command->first_argument, connect_args,
sizeof(connect_args)/sizeof(struct command_arg),
',');
@@ -4192,16 +4367,12 @@ int read_command(struct st_command** command_ptr)
DBUG_RETURN(0);
}
if (!(*command_ptr= command=
- (struct st_command*) my_malloc(sizeof(*command), MYF(MY_WME))) ||
+ (struct st_command*) my_malloc(sizeof(*command),
+ MYF(MY_WME|MY_ZEROFILL))) ||
insert_dynamic(&q_lines, (gptr) &command))
die(NullS);
-
- command->require_file[0]= 0;
- command->first_word_len= 0;
- command->query_len= 0;
-
command->type= Q_UNKNOWN;
- command->query_buf= command->query= 0;
+
read_command_buf[0]= 0;
if (read_line(read_command_buf, sizeof(read_command_buf)))
{
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 35dcf9b62d2..389f20e0407 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -666,4 +666,43 @@ INSERT INTO t1 SELECT f1 - 256 FROM t1;
INSERT INTO t1 SELECT f1 - 512 FROM t1;
SELECT * FROM t1;
DROP TABLE t1;
+CREATE TABLE t1(
+a int, b varchar(255), c datetime
+);
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b varchar(255) YES NULL
+c datetime YES NULL
+statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=int(11)
+statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=int(11)
+statement=SHOW COLUMNS FROM t1 row_number=1, column_name=Default, Value=NULL
+value= ->A B<-
+value= 1
+mysqltest: At line 1: query_get_value - argument list started with '(' must be ended with ')'
+mysqltest: At line 1: Missing required argument 'query' to command 'query_get_value'
+mysqltest: At line 1: Missing required argument 'column name' to command 'query_get_value'
+mysqltest: At line 1: Missing required argument 'row number' to command 'query_get_value'
+value= No such row
+value= No such row
+mysqltest: At line 1: Invalid row number: 'notnumber'
+mysqltest: At line 1: Could not find column 'column_not_exists' in the result of 'SHOW COLUMNS FROM t1'
+mysqltest: At line 1: Query 'SET @A = 1' didn't return a result set
+mysqltest: At line 1: Could not find column '1 AS B' in the result of 'SELECT 1 AS A'
+value= No such row
+mysqltest: At line 1: Error running query 'SHOW COLNS FROM t1': 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'COLNS FROM t1' at line 1
+
+Field Type Null Key Default Extra
+a int(11) YES -><- NULL
+b varchar(255) YES -><- NULL
+c datetime YES -><- NULL
+
+Number of columns with Default NULL: 3
+
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+a int(11) YES NULL
+b varchar(255) YES NULL
+c datetime YES NULL
+drop table t1;
End of tests
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index 057432d37fd..cf93df3b0c1 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -1877,4 +1877,125 @@ DROP TABLE t1;
--exec $MYSQL_TEST a b c 2>&1 > /dev/null
--enable_abort_on_error
+# ----------------------------------------------------------------------------
+# test for query_get_value
+# ----------------------------------------------------------------------------
+
+CREATE TABLE t1(
+ a int, b varchar(255), c datetime
+);
+SHOW COLUMNS FROM t1;
+
+#------------ Positive tests ------------
+# 1. constant parameters
+# value is simple string without spaces
+let $value= query_get_value(SHOW COLUMNS FROM t1, Type, 1);
+--echo statement=SHOW COLUMNS FROM t1 row_number=1, column_name="Type", Value=$value
+let $value= query_get_value("SHOW COLUMNS FROM t1", Type, 1);
+--echo statement="SHOW COLUMNS FROM t1" row_number=1, column_name="Type", Value=$value
+#
+# 2. $variables as parameters
+# value IS NULL
+let $my_show= SHOW COLUMNS FROM t1;
+let $column_name= Default;
+let $row_number= 1;
+let $value= query_get_value($my_show, $column_name, $row_number);
+--echo statement=$my_show row_number=$row_number, column_name=$column_name, Value=$value
+#
+# 3. result set of a SELECT (not recommended, because projection and
+# selection could be done much better by pure SELECT functionality)
+# value is string with space in the middle
+let $value= query_get_value(SELECT 'A B' AS "MyColumn", MyColumn, 1);
+--echo value= ->$value<-
+#
+# 4. column name with space
+let $value= query_get_value(SELECT 1 AS "My Column", My Column, 1);
+--echo value= $value
+#
+#------------ Negative tests ------------
+# 5. Incomplete statement including missing parameters
+# 5.1 incomplete statement
+--error 1
+--exec echo "let \$value= query_get_value(SHOW;" | $MYSQL_TEST 2>&1
+# 5.2 missing query
+--error 1
+--exec echo "let \$value= query_get_value;" | $MYSQL_TEST 2>&1
+# 5.3 missing column name
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1);" | $MYSQL_TEST 2>&1
+# 5.4 missing row number
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field);" | $MYSQL_TEST 2>&1
+#
+# 6. Somehow "wrong" value of parameters
+# 6.1 row parameter
+# 6.1.1 non sense number 0
+let $value= initialized;
+let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 0);
+--echo value= $value
+# 6.1.2 after the last row
+let $value= initialized;
+let $value= query_get_value(SHOW COLUMNS FROM t1, Field, 10);
+--echo value= $value
+# 6.1.3 invalid row number
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, Field, notnumber);" | $MYSQL_TEST 2>&1
+# 6.2 column name parameter, name of not existing column
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLUMNS FROM t1, column_not_exists, 1);" | $MYSQL_TEST 2>&1
+# 6.3. statement which never gives a result set
+--error 1
+--exec echo "let \$value= query_get_value(SET @A = 1, Field, 1);" | $MYSQL_TEST 2>&1
+# 6.4. statement contains a ","
+# Note: There is no need to improve this, because we need query_get_value
+# for SHOW commands only.
+--error 1
+--exec echo "let \$value= query_get_value(SELECT 1 AS "A", 1 AS "B", 1);" | $MYSQL_TEST 2>&1
+#
+# 7. empty result set
+let $value= initialized;
+let $value= query_get_value(SELECT a FROM t1, a, 1);
+--echo value= $value
+#
+# 9. failing statement
+--error 1
+--exec echo "let \$value= query_get_value(SHOW COLNS FROM t1, Field, 1);" | $MYSQL_TEST 2>&1
+#
+# 10. Artificial example how to process a complete SHOW result set:
+let $show_statement= SHOW COLUMNS FROM t1;
+let $rowno= 1;
+let $run=1;
+let $count= 0;
+--echo
+--echo Field Type Null Key Default Extra
+while ($run)
+{
+ let $Field= query_get_value($show_statement, Field, $rowno);
+ if (`SELECT '$Field' = 'No such row'`)
+ {
+ let $run= 0;
+ }
+ if (`SELECT '$Field' <> 'No such row'`)
+ {
+ let $Type= query_get_value($show_statement, Type, $rowno);
+ let $Null= query_get_value($show_statement, Null, $rowno);
+ if (`SELECT '$Null' = 'YES'`)
+ {
+ inc $count;
+ }
+ let $Key= query_get_value($show_statement, Key, $rowno);
+ let $Default= query_get_value($show_statement, Default, $rowno);
+ let $Extra= query_get_value($show_statement, Extra, $rowno);
+ --echo $Field $Type $Null ->$Key<- $Default $Extra
+ inc $rowno;
+ }
+}
+--echo
+--echo Number of columns with Default NULL: $count
+--echo
+eval $show_statement;
+
+drop table t1;
+
--echo End of tests
+