};
size_t sql_rcode_table_len = NUM_ELEMENTS(sql_rcode_table);
-#if 0
-/*************************************************************************
- *
- * Function: sql_pair_afrom_row
- *
- * Purpose: Convert one rlm_sql_row_t to a fr_pair_t, and add it to "out"
- *
- *************************************************************************/
-static int sql_pair_afrom_row(TALLOC_CTX *ctx, request_t *request, fr_pair_list_t *out, rlm_sql_row_t row, fr_pair_t **relative_vp)
-{
- fr_pair_t *vp;
- char const *ptr, *value;
- char buf[FR_MAX_STRING_LEN];
- fr_dict_attr_t const *da;
- fr_token_t token, op = T_EOL;
- fr_pair_list_t *my_list;
- TALLOC_CTX *my_ctx;
-
- /*
- * Verify the 'Attribute' field
- */
- if (!row[2] || row[2][0] == '\0') {
- REDEBUG("Attribute field is empty or NULL, skipping the entire row");
- return -1;
- }
-
- /*
- * Verify the 'op' field
- */
- if (row[4] != NULL && row[4][0] != '\0') {
- ptr = row[4];
- op = gettoken(&ptr, buf, sizeof(buf), false);
- if (!fr_assignment_op[op] && !fr_comparison_op[op]) {
- REDEBUG("Invalid op \"%s\" for attribute %s", row[4], row[2]);
- return -1;
- }
-
- } else {
- /*
- * Complain about empty or invalid 'op' field
- */
- op = T_OP_CMP_EQ;
- REDEBUG("The op field for attribute '%s = %s' is NULL, or non-existent.", row[2], row[3]);
- REDEBUG("You MUST FIX THIS if you want the configuration to behave as you expect");
- }
-
- /*
- * The 'Value' field may be empty or NULL
- */
- if (!row[3]) {
- REDEBUG("Value field is empty or NULL, skipping the entire row");
- return -1;
- }
-
- RDEBUG3("Found row[%s]: %s %s %s", row[0], row[2], fr_table_str_by_value(fr_tokens_table, op, "<INVALID>"), row[3]);
-
- value = row[3];
-
- /*
- * If we have a string, where the *entire* string is
- * quoted, do xlat's.
- */
- if (row[3] != NULL &&
- ((row[3][0] == '\'') || (row[3][0] == '`') || (row[3][0] == '"')) &&
- (row[3][0] == row[3][strlen(row[3])-1])) {
-
- token = gettoken(&value, buf, sizeof(buf), false);
- switch (token) {
- /*
- * Take the unquoted string.
- */
- case T_BACK_QUOTED_STRING:
- case T_SINGLE_QUOTED_STRING:
- case T_DOUBLE_QUOTED_STRING:
- value = buf;
- break;
-
- /*
- * Keep the original string.
- */
- default:
- value = row[3];
- break;
- }
- }
-
- /*
- * Check for relative attributes
- *
- * @todo - allow "..foo" to mean "grandparent of
- * relative_vp", and it should also update relative_vp
- * with the new parent. However, doing this means
- * walking the list of the current relative_vp, finding
- * the dlist head, and then converting that into a
- * fr_pair_t pointer. That's complex, so we don't do it
- * right now.
- */
- if (row[2][0] == '.') {
- char const *p = row[2];
-
- if (!*relative_vp) {
- REDEBUG("Relative attribute '%s' can only be used immediately after an attribute of type 'group'", row[2]);
- return -1;
- }
-
- da = fr_dict_attr_by_oid(NULL, (*relative_vp)->da, p + 1);
- if (!da) goto unknown;
-
- my_list = &(*relative_vp)->vp_group;
- my_ctx = *relative_vp;
-
- MEM(vp = fr_pair_afrom_da(my_ctx, da));
- fr_pair_append(my_list, vp);
- } else {
- /*
- * Search in our local dictionary
- * falling back to internal.
- */
- da = fr_dict_attr_by_oid(NULL, fr_dict_root(request->dict), row[2]);
- if (!da) {
- da = fr_dict_attr_by_oid(NULL, fr_dict_root(fr_dict_internal()), row[2]);
- if (!da) {
- unknown:
- RPEDEBUG("Unknown attribute '%s'", row[2]);
- return -1;
- }
- }
-
- my_list = out;
- my_ctx = ctx;
-
- MEM(vp = fr_pair_afrom_da_nested(my_ctx, my_list, da));
- }
-
- vp->op = op;
-
- if ((vp->vp_type == FR_TYPE_TLV) && !*value) {
- /*
- * Allow empty values for TLVs: we just create the value.
- *
- * fr_pair_value_from_str() is not yet updated to
- * handle TLVs. Until such time as we know what
- * to do there, we will just do a hack here,
- * specific to the SQL module.
- */
- } else {
- if (fr_pair_value_from_str(vp, value, strlen(value), NULL, true) < 0) {
- RPEDEBUG("Error parsing value");
- return -1;
- }
- }
-
- /*
- * Update the relative vp.
- */
- if (my_list == out) switch (da->type) {
- case FR_TYPE_STRUCTURAL:
- *relative_vp = vp;
- break;
-
- default:
- break;
- }
-
- /*
- * If there's a relative VP, and it's not the one
- * we just added above, and we're not adding this
- * VP to the relative one, then nuke the relative
- * VP.
- */
- if (*relative_vp && (vp != *relative_vp) && (my_ctx != *relative_vp)) {
- *relative_vp = NULL;
- }
-
- return 0;
-}
-#endif
-
/** Call the driver's sql_fetch_row function
*
* Calls the driver's sql_fetch_row logging any errors. On success, will