added qse_awk_backuperrmsg() and qse_awk_rtx_backuperrmsg().

enhanced the module loading code to emit more comprehensive error message in awk/parse.c
removed dynamic exception specification from some methods.
added mysql::affected_rows()
fixed wrong parameter handling in mysql::autocommit().
changed mysql::esacpe_string() to return the result via the second parameter
This commit is contained in:
2019-06-06 12:11:40 +00:00
parent 5ec8e15140
commit 38dc85ddf4
8 changed files with 244 additions and 164 deletions

View File

@ -254,88 +254,6 @@ static int fnc_close (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
return 0;
}
static int fnc_connect (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int ret = -1, take_rtx_err = 0;
qse_awk_val_t* a1, * a2, * a3;
qse_mchar_t* host = QSE_NULL;
qse_mchar_t* user = QSE_NULL;
qse_mchar_t* pass = QSE_NULL;
sql_list = rtx_to_sql_list(rtx, fi);
sql_node = get_sql_list_node_with_arg(rtx, sql_list, qse_awk_rtx_getarg(rtx, 0));
if (sql_node)
{
a1 = qse_awk_rtx_getarg(rtx, 1);
a2 = qse_awk_rtx_getarg(rtx, 2);
a3 = qse_awk_rtx_getarg(rtx, 3);
host = qse_awk_rtx_getvalmbs(rtx, a1, QSE_NULL);
if (!host) { take_rtx_err = 1; goto done; }
user = qse_awk_rtx_getvalmbs(rtx, a2, QSE_NULL);
if (!user) { take_rtx_err = 1; goto done; }
pass = qse_awk_rtx_getvalmbs(rtx, a3, QSE_NULL);
if (!pass) { take_rtx_err = 1; goto done; }
if (!mysql_real_connect(sql_node->mysql, host, user, pass, QSE_NULL, 0, QSE_NULL, 0))
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
sql_node->connect_ever_attempted = 1; /* doesn't matter if mysql_real_connect() failed */
goto done;
}
sql_node->connect_ever_attempted = 1;
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
if (pass) qse_awk_rtx_freevalmbs (rtx, a3, pass);
if (user) qse_awk_rtx_freevalmbs (rtx, a2, user);
if (host) qse_awk_rtx_freevalmbs (rtx, a1, host);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
}
static int fnc_ping (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int ret = -1, take_rtx_err = 0;
sql_list = rtx_to_sql_list(rtx, fi);
sql_node = get_sql_list_node_with_arg(rtx, sql_list, qse_awk_rtx_getarg(rtx, 0));
if (sql_node)
{
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
if (mysql_ping(sql_node->mysql) != 0)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
goto done;
}
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
oops:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
return -1;
}
#if 0
static int fnc_get_option (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
@ -360,12 +278,6 @@ static int fnc_get_option (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
goto oops;
}
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
switch (id)
{
case MYSQL_OPT_CONNECT_TIMEOUT:
@ -484,7 +396,6 @@ static int fnc_set_option (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
goto done;
}
printf ("%d %d\n", (int)id, *(int*)vptr);
if (mysql_options(sql_node->mysql, id, vptr) != 0)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
@ -504,6 +415,93 @@ oops:
return -1;
}
static int fnc_connect (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int ret = -1, take_rtx_err = 0;
qse_awk_val_t* a1, * a2, * a3;
qse_mchar_t* host = QSE_NULL;
qse_mchar_t* user = QSE_NULL;
qse_mchar_t* pass = QSE_NULL;
sql_list = rtx_to_sql_list(rtx, fi);
sql_node = get_sql_list_node_with_arg(rtx, sql_list, qse_awk_rtx_getarg(rtx, 0));
if (sql_node)
{
a1 = qse_awk_rtx_getarg(rtx, 1);
a2 = qse_awk_rtx_getarg(rtx, 2);
a3 = qse_awk_rtx_getarg(rtx, 3);
host = qse_awk_rtx_getvalmbs(rtx, a1, QSE_NULL);
if (!host) { take_rtx_err = 1; goto done; }
user = qse_awk_rtx_getvalmbs(rtx, a2, QSE_NULL);
if (!user) { take_rtx_err = 1; goto done; }
pass = qse_awk_rtx_getvalmbs(rtx, a3, QSE_NULL);
if (!pass) { take_rtx_err = 1; goto done; }
if (!mysql_real_connect(sql_node->mysql, host, user, pass, QSE_NULL, 0, QSE_NULL, 0))
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
sql_node->connect_ever_attempted = 1; /* doesn't matter if mysql_real_connect() failed */
goto done;
}
sql_node->connect_ever_attempted = 1;
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
if (pass) qse_awk_rtx_freevalmbs (rtx, a3, pass);
if (user) qse_awk_rtx_freevalmbs (rtx, a2, user);
if (host) qse_awk_rtx_freevalmbs (rtx, a1, host);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
}
#define ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node) \
do { \
if (!(sql_node)->connect_ever_attempted) \
{ \
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected")); \
goto done; \
} \
} while(0)
static int fnc_ping (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int ret = -1, take_rtx_err = 0;
sql_list = rtx_to_sql_list(rtx, fi);
sql_node = get_sql_list_node_with_arg(rtx, sql_list, qse_awk_rtx_getarg(rtx, 0));
if (sql_node)
{
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
if (mysql_ping(sql_node->mysql) != 0)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
goto done;
}
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
oops:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
return -1;
}
static int fnc_autocommit (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
@ -519,11 +517,7 @@ static int fnc_autocommit (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
v = qse_awk_rtx_valtobool(rtx, qse_awk_rtx_getarg(rtx, 1));
if (v <= -1) { take_rtx_err = 1; goto oops; }
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
if (mysql_autocommit(sql_node->mysql, v) != 0)
{
@ -559,11 +553,7 @@ static int fnc_commit (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
v = qse_awk_rtx_valtobool(rtx, qse_awk_rtx_getarg(rtx, 1));
if (v <= -1) { take_rtx_err = 1; goto oops; }
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
if (mysql_commit(sql_node->mysql) != 0)
{
@ -599,11 +589,7 @@ static int fnc_rollback (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
v = qse_awk_rtx_valtobool(rtx, qse_awk_rtx_getarg(rtx, 1));
if (v <= -1) { take_rtx_err = 1; goto oops; }
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
if (mysql_rollback(sql_node->mysql) != 0)
{
@ -624,11 +610,61 @@ oops:
return -1;
}
static int fnc_affected_rows (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int ret = -1, take_rtx_err = 0;
sql_list = rtx_to_sql_list(rtx, fi);
sql_node = get_sql_list_node_with_arg(rtx, sql_list, qse_awk_rtx_getarg(rtx, 0));
if (sql_node)
{
my_ulonglong nrows;
qse_awk_val_t* vrows;
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
nrows = mysql_affected_rows(sql_node->mysql);
if (nrows == (my_ulonglong)-1)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
goto done;
}
vrows = qse_awk_rtx_makeintval(rtx, nrows);
if (!vrows)
{
take_rtx_err = 1;
goto oops;
}
if (qse_awk_rtx_setrefval(rtx, (qse_awk_val_ref_t*)qse_awk_rtx_getarg(rtx, 1), vrows) <= -1)
{
qse_awk_rtx_refupval (rtx, vrows);
qse_awk_rtx_refdownval (rtx, vrows);
take_rtx_err = 1;
goto oops;
}
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
oops:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
return -1;
}
static int fnc_escape_string (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
{
sql_list_t* sql_list;
sql_node_t* sql_node;
int take_rtx_err = 0;
int ret = -1, take_rtx_err = 0;
qse_awk_val_t* a1, *retv;
qse_mchar_t* qstr = QSE_NULL;
@ -639,7 +675,7 @@ static int fnc_escape_string (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
if (sql_node)
{
qse_size_t qlen;
a1 = qse_awk_rtx_getarg(rtx, 1);
qstr = qse_awk_rtx_getvalmbs(rtx, a1, &qlen);
@ -648,27 +684,38 @@ static int fnc_escape_string (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
ebuf = qse_awk_rtx_allocmem(rtx, (qlen * 2 + 1) * QSE_SIZEOF(*qstr));
if (!ebuf) { take_rtx_err = 1; goto oops; }
if (mysql_real_escape_string(sql_node->mysql, ebuf, qstr, qlen) != 0)
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
mysql_real_escape_string(sql_node->mysql, ebuf, qstr, qlen);
retv = qse_awk_rtx_makestrvalwithmbs(rtx, ebuf);
if (!retv)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("%hs"), mysql_error(sql_node->mysql));
goto done;
take_rtx_err = 1;
goto oops;
}
if (qse_awk_rtx_setrefval(rtx, (qse_awk_val_ref_t*)qse_awk_rtx_getarg(rtx, 2), retv) <= -1)
{
qse_awk_rtx_refupval (rtx, retv);
qse_awk_rtx_refdownval (rtx, retv);
take_rtx_err = 1;
goto oops;
}
ret = 0;
}
done:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
if (qstr) qse_awk_rtx_freevalmbs (rtx, a1, qstr);
retv = ebuf? qse_awk_rtx_makestrvalwithmbs(rtx, ebuf): qse_awk_rtx_makenilval(rtx);
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
if (ebuf) qse_awk_rtx_freemem (rtx, ebuf);
if (!retv) return -1;
qse_awk_rtx_setretval (rtx, retv);
if (qstr) qse_awk_rtx_freevalmbs (rtx, a1, qstr);
qse_awk_rtx_setretval (rtx, qse_awk_rtx_makeintval(rtx, ret));
return 0;
oops:
if (take_rtx_err) set_error_on_sql_list (rtx, sql_list, QSE_NULL);
if (qstr) qse_awk_rtx_freevalmbs (rtx, a1, qstr);
if (ebuf) qse_awk_rtx_freemem (rtx, ebuf);
if (qstr) qse_awk_rtx_freevalmbs (rtx, a1, qstr);
return -1;
}
@ -691,11 +738,7 @@ static int fnc_query (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
qstr = qse_awk_rtx_getvalmbs(rtx, a1, &qlen);
if (!qstr) { take_rtx_err = 1; goto oops; }
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
if (mysql_real_query(sql_node->mysql, qstr, qlen) != 0)
{
@ -734,11 +777,7 @@ static int fnc_store_result (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
res_list = rtx_to_res_list(rtx, fi);
if (!sql_node->connect_ever_attempted)
{
set_error_on_sql_list (rtx, sql_list, QSE_T("not connected"));
goto done;
}
ENSURE_CONNECT_EVER_ATTEMPTED(rtx, sql_list, sql_node);
res = mysql_store_result(sql_node->mysql);
if (!res)
@ -888,21 +927,22 @@ struct inttab_t
static fnctab_t fnctab[] =
{
/* keep this table sorted for binary search in query(). */
{ QSE_T("autocommit"), { { 1, 1, QSE_NULL }, fnc_autocommit, 0 } },
{ QSE_T("close"), { { 1, 1, QSE_NULL }, fnc_close, 0 } },
{ QSE_T("commit"), { { 1, 1, QSE_NULL }, fnc_commit, 0 } },
{ QSE_T("connect"), { { 4, 8, QSE_NULL }, fnc_connect, 0 } },
{ QSE_T("errmsg"), { { 0, 0, QSE_NULL }, fnc_errmsg, 0 } },
{ QSE_T("escape_string"), { { 2, 2, QSE_NULL }, fnc_escape_string, 0 } },
{ QSE_T("fetch_row"), { { 2, 2, QSE_T("vr") }, fnc_fetch_row, 0 } },
{ QSE_T("free_result"), { { 1, 1, QSE_NULL }, fnc_free_result, 0 } },
/*{ QSE_T("get_option"), { { 3, 3, QSE_T("vr") }, fnc_get_option, 0 } },*/
{ QSE_T("open"), { { 0, 0, QSE_NULL }, fnc_open, 0 } },
{ QSE_T("ping"), { { 1, 1, QSE_NULL }, fnc_ping, 0 } },
{ QSE_T("query"), { { 2, 2, QSE_NULL }, fnc_query, 0 } },
{ QSE_T("rollback"), { { 1, 1, QSE_NULL }, fnc_rollback, 0 } },
{ QSE_T("set_option"), { { 3, 3, QSE_NULL }, fnc_set_option, 0 } },
{ QSE_T("store_result"), { { 1, 1, QSE_NULL }, fnc_store_result, 0 } }
{ QSE_T("affected_rows"), { { 2, 2, QSE_T("vr") }, fnc_affected_rows, 0 } },
{ QSE_T("autocommit"), { { 2, 2, QSE_NULL }, fnc_autocommit, 0 } },
{ QSE_T("close"), { { 1, 1, QSE_NULL }, fnc_close, 0 } },
{ QSE_T("commit"), { { 1, 1, QSE_NULL }, fnc_commit, 0 } },
{ QSE_T("connect"), { { 4, 8, QSE_NULL }, fnc_connect, 0 } },
{ QSE_T("errmsg"), { { 0, 0, QSE_NULL }, fnc_errmsg, 0 } },
{ QSE_T("escape_string"), { { 3, 3, QSE_T("vvr") }, fnc_escape_string, 0 } },
{ QSE_T("fetch_row"), { { 2, 2, QSE_T("vr") }, fnc_fetch_row, 0 } },
{ QSE_T("free_result"), { { 1, 1, QSE_NULL }, fnc_free_result, 0 } },
/*{ QSE_T("get_option"), { { 3, 3, QSE_T("vr") }, fnc_get_option, 0 } },*/
{ QSE_T("open"), { { 0, 0, QSE_NULL }, fnc_open, 0 } },
{ QSE_T("ping"), { { 1, 1, QSE_NULL }, fnc_ping, 0 } },
{ QSE_T("query"), { { 2, 2, QSE_NULL }, fnc_query, 0 } },
{ QSE_T("rollback"), { { 1, 1, QSE_NULL }, fnc_rollback, 0 } },
{ QSE_T("set_option"), { { 3, 3, QSE_NULL }, fnc_set_option, 0 } },
{ QSE_T("store_result"), { { 1, 1, QSE_NULL }, fnc_store_result, 0 } }
};
static inttab_t inttab[] =
@ -1023,6 +1063,7 @@ static void unload (qse_awk_mod_t* mod, qse_awk_t* awk)
QSE_ASSERT (QSE_RBT_SIZE(rbt) == 0);
qse_rbt_close (rbt);
//mysql_library_end ();
}
int qse_awk_mod_mysql (qse_awk_mod_t* mod, qse_awk_t* awk)