Ejemplo n.º 1
0
/**
 * Bind params, give real values into prepared statement.
 * Up to two sets of parameters are provided.
 * Both of them are used in UPDATE command, params1 as colspecs and values and
 * params2 as WHERE clause. In other cases one set could be enough because values
 * or match (WHERE clause) is needed.
 * @param st MySQL command statement
 * @param params1 first set of params
 * @param params2 second set of params
 * @return 0 if OK, <0 on MySQL error, >0 on DB API error
 * @see update_params
 */
static int bind_mysql_params(MYSQL_STMT* st, db_fld_t* params1, db_fld_t* params2)
{
	int my_idx, fld_idx;
	int count1, count2;
	MYSQL_BIND* my_params;
	int err = 0;

	/* Calculate the number of parameters */
	for(count1 = 0; !DB_FLD_EMPTY(params1) && !DB_FLD_LAST(params1[count1]); count1++);
	for(count2 = 0; !DB_FLD_EMPTY(params2) && !DB_FLD_LAST(params2[count2]); count2++);
	if (st->param_count != count1 + count2) {
		BUG("mysql: Number of parameters in SQL command does not match number of DB API parameters\n");
		return 1;
	}
	
	my_params = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * (count1 + count2));
	if (my_params == NULL) {
		ERR("mysql: No memory left\n");
		return -1;
	}
	memset(my_params, '\0', sizeof(MYSQL_BIND) * (count1 + count2));

	/* params1 */
	my_idx = 0;
	for (fld_idx = 0; fld_idx < count1; fld_idx++, my_idx++) {
		set_field(&my_params[my_idx], params1 + fld_idx);
	}
	/* params2 */
	for (fld_idx = 0; fld_idx < count2; fld_idx++, my_idx++) {
		set_field(&my_params[my_idx], params2 + fld_idx);
	}

	err = mysql_stmt_bind_param(st, my_params);
	if (err) {
		ERR("mysql: libmysqlclient: %d, %s\n", 
			mysql_stmt_errno(st), mysql_stmt_error(st));
		goto error;
	}

	/* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
	 * creates a copy in the statement and we will update it there
	 */
	pkg_free(my_params);
	return err;
   
 error:
	if (my_params) pkg_free(my_params);
	return err;
}
Ejemplo n.º 2
0
/* skip fields belonging to a field which is requested for filtering at client side */
inline static void skip_client_side_filtering_fields(db_cmd_t* cmd, db_fld_t **fld) {
	struct ld_fld* lfld;
	db_fld_t *f;
try_next:
	if (DB_FLD_EMPTY(*fld) || DB_FLD_LAST(**fld)) return; 
	for (f=cmd->result; !DB_FLD_EMPTY(f) && !DB_FLD_LAST(*f); f++) {
		lfld = DB_GET_PAYLOAD(f);
		if (lfld->client_side_filtering && lfld->filter) {
			int j;
			for (j = 0; lfld->filter[j]; j++) {
				if (lfld->filter[j] == *fld) {
					(*fld)++;
					goto try_next;
				}
			}
		}
	}
}
Ejemplo n.º 3
0
void db_fld_free(db_fld_t* fld)
{
	int i;
	
	if (DB_FLD_EMPTY(fld)) return;
	for(i = 0; !DB_FLD_LAST(fld[i]); i++) {
		db_gen_free(&fld[i].gen);
	}
	pkg_free(fld);
}
Ejemplo n.º 4
0
int ld_resolve_fld(db_fld_t* fld, struct ld_cfg* cfg)
{
	int i;
	struct ld_fld* lfld;

	if (fld == NULL || cfg == NULL) return 0;

	for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		lfld = DB_GET_PAYLOAD(fld + i);
		lfld->attr.s = ld_find_attr_name(&lfld->syntax, cfg, fld[i].name);
		if (lfld->attr.s == NULL) lfld->attr.s = fld[i].name;
		if (lfld->attr.s) lfld->attr.len = strlen(lfld->attr.s);
	}
	return 0;
}
Ejemplo n.º 5
0
int flat_cmd(db_cmd_t* cmd)
{
	struct flat_cmd* fcmd;
	db_con_t* con;

	if (cmd->type != DB_PUT) {
		ERR("flatstore: The driver supports PUT operation only.\n");
		return -1;
	}

	if (DB_FLD_EMPTY(cmd->vals)) {
		ERR("flatstore: PUT command with no values encountered\n");
		return -1;
	}

	fcmd = (struct flat_cmd*)pkg_malloc(sizeof(struct flat_cmd));
	if (fcmd == NULL) {
		ERR("flatstore: No memory left\n");
		return -1;
	}
	memset(fcmd, '\0', sizeof(struct flat_cmd));
	if (db_drv_init(&fcmd->gen, flat_cmd_free) < 0) goto error;

	/* FIXME */
	con = cmd->ctx->con[db_payload_idx];
	if (flat_open_table(&fcmd->file_index, con, &cmd->table) < 0) goto error;

	DB_SET_PAYLOAD(cmd, fcmd);
	return 0;

 error:
	if (fcmd) {
		DB_SET_PAYLOAD(cmd, NULL);
		db_drv_free(&fcmd->gen);
		pkg_free(fcmd);
	}
	return -1;
}
Ejemplo n.º 6
0
int ld_incindex(db_fld_t* fld) {
	int i;
	struct ld_fld* lfld;


	if (fld == NULL) return 0;

	i = 0;
	while (!DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i])) {
		lfld = DB_GET_PAYLOAD(fld + i);
		lfld->index++;
		/* the index limit has been reached */
		if (lfld->index >= lfld->valuesnum) {
			lfld->index = 0;
		} else {
			return 0;
		}
		i++;
	}

	/* there is no more value combination left */
	return 1;
}
Ejemplo n.º 7
0
int ld_cmd_setopt(db_cmd_t* cmd, char* optname, va_list ap)
{
	struct ld_fld* lfld;
	char* val, *c;
	int i;
		
	if (!strcasecmp("client_side_filtering", optname)) {
		val = va_arg(ap, char*);

		for(i = 0; !DB_FLD_EMPTY(cmd->result) && !DB_FLD_LAST(cmd->result[i]); i++) {
			c = val;
			do {
				c = strstr(c, cmd->result[i].name);
				if (c) {
					if ((c == val || is_space(*(c-1))) && is_space(*(c+strlen(cmd->result[i].name)))) {
						lfld = (struct ld_fld*)DB_GET_PAYLOAD(cmd->result + i);
						lfld->client_side_filtering = 1;
						break;
					}
					c += strlen(cmd->result[i].name);
				}
			} while (c != NULL);
		}
	}
Ejemplo n.º 8
0
int build_update_sql(str* sql_cmd, db_cmd_t* cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
							  .size = 0, .increment = 128};
	db_fld_t* fld;
	int i, rv = 0;
	str tmpstr;

	rv = sb_add(&sql_buf, &strings[STR_UPDATE]); /* "UPDATE " */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
	rv |= sb_add(&sql_buf, &cmd->table);		 /* table name */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
	rv |= sb_add(&sql_buf, &strings[STR_SET]);	 /* " SET " */

	/* column name-value pairs */
	for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
		rv |= sb_add(&sql_buf, set_str(&tmpstr, "="));
		rv |= sb_add(&sql_buf, &strings[STR_ESC]);
		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
	}
	if (rv) goto error;

	if (!DB_FLD_EMPTY(cmd->match)) {
		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));

			switch(fld[i].op) {
			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
			case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
			}
			
			rv |= sb_add(&sql_buf, get_marker(i + 1));
			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
		}
	}
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;

	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


int build_insert_sql(str* sql_cmd, db_cmd_t* cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
									.size = 0, .increment = 128};
	db_fld_t* fld;
	int i, rv = 0;
	str tmpstr;

	rv = sb_add(&sql_buf, &strings[STR_INSERT]); /* "INSERT INTO " */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
	rv |= sb_add(&sql_buf, &cmd->table);		 /* table name */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\" ("));

	/* column names */
	for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
	}
	if (rv) goto error;

	rv |= sb_add(&sql_buf, &strings[STR_VALUES]);

	for(i = 0, fld = cmd->vals; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		rv |= sb_add(&sql_buf, get_marker(i + 1));
		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
	}
	rv |= sb_add(&sql_buf, set_str(&tmpstr, ")"));
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;
				 
	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


int build_delete_sql(str* sql_cmd, db_cmd_t* cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
									.size = 0, .increment = 128};
	db_fld_t* fld;
	int i, rv = 0;
	str tmpstr;

	rv = sb_add(&sql_buf, &strings[STR_DELETE]); /* "DELETE FROM " */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
	rv |= sb_add(&sql_buf, &cmd->table);		 /* table name */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));

	if (!DB_FLD_EMPTY(cmd->match)) {
		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));

			switch(fld[i].op) {
			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
			case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
			}
			
			rv |= sb_add(&sql_buf, get_marker(i + 1));
			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
		}
	}
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;

	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


int build_select_sql(str* sql_cmd, db_cmd_t* cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
									.size = 0, .increment = 128};
	db_fld_t* fld;
	int i, rv = 0;
	str tmpstr;

	rv = sb_add(&sql_buf, &strings[STR_SELECT]); /* "SELECT " */

	if (DB_FLD_EMPTY(cmd->result)) {
		rv |= sb_add(&sql_buf, set_str(&tmpstr, "*"));
	} else {
		for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ","));
		}
	}

	rv |= sb_add(&sql_buf, &strings[STR_FROM]);  /* " FROM " */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));
	rv |= sb_add(&sql_buf, &cmd->table);		 /* table name */
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\""));

	if (!DB_FLD_EMPTY(cmd->match)) {
		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));

			switch(fld[i].op) {
			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
			case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
			}
			
			rv |= sb_add(&sql_buf, get_marker(i + 1));
			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
		}
	}
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;

	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


int build_select_oid_sql(str* sql_cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
									.size = 0, .increment = 128};
	int rv = 0;
	
	rv = sb_add(&sql_buf, &strings[STR_OID]);
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;

	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

 error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


int build_timestamp_format_sql(str* sql_cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, 
									.size = 0, .increment = 128};
	int rv = 0;
	
	rv = sb_add(&sql_buf, &strings[STR_TIMESTAMP]);
	rv |= sb_add(&sql_buf, &strings[STR_ZT]);
	if (rv) goto error;

	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

 error:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}
Ejemplo n.º 9
0
int ld_cmd(db_cmd_t* cmd)
{
	struct ld_cmd* lcmd;
	struct ld_cfg* cfg;
	struct ld_fld* lfld;
	int i, j;

	lcmd = (struct ld_cmd*)pkg_malloc(sizeof(struct ld_cmd));
	if (lcmd == NULL) {
		ERR("ldap: No memory left\n");
		goto error;
	}
	memset(lcmd, '\0', sizeof(struct ld_cmd));
	if (db_drv_init(&lcmd->gen, ld_cmd_free) < 0) goto error;

	switch(cmd->type) {
	case DB_PUT:
	case DB_DEL:
	case DB_UPD:
		ERR("ldap: The driver does not support directory modifications yet.\n");
		goto error;
		break;

	case DB_GET:
		break;

	case DB_SQL:
		ERR("ldap: The driver does not support raw queries yet.\n");
		goto error;
	}

	cfg = ld_find_cfg(&cmd->table);
	if (cfg == NULL) {
		ERR("ldap: Cannot find configuration for '%.*s', giving up\n",
			STR_FMT(&cmd->table));
		goto error;
	}

	lcmd->base = cfg->base.s;
	lcmd->scope = cfg->scope;

	lcmd->sizelimit = cfg->sizelimit;
	if (cfg->timelimit) {
		lcmd->timelimit.tv_sec = cfg->timelimit;
		lcmd->timelimit.tv_usec = 0;
	}

	if (cfg->filter.s) {
		lcmd->filter = cfg->filter;
	}
	lcmd->chase_references = cfg->chase_references;
	lcmd->chase_referrals = cfg->chase_referrals;

	if (ld_resolve_fld(cmd->match, cfg) < 0) goto error;
	if (ld_resolve_fld(cmd->result, cfg) < 0) goto error;

	/* prepare filter for each result field */
	for(i = 0; !DB_FLD_EMPTY(cmd->result) && !DB_FLD_LAST(cmd->result[i]); i++) {
		int n;
		lfld = DB_GET_PAYLOAD(cmd->result + i);
		lfld->filter = NULL;
	
		for(j = 0, n = 0; !DB_FLD_EMPTY(cmd->match) && !DB_FLD_LAST(cmd->match[j]); j++) {
			if (strcmp(cmd->result[i].name, cmd->match[j].name) == 0)
				n++;	
		}
		
		if (n > 0) {
			lfld->filter = pkg_malloc((n+1)*sizeof(*(lfld->filter)));
			if (!lfld->filter) return -1 /* E_OUT_OF_MEM*/;
			for(j = 0, n = 0; !DB_FLD_EMPTY(cmd->match) && !DB_FLD_LAST(cmd->match[j]); j++) {
				if (strcmp(cmd->result[i].name, cmd->match[j].name) == 0) {
					lfld->filter[n] = cmd->match+j;
					n++;
				}
			}
			lfld->filter[n] = NULL;
		}
	}
	if (build_result_array(&lcmd->result, cmd) < 0) goto error;

	DB_SET_PAYLOAD(cmd, lcmd);
	return 0;

 error:
	if (lcmd) {
		DB_SET_PAYLOAD(cmd, NULL);
		db_drv_free(&lcmd->gen);
		if (lcmd->result) pkg_free(lcmd->result);
		pkg_free(lcmd);
	}
	return -1;
}
Ejemplo n.º 10
0
/* FIXME: Add support for DB_NONE, in this case the function should determine
 * the type of the column in the database and set the field type appropriately.
 * This function must be called after check_result.
 */
static int bind_result(MYSQL_STMT* st, db_fld_t* fld)
{
	int i, n, err = 0;
	struct my_fld* f;
	MYSQL_BIND* result;

	/* Calculate the number of fields in the result */
	for(n = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[n]); n++);
	/* Return immediately if there are no fields in the result set */
	if (n == 0) return 0;

	result = (MYSQL_BIND*)pkg_malloc(sizeof(MYSQL_BIND) * n);
	if (result == NULL) {
		ERR("mysql: No memory left\n");
		return 1;
	}
	memset(result, '\0', sizeof(MYSQL_BIND) * n);
	
	for(i = 0; i < n; i++) {
		f = DB_GET_PAYLOAD(fld + i);
		result[i].is_null = &f->is_null;
		/* We can do it for all the types here, mysql will ignore it
		 * for fixed-size types such as MYSQL_TYPE_LONG
		 */
		result[i].length = &f->length;
		switch(fld[i].type) {
		case DB_INT:
		case DB_BITMAP:
			result[i].buffer_type = MYSQL_TYPE_LONG;
			result[i].buffer = &fld[i].v.int4;
			break;

		case DB_FLOAT:
			result[i].buffer_type = MYSQL_TYPE_FLOAT;
			result[i].buffer = &fld[i].v.flt;
			break;
			
		case DB_DOUBLE:
			result[i].buffer_type = MYSQL_TYPE_DOUBLE;
			result[i].buffer = &fld[i].v.dbl;
			break;

		case DB_DATETIME:
			result[i].buffer_type = MYSQL_TYPE_DATETIME;
			result[i].buffer = &f->time;
			break;

		case DB_STR:
			result[i].buffer_type = MYSQL_TYPE_VAR_STRING;
			if (!f->buf.s) f->buf.s = pkg_malloc(STR_BUF_SIZE);
			if (f->buf.s == NULL) {
				ERR("mysql: No memory left\n");
				err = 1;
				goto error;
			}
			result[i].buffer = f->buf.s;
			fld[i].v.lstr.s = f->buf.s;
			result[i].buffer_length = STR_BUF_SIZE - 1;
			break;

		case DB_CSTR:
			result[i].buffer_type = MYSQL_TYPE_VAR_STRING;
			if (!f->buf.s) f->buf.s = pkg_malloc(STR_BUF_SIZE);
			if (f->buf.s == NULL) {
				ERR("mysql: No memory left\n");
				err = 1;
				goto error;
			}
			result[i].buffer = f->buf.s;
			fld[i].v.cstr = f->buf.s;
			result[i].buffer_length = STR_BUF_SIZE - 1;
			break;

		case DB_BLOB:
			result[i].buffer_type = MYSQL_TYPE_BLOB;
			if (!f->buf.s) f->buf.s = pkg_malloc(STR_BUF_SIZE);
			if (f->buf.s == NULL) {
				ERR("mysql: No memory left\n");
				err = 1;
				goto error;
			}
			result[i].buffer = f->buf.s;
			fld[i].v.blob.s = f->buf.s;
			result[i].buffer_length = STR_BUF_SIZE - 1;
			break;

		case DB_NONE:
			/* Eliminates gcc warning */
			break;

		}
	}

	err = mysql_stmt_bind_result(st, result);
	if (err) {
		ERR("mysql: Error while binding result: %s\n", mysql_stmt_error(st));
		goto error;
	}

	/* We do not need the array of MYSQL_BIND anymore, mysql_stmt_bind_param
	 * creates a copy in the statement and we will update it there
	 */
	if (result) pkg_free(result);
	return 0;
   
 error:
	if (result) pkg_free(result);
	return err;
}
Ejemplo n.º 11
0
/**
 *  Builds UPDATE statement where cmd->valss specify column name-value pairs
 *  and cmd->match specify WHERE clause.
 * @param sql_cmd  SQL statement as a result of this function
 * @param cmd      input for statement creation
 */
static int build_update_cmd(str* sql_cmd, db_cmd_t* cmd)
{
	struct string_buffer sql_buf = {.s = NULL, .len = 0, .size = 0, .increment = 128};
	db_fld_t* fld;
	int i;
	int rv = 0;
	str tmpstr;

	rv = sb_add(&sql_buf, &strings[STR_UPDATE]);	/* "UPDATE " */
	rv |= sb_add(&sql_buf, &cmd->table);			/* table name */
	rv |= sb_add(&sql_buf, &strings[STR_SET]);		/* " SET " */

	/* column name-value pairs */
	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
		rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));
		rv |= sb_add(&sql_buf, set_str(&tmpstr, " = "));
		rv |= sb_add(&sql_buf, &strings[STR_ESC]);
		if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, set_str(&tmpstr, ", "));
	}
	if (rv) {
		goto err;
	}

	if (!DB_FLD_EMPTY(cmd->match)) {
		rv |= sb_add(&sql_buf, &strings[STR_WHERE]);

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			rv |= sb_add(&sql_buf, set_str(&tmpstr, fld[i].name));

			switch(fld[i].op) {
			case DB_EQ:  rv |= sb_add(&sql_buf, &strings[STR_OP_EQ]);  break;
			case DB_NE:  rv |= sb_add(&sql_buf, &strings[STR_OP_NE]);  break;
			case DB_LT:  rv |= sb_add(&sql_buf, &strings[STR_OP_LT]);  break;
			case DB_GT:  rv |= sb_add(&sql_buf, &strings[STR_OP_GT]);  break;
			case DB_LEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_LEQ]); break;
			case DB_GEQ: rv |= sb_add(&sql_buf, &strings[STR_OP_GEQ]); break;
			}
			
			rv |= sb_add(&sql_buf, &strings[STR_ESC]);
			if (!DB_FLD_LAST(fld[i + 1])) rv |= sb_add(&sql_buf, &strings[STR_AND]);
		}
	}
	rv |= sb_add(&sql_buf, set_str(&tmpstr, "\0"));
	if (rv) {
		goto err;
	}
	sql_cmd->s = sql_buf.s;
	sql_cmd->len = sql_buf.len;
	return 0;

err:
	if (sql_buf.s) pkg_free(sql_buf.s);
	return -1;
}


static inline void update_field(MYSQL_BIND *param, db_fld_t* fld)
{
	struct my_fld* fp;      /* field payload */
	struct tm* t;
	
	fp = DB_GET_PAYLOAD(fld);

#ifndef MYSQL_FAKE_NULL
	fp->is_null = fld->flags & DB_NULL;
	if (fp->is_null) return;
#else
	if (fld->flags & DB_NULL) {
		switch(fld->type) {
		case DB_STR:
		case DB_CSTR:
			param->buffer = FAKE_NULL_STR.s;
			fp->length = FAKE_NULL_STR.len;
			break;
		case DB_INT:
			*(int*)param->buffer = FAKE_NULL_INT;
			break;
		case DB_BLOB:
		case DB_DATETIME:
		case DB_NONE:
		case DB_FLOAT:
		case DB_DOUBLE:
		case DB_BITMAP:
			/* we don't have fake null value for these types */
			fp->is_null = DB_NULL;
			break;
		}
		return;
	}
#endif
	switch(fld->type) {
	case DB_STR:
		param->buffer = fld->v.lstr.s;
		fp->length = fld->v.lstr.len;
		break;

	case DB_BLOB:
		param->buffer = fld->v.blob.s;
		fp->length = fld->v.blob.len;
		break;

	case DB_CSTR:
		param->buffer = (char*)fld->v.cstr;
		fp->length = strlen(fld->v.cstr);
		break;

	case DB_DATETIME:
		t = gmtime(&fld->v.time);
		fp->time.second = t->tm_sec;
		fp->time.minute = t->tm_min;
		fp->time.hour = t->tm_hour;
		fp->time.day = t->tm_mday;
		fp->time.month = t->tm_mon + 1;
		fp->time.year = t->tm_year + 1900;
		break;
		
	case DB_NONE:
	case DB_INT:
	case DB_FLOAT:
	case DB_DOUBLE:
	case DB_BITMAP:
		/* No need to do anything for these types */
		break;

	}
}


/**
 * Update values of MySQL bound parameters with values from
 * the DB API.
 * @param cmd Command structure which contains pointers to MYSQL_STMT and parameters values
 * @see bind_mysql_params
 */
static inline void set_mysql_params(db_cmd_t* cmd)
{
	struct my_cmd* mcmd;
	int i;

	mcmd = DB_GET_PAYLOAD(cmd);

	/* FIXME: We are updating internals of the prepared statement here,
	 * this is probably not nice but I could not find another way of
	 * updating the pointer to the buffer without the need to run
	 * mysql_stmt_bind_param again (which would be innefficient)
	 */
	for(i = 0; i < cmd->vals_count; i++) {
		update_field(mcmd->st->params + i, cmd->vals + i);
	}

	for(i = 0; i < cmd->match_count; i++) {
		update_field(mcmd->st->params + cmd->vals_count + i, cmd->match + i);
	}
}


static inline int update_result(db_fld_t* result, MYSQL_STMT* st)
{
	int i;
	struct my_fld* rp; /* Payload of the current field in result */
	struct tm t;

	/* Iterate through all the fields returned by MySQL and convert
	 * them to DB API representation if necessary
	 */

	for(i = 0; i < st->field_count; i++) {
		rp = DB_GET_PAYLOAD(result + i);

		if (rp->is_null) {
			result[i].flags |= DB_NULL;
			continue;
		} else {
			result[i].flags &= ~DB_NULL;
		}

		switch(result[i].type) {
		case DB_STR:
			result[i].v.lstr.len = rp->length;
#ifdef MYSQL_FAKE_NULL
			if (STR_EQ(FAKE_NULL_STR,result[i].v.lstr)) {
				result[i].flags |= DB_NULL;
			}
#endif
			break;

		case DB_BLOB:
			result[i].v.blob.len = rp->length;
			break;

		case DB_CSTR:
			if (rp->length < STR_BUF_SIZE) {
				result[i].v.cstr[rp->length] = '\0';
			} else {
				/* Truncated field but rp->length contains full size,
				 * zero terminated the last byte in the buffer
				 */
				result[i].v.cstr[STR_BUF_SIZE - 1] = '\0';
			}
#ifdef MYSQL_FAKE_NULL
			if (strcmp(FAKE_NULL_STR.s,result[i].v.cstr)==0) {
				result[i].flags |= DB_NULL;
			}
#endif
			break;
			
		case DB_DATETIME:
			memset(&t, '\0', sizeof(struct tm));
			t.tm_sec = rp->time.second;
			t.tm_min = rp->time.minute;
			t.tm_hour = rp->time.hour;
			t.tm_mday = rp->time.day;
			t.tm_mon = rp->time.month - 1;
			t.tm_year = rp->time.year - 1900;

			/* Daylight saving information got lost in the database
			 * so let timegm to guess it. This eliminates the bug when
			 * contacts reloaded from the database have different time
			 * of expiration by one hour when daylight saving is used
			 */ 
			t.tm_isdst = -1;
#ifdef HAVE_TIMEGM
			result[i].v.time = timegm(&t);
#else
			result[i].v.time = _timegm(&t);
#endif /* HAVE_TIMEGM */
			break;

		case DB_INT:
#ifdef MYSQL_FAKE_NULL
			if (FAKE_NULL_INT==result[i].v.int4) {
				result[i].flags |= DB_NULL;
			}
			break;
#endif
		case DB_NONE:
		case DB_FLOAT:
		case DB_DOUBLE:
		case DB_BITMAP:
			/* No need to do anything for these types */
			break;
		}
	}
	
	return 0;
}
Ejemplo n.º 12
0
int flat_put(db_res_t* res, db_cmd_t* cmd)
{
	struct flat_cmd* fcmd;
	struct flat_con* fcon;
	db_con_t* con;
	int i;
	FILE* f;
	char delims[4], *s;
	size_t len;

	fcmd = DB_GET_PAYLOAD(cmd);
	/* FIXME */
	con = cmd->ctx->con[db_payload_idx];
	fcon = DB_GET_PAYLOAD(con);

	f = fcon->file[fcmd->file_index].f;
	if (f == NULL) {
		ERR("flatstore: Cannot write, file handle not open\n");
		return -1;
	}

	if (flat_local_timestamp < *flat_rotate) {
		flat_con_disconnect(con);
		if (flat_con_connect(con) < 0) {
			ERR("flatstore: Error while rotating files\n");
			return -1;
		}
		flat_local_timestamp = *flat_rotate;
	}

	for(i = 0; !DB_FLD_EMPTY(cmd->vals) && !DB_FLD_LAST(cmd->vals[i]); i++) {
		if (i) {
			if (fprintf(f, "%c", flat_delimiter.s[0]) < 0) goto error;
		}

		/* TODO: how to distinguish NULL from empty */
		if (cmd->vals[i].flags & DB_NULL) continue;
		
		switch(cmd->vals[i].type) {
		case DB_INT:
			if (fprintf(f, "%d", cmd->vals[i].v.int4) < 0) goto error;
			break;

		case DB_FLOAT:
			if (fprintf(f, "%f", cmd->vals[i].v.flt) < 0) goto error;
			break;

		case DB_DOUBLE:
			if (fprintf(f, "%f", cmd->vals[i].v.dbl) < 0) goto error;
			break;

		case DB_DATETIME:
			if (fprintf(f, "%u", (unsigned int)cmd->vals[i].v.time) < 0) 
				goto error;
			break;

		case DB_CSTR:
			s = cmd->vals[i].v.cstr;
			delims[0] = flat_delimiter.s[0];
			delims[1] = flat_record_delimiter.s[0];
			delims[2] = flat_escape.s[0];
			delims[3] = '\0';
			while (*s) {
				len = strcspn(s, delims);
				if (fprintf(f, "%.*s", (int)len, s) < 0) goto error;
				s += len;
				if (*s) {
					/* FIXME: do not use the escaped value for easier parsing */
					if (fprintf(f, "%c%c", flat_escape.s[0], *s) < 0) goto error;
					s++;
				}
			}
			break;

		case DB_STR:
		case DB_BLOB:
			/* FIXME: rewrite */
			s = cmd->vals[i].v.lstr.s;
			len = cmd->vals[i].v.lstr.len;
			while (len > 0) {
				char *c;
				for (c = s; len > 0 && 
						 *c != flat_delimiter.s[0] && 
						 *c != flat_record_delimiter.s[0] && 
						 *c != flat_escape.s[0]; 
					 c++, len--);
				if (fprintf(f, "%.*s", (int)(c-s), s) < 0) goto error;
				s = c;
				if (len > 0) {
					if (fprintf(f, "%c%c", flat_escape.s[0], *s) < 0) goto error;
					s++;
					len--;
				}
			}
			break;

		case DB_BITMAP:
			if (fprintf(f, "%u", cmd->vals[i].v.bitmap) < 0) goto error;
			break;

		default:
			BUG("flatstore: Unsupported field type %d\n", cmd->vals[i].type);
			return -1;
		}
	}

	if (fprintf(f, "%c", flat_record_delimiter.s[0]) < 0) goto error;

	if (flat_flush && (fflush(f) != 0)) {
		ERR("flatstore: Error while flushing file: %s\n", strerror(errno));
		return -1;
	}

	return 0;

 error:
	ERR("flastore: Error while writing data to file\n");
	return -1;
}
Ejemplo n.º 13
0
int my_cmd(db_cmd_t* cmd)
{
	struct my_cmd* res;
 
	res = (struct my_cmd*)pkg_malloc(sizeof(struct my_cmd));
	if (res == NULL) {
		ERR("mysql: No memory left\n");
		goto error;
	}
	memset(res, '\0', sizeof(struct my_cmd));
	/* Fetch all data to client at once by default */
	res->flags |= MY_FETCH_ALL;
	if (db_drv_init(&res->gen, my_cmd_free) < 0) goto error;

	switch(cmd->type) {
	case DB_PUT:
		if (DB_FLD_EMPTY(cmd->vals)) {
			BUG("mysql: No parameters provided for DB_PUT in context '%.*s'\n", 
				cmd->ctx->id.len, ZSW(cmd->ctx->id.s));
			goto error;
		}
		if (build_replace_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_DEL:
		if (build_delete_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_GET:
		if (build_select_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_UPD:
		if (build_update_cmd(&res->sql_cmd, cmd) < 0) goto error;
		break;

	case DB_SQL:
		res->sql_cmd.s = (char*)pkg_malloc(cmd->table.len);
		if (res->sql_cmd.s == NULL) {
			ERR("mysql: Out of private memory\n");
			goto error;
		}
		memcpy(res->sql_cmd.s,cmd->table.s, cmd->table.len);
		res->sql_cmd.len = cmd->table.len;
        break;
	}

	DB_SET_PAYLOAD(cmd, res);

	/* In order to check all the parameters and results, we need to upload
	 * the command to the server. We need to do that here before we report
	 * back that the command was created successfully. Hence, this
	 * function requires the corresponding connection be established. We
	 * would not be able to check parameters if we don't do that there and
	 * that could result in repeated execution failures at runtime.
	 */
	if (upload_cmd(cmd)) goto error;
	return 0;

 error:
	if (res) {
		DB_SET_PAYLOAD(cmd, NULL);
		db_drv_free(&res->gen);
		if (res->sql_cmd.s) pkg_free(res->sql_cmd.s);
		pkg_free(res);
	}
	return -1;
}
Ejemplo n.º 14
0
int ld_ldap2fldex(db_fld_t* fld, LDAP* ldap, LDAPMessage* msg, int init)
{
	int i;
	struct ld_fld* lfld;
	str v;

	if (fld == NULL || msg == NULL) return 0;
	for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {
		lfld = DB_GET_PAYLOAD(fld + i);
		if (init) {
			if (fld[i].type == DB_NONE) {
				switch (lfld->syntax) {
					case LD_SYNTAX_STRING:
						fld[i].type = DB_STR;
						break;
					case LD_SYNTAX_INT:
					case LD_SYNTAX_BOOL:
					case LD_SYNTAX_BIT:
						fld[i].type = DB_INT;
						break;
					case LD_SYNTAX_FLOAT:
						fld[i].type = DB_FLOAT;
						break;
						
					case LD_SYNTAX_GENTIME:
						fld[i].type = DB_DATETIME;
						break;
					case LD_SYNTAX_BIN:
						fld[i].type = DB_BITMAP;
						break;
				}

			}
			
			/* free the values of the previous object */
			if (lfld->values) ldap_value_free_len(lfld->values);
			lfld->values = ldap_get_values_len(ldap, msg, lfld->attr.s);
			lfld->index = 0;
			
			if (lfld->values == NULL || lfld->values[0] == NULL) {
				fld[i].flags |= DB_NULL;
				/* index == 0 means no value available */
				lfld->valuesnum = 0;
				if (lfld->client_side_filtering && lfld->filter) {
					int j;
					/* if the all filter conditions requires NULL value then we can accept the record */
					for (j=0; lfld->filter[j]; j++) {
						if (lfld->filter[j]->flags & DB_NULL && lfld->filter[j]->op == DB_EQ) {
							continue;
						}
						return 1; /* get next record */
					}
				}
			} else {
				/* init the number of values */
				fld[i].flags &= ~DB_NULL;
				lfld->valuesnum = ldap_count_values_len(lfld->values);
			
				if ((lfld->valuesnum > 1 || lfld->client_side_filtering) && lfld->filter) {
					
					/* in case of multivalue we must check if value fits in filter criteria.
					   LDAP returns record (having each multivalue) if one particular
					   multivalue fits in filter provided to LDAP search. We need
					   filter out these values manually. It not perfect because 
					   LDAP filtering may be based on different rule/locale than
					   raw (ASCII,...) comparision. 
					
					   We reorder values so we'll have interesting values located from top up to valuesnum at the end.

					   The same algorithm is applied for client side filtering
					   
					 */
					 
					do {
						int passed, j;
						for (j=0, passed = 1; lfld->filter[j] && passed; j++) {
							int op;  /* b0..less, b1..equal, b2..greater, zero..non equal */ 
							op = 0x00;
							if (lfld->filter[j]->flags & DB_NULL) {
								/* always non equal because field is not NULL */
							}
							else {
								
								v.s = lfld->values[lfld->index]->bv_val;
								v.len = lfld->values[lfld->index]->bv_len;
							
								if (ldap_fld2db_fld(fld + i, v) < 0) {
									passed = 0;
									break; /* for loop */
								}
								else {
									db_fld_val_t v;
									int t;
									static char buf[30];
									t = lfld->filter[j]->type;
									/* we need compare value provided in match condition with value returned by LDAP.
									   The match value should be the same type as LDAP value obtained during
									   db_cmd(). We implement some basic conversions.
									 */
									v = lfld->filter[j]->v;
									if (t == DB_CSTR) {
										v.lstr.s = v.cstr;
										v.lstr.len = strlen(v.lstr.s);
										t = DB_STR;
									} 
									switch (fld[i].type) {
										case DB_CSTR:
											fld[i].v.lstr.s = fld[i].v.cstr;
											fld[i].v.lstr.len = strlen(fld[i].v.lstr.s);
											fld[i].type = DB_STR; 
											/* no break */
										case DB_STR:
											
											switch (t) {
												case DB_INT:
													v.lstr.len = snprintf(buf, sizeof(buf)-1, "%d", v.int4);
													v.lstr.s = buf;
													break;
												/* numeric conversion for double/float not supported because of non unique string representation */
												default:
													goto skip_conv;
											}
											break;
										case DB_INT:
											switch (t) {
												case DB_DOUBLE:
													if ((double)(int)v.dbl != (double)v.dbl) 
														goto skip_conv;
													v.int4 = v.dbl;
													break;
												case DB_FLOAT:
													if ((float)(int)v.flt != (float)v.flt) 
														goto skip_conv;
													v.int4 = v.flt;
													break;
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														int n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtol(v.lstr.s, &p, 10);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.int4 = n;
													}
													break;
												default:
													goto skip_conv;
											}
											break;
										case DB_FLOAT:
											switch (t) {
												case DB_DOUBLE:
													v.flt = v.dbl;
													break;
												case DB_INT:
													v.flt = v.int4;
													break;
												#ifdef  __USE_ISOC99
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														float n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtof(v.lstr.s, &p);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.flt = n;
													}
													break;
												#endif
												default:
													goto skip_conv;
											}
											break;
										case DB_DOUBLE:
											switch (t) {
												case DB_FLOAT:
													v.dbl = v.flt;
													break;
												case DB_INT:
													v.dbl = v.int4;
													break;
												case DB_STR: 
													if (v.lstr.len > 0) {
														char c, *p;
														double n;
														c = v.lstr.s[v.lstr.len];
														v.lstr.s[v.lstr.len] = '\0';
														n = strtod(v.lstr.s, &p);
														v.lstr.s[v.lstr.len] = c;
														if ((*p) != '\0') {
															goto skip_conv;
														}
														v.dbl = n;
													}
													break;
												default:
													goto skip_conv;
											}
											break;
										case DB_BLOB:
										case DB_BITMAP:
										case DB_DATETIME:
										default:
											goto skip_conv;
										}
									t = fld[i].type;
								skip_conv:
									if (t == fld[i].type) {
									
										switch (fld[i].type) {
											case DB_CSTR: /* impossible, already converted to DB_STR */
											case DB_STR:
												if (fld[i].v.lstr.len == v.lstr.len) {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, v.lstr.len);
													if (op < 0) 
														op = 0x01;
													else if (op > 0)
														op = 0x04;
													else
														op = 0x02;
												}
												else if (fld[i].v.lstr.len < v.lstr.len) {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, fld[i].v.lstr.len);
													if (op < 0) 
														op = 0x01;
													else 
														op = 0x04;
												}
												else /* if (fld[i].v.lstr.len > v.lstr.len) */ {
													op = strncmp(fld[i].v.lstr.s, v.lstr.s, v.lstr.len);
													if (op > 0) 
														op = 0x04;
													else 
														op = 0x01;
												}
												break;
											case DB_BLOB:
												if (fld[i].v.blob.len == v.blob.len && memcmp(fld[i].v.blob.s, v.blob.s, v.blob.len) == 0)
													op = 0x02;
												break;											
											case DB_INT:
												CMP_NUM(fld[i].v, v, int4);
												break; 
											case DB_BITMAP:
												CMP_NUM(fld[i].v, v, bitmap);
												break; 
											case DB_DATETIME:
												CMP_NUM(fld[i].v, v, time);
												break; 
											case DB_FLOAT:
												CMP_NUM(fld[i].v, v, flt);
												break; 
											case DB_DOUBLE:
												CMP_NUM(fld[i].v, v, dbl);
												break; 
											default:
												;
										}
									}
									 
								}
							}
							switch (lfld->filter[j]->op) {
								case DB_EQ:
									passed = op == 0x02;
									break;
								case DB_NE:
									passed = (op & 0x02) == 0;
									break;
								case DB_LT:
									passed = op == 0x01;
									break;
								case DB_LEQ:
									passed = op == 0x01 || op == 0x02;
									break;
								case DB_GT:
									passed = op == 0x04;
									break;
								case DB_GEQ:
									passed = op == 0x04 || op == 0x02;
									break;
								default:
									;
							}
						}
						
						if (passed) {
							lfld->index++;	
						}
						else {
							char *save_bvval;
							int save_bvlen;
							int i;
							/* shift following values, push useless value at the end and decrease num of values */
							
							save_bvval = lfld->values[lfld->index]->bv_val;
							save_bvlen = lfld->values[lfld->index]->bv_len;
							for (i=lfld->index+1; i < lfld->valuesnum; i++) {
								 lfld->values[i-1]->bv_val = lfld->values[i]->bv_val;
								 lfld->values[i-1]->bv_len = lfld->values[i]->bv_len;
							}
							lfld->values[lfld->valuesnum-1]->bv_val = save_bvval;
							lfld->values[lfld->valuesnum-1]->bv_len = save_bvlen;
							lfld->valuesnum--;
						}
				
					} while (lfld->index < lfld->valuesnum);
						
					if (lfld->valuesnum == 0) {
						return 1;  /* get next record */
					}
				}
			}	
			/* pointer to the current value */
			lfld->index = 0;
		}

		/* this is an empty value */
		if (!lfld->valuesnum)
			continue;

		v.s = lfld->values[lfld->index]->bv_val;
		v.len = lfld->values[lfld->index]->bv_len;

		if (ldap_fld2db_fld(fld + i, v) < 0) 
			return -1;
		
	}
	return 0;
}
Ejemplo n.º 15
0
int ld_prepare_ldap_filter(char** filter, db_cmd_t* cmd, str* add)
{
	db_fld_t* fld;
	struct ld_fld* lfld;
	int rv = 0;
	struct sbuf buf = {
		.s = NULL, .len = 0,
		.size = 0, .increment = 128
	};

	fld = cmd->match;
	skip_client_side_filtering_fields(cmd, &fld);
	
	/* Return NULL if there are no fields and no preconfigured search
	 * string supplied in the configuration file
	 */
	if ((DB_FLD_EMPTY(fld) || DB_FLD_LAST(*fld)) && ((add->s == NULL) || !add->len)) {
		*filter = NULL;
		return 0;
	}

	rv = sb_add(&buf, "(&", 2);
	if (add->s && add->len) {
		/* Add the filter component specified in the config file */
		rv |= sb_add(&buf, add->s, add->len);
	}

	for(; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(*fld); fld++, skip_client_side_filtering_fields(cmd, &fld)) {
		int op;
		lfld = DB_GET_PAYLOAD(fld);

		op = fld->op;
		
		if (fld->flags & DB_NULL) {
			switch (op) {
				case DB_EQ:
					/* fld==NULL -> (!(x=*)) */
					op = DB_NE;

				case DB_NE:
					/* fld!=NULL -> (x=*) */
					op = DB_EQ;
					break;
				default:
					ERR("ldap: Cannot compare null value field %s\n", fld->name);				
					goto error;
			}	
		}
		
		/* we need construct operators as:
		    not:  (!(fld=val))
		    </>:  (!(fld=val))(fld</>val)
		*/
		switch (op) {
			case DB_LT:
			case DB_GT:
			case DB_NE:
				rv |= sb_add(&buf, "(!(", 3);
				rv |= sb_add(&buf, lfld->attr.s, lfld->attr.len);
				rv |= sb_add(&buf, "=", 1);
				if (fld->flags & DB_NULL) {
					rv |= sb_add(&buf, "*", 1);
				}
				else {
					if (ld_db2ldap(&buf, fld) < 0) {
						goto error;
					}
				}
				rv |= sb_add(&buf, "))", 2);
				break;
			default:
			    ;
		}
		if (op != DB_NE) {
			rv |= sb_add(&buf, "(", 1);
			rv |= sb_add(&buf, lfld->attr.s, lfld->attr.len);
			switch (op) {
				case DB_LEQ:
				case DB_LT:
					rv |= sb_add(&buf, "<=", 2);
					break;
				case DB_GEQ:
				case DB_GT:
					rv |= sb_add(&buf, ">=", 2);
					break;
				case DB_EQ:
					rv |= sb_add(&buf, "=", 1);
					break;
				default:
				;
			}
			if (fld->flags & DB_NULL) {
				rv |= sb_add(&buf, "*", 1);
			}
			else {
				if (ld_db2ldap(&buf, fld) < 0) {
					goto error;
				}
			}
			rv |= sb_add(&buf, ")", 1);
		}		
	}

	rv |= sb_add(&buf, ")", 1);
	rv |= sb_add(&buf, "", 1);
	if (rv) goto error;

	*filter = buf.s;
	return 0;

error:
	if (buf.s) pkg_free(buf.s);
	return -1;
}
Ejemplo n.º 16
0
/**
 * Execute a query
 * @param cmd DB command structure
 * @param bcmd Berkely DB command structure
 * @return 0 on success, -1 on error
 */
int bdb_query(db_cmd_t *cmd, bdb_cmd_t *bcmd)
{
	DBT key;
	DB *db;
	static char kbuf[MAX_ROW_SIZE];
	int klen;

	bdb_tcache_t *tbc = NULL;
	bdb_table_t *tp = NULL;

	if(bcmd->bcon == NULL || bcmd->bcon->dbp == NULL)
		return -1;

	tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
	if(tbc == NULL) {
		ERR("bdb: table does not exist!\n");
		return -1;
	}

	tp = tbc->dtp;
	if(tp == NULL) {
		ERR("bdb: table not loaded!\n");
		return -1;
	}
	db = tp->db;
	if(db == NULL) {
		ERR("bdb: db structure not initialized!\n");
		return -1;
	}

	if(DB_FLD_EMPTY(cmd->match)) { /* no match constraint */
		if(db->cursor(db, NULL, &bcmd->dbcp, 0) != 0) {
			ERR("bdb: error creating cursor\n");
			goto error;
		}
		bcmd->skey.len = 0;
		return 0;
	}

	memset(&key, 0, sizeof(DBT));
	memset(kbuf, 0, MAX_ROW_SIZE);

	klen = MAX_ROW_SIZE;
	if(bdblib_valtochar(tp, cmd->match, cmd->match_count, kbuf, &klen, BDB_KEY)
			!= 0) {
		ERR("bdb: error creating key\n");
		goto error;
	}

	if(klen > bcmd->skey_size || bcmd->skey.s == NULL) {
		if(bcmd->skey.s != NULL)
			pkg_free(bcmd->skey.s);
		bcmd->skey.s = (char *)pkg_malloc(klen * sizeof(char));
		if(bcmd->skey.s == NULL) {
			ERR("bdb: no pkg memory\n");
			goto error;
		}
		bcmd->skey_size = klen;
	}
	memcpy(bcmd->skey.s, kbuf, klen);
	bcmd->skey.len = klen;

	return 0;
error:
	return -1;
}
Ejemplo n.º 17
0
/** Prepare a query
 * @param cmd DB command structure
 * @param bcmd berkey DB command structure
 * @return 0 on success, -1 on error
 */
int bdb_prepare_query(db_cmd_t *cmd, bdb_cmd_t *bcmd)
{
	bdb_tcache_t *tbc = NULL;
	bdb_table_t *tp = NULL;
	bdb_fld_t *f;
	db_fld_t *fld;
	int mode;
	int i;

	if(bcmd->bcon == NULL || bcmd->bcon->dbp == NULL)
		return -1;

	tbc = bdblib_get_table(bcmd->bcon->dbp, &cmd->table);
	if(tbc == NULL) {
		ERR("bdb: table does not exist!\n");
		return -1;
	}

	tp = tbc->dtp;
	if(tp == NULL || tp->db == NULL) {
		ERR("bdb: table not loaded!\n");
		return -1;
	}

	mode = 0;
	if(!DB_FLD_EMPTY(cmd->result)) { /* columns to be returned provided */
		if(cmd->result_count > tp->ncols) {
			ERR("bdb: too many columns in query\n");
			goto error;
		}
	} else {
		mode = 1;
		cmd->result = db_fld(tp->ncols + 1);
		cmd->result_count = tp->ncols;
		for(i = 0; i < cmd->result_count; i++) {
			if(bdb_fld(cmd->result + i, cmd->table.s) < 0)
				goto error;
		}
	}

	for(i = 0; i < cmd->result_count; i++) {
		fld = cmd->result + i;
		f = DB_GET_PAYLOAD(fld);
		if(mode == 1) {
			DBG("bdb: column name [%.*s]\n", tp->colp[i]->name.len,
					tp->colp[i]->name.s);

			f->name = pkg_malloc(tp->colp[i]->name.len + 1);
			if(f->name == NULL) {
				ERR("bdb: Out of private memory\n");
				goto error;
			}
			strncpy(f->name, tp->colp[i]->name.s, tp->colp[i]->name.len);
			f->name[tp->colp[i]->name.len] = '\0';
			fld->name = f->name;
			fld->type = tp->colp[i]->type;
			f->col_pos = i;
		} else {
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Column not found\n");
				goto error;
			}
		}
		switch(fld->type) {
			case DB_INT:
			case DB_BITMAP:
			case DB_FLOAT:
			case DB_DOUBLE:
			case DB_DATETIME:
			case DB_STR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.lstr.s = f->buf.s;
				break;

			case DB_CSTR:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("bdb: No memory left\n");
					goto error;
				}
				fld[i].v.cstr = f->buf.s;
				break;

			case DB_BLOB:
				if(!f->buf.s)
					f->buf.s = pkg_malloc(BDB_BUF_SIZE);
				if(f->buf.s == NULL) {
					ERR("mysql: No memory left\n");
					goto error;
				}
				fld[i].v.blob.s = f->buf.s;
				break;

			case DB_NONE:
				/* Eliminates gcc warning */
				break;
		}
	}

	if(!DB_FLD_EMPTY(cmd->match)) {
		if(cmd->match_count > tp->ncols) {
			ERR("bdb: too many columns in match struct of query\n");
			goto error;
		}
		for(i = 0; i < cmd->match_count; i++) {
			fld = cmd->result + i;
			f = DB_GET_PAYLOAD(fld);
			f->col_pos = bdb_get_colpos(tp, fld->name);
			if(f->col_pos == -1) {
				ERR("bdb: Match column not found\n");
				goto error;
			}
		}
	}

	return 0;

error:
	return -1;
}
Ejemplo n.º 18
0
/**
 *  Builds SELECT statement where cmd->values specify column names
 *  and cmd->match specify WHERE clause.
 * @param sql_cmd SQL statement as a result of this function
 * @param cmd     input for statement creation
 */
static int build_select_cmd(str* sql_cmd, db_cmd_t* cmd)
{
	db_fld_t* fld;
	int i;
	char* p;

	sql_cmd->len = strings[STR_SELECT].len;

	if (DB_FLD_EMPTY(cmd->result)) {
		sql_cmd->len += 1; /* "*" */
	} else {
		for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
			sql_cmd->len += strlen(fld[i].name);
			if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += 1; /* , */
		}
	}
	sql_cmd->len += strings[STR_FROM].len;
	sql_cmd->len += cmd->table.len;

	if (!DB_FLD_EMPTY(cmd->match)) {
		sql_cmd->len += strings[STR_WHERE].len;

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			sql_cmd->len += strlen(fld[i].name);

			switch(fld[i].op) {
			case DB_EQ:  sql_cmd->len += strings[STR_OP_EQ].len; break;
			case DB_NE:  sql_cmd->len += strings[STR_OP_NE].len; break;
			case DB_LT:  sql_cmd->len += strings[STR_OP_LT].len; break;
			case DB_GT:  sql_cmd->len += strings[STR_OP_GT].len; break;
			case DB_LEQ: sql_cmd->len += strings[STR_OP_LEQ].len; break;
			case DB_GEQ: sql_cmd->len += strings[STR_OP_GEQ].len; break;
			default:
				ERR("mysql: Unsupported db_fld operator %d\n", fld[i].op);
				return -1;
			}

			sql_cmd->len += strings[STR_ESC].len;
			
			if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += strings[STR_AND].len;
		}
	}

	sql_cmd->s = pkg_malloc(sql_cmd->len + 1);
	if (sql_cmd->s == NULL) {
		ERR("mysql: No memory left\n");
		return -1;
	}
	p = sql_cmd->s;
	
	APPEND_STR(p, strings[STR_SELECT]);
	if (DB_FLD_EMPTY(cmd->result)) {
		*p++ = '*';
	} else {
		for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
			APPEND_CSTR(p, fld[i].name);
			if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
		}
	}
	APPEND_STR(p, strings[STR_FROM]);
	APPEND_STR(p, cmd->table);

	if (!DB_FLD_EMPTY(cmd->match)) {
		APPEND_STR(p, strings[STR_WHERE]);

		for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
			APPEND_CSTR(p, fld[i].name);

			switch(fld[i].op) {
			case DB_EQ:  APPEND_STR(p, strings[STR_OP_EQ]);  break;
			case DB_NE:  APPEND_STR(p, strings[STR_OP_NE]);  break;
			case DB_LT:  APPEND_STR(p, strings[STR_OP_LT]);  break;
			case DB_GT:  APPEND_STR(p, strings[STR_OP_GT]);  break;
			case DB_LEQ: APPEND_STR(p, strings[STR_OP_LEQ]); break;
			case DB_GEQ: APPEND_STR(p, strings[STR_OP_GEQ]); break;
			}
			
			APPEND_STR(p, strings[STR_ESC]);
			if (!DB_FLD_LAST(fld[i + 1])) APPEND_STR(p, strings[STR_AND]);
		}
	}

	*p = '\0';
	return 0;
}