Esempio 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;
}
Esempio n. 2
0
void db_fld_close(db_fld_t* fld)
{
	int i;

	for(i = 0; !DB_FLD_LAST(fld[i]); i++) {
		db_gen_free(&fld[i].gen);
	}
}
Esempio n. 3
0
int db_fld_init(db_fld_t* fld)
{
	int i;

	for(i = 0; !DB_FLD_LAST(fld[i]); i++) {
		if (db_gen_init(&fld[i].gen) < 0) return -1;
	}
	return 0;
}
Esempio n. 4
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;
				}
			}
		}
	}
}
Esempio n. 5
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);
}
Esempio n. 6
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;
}
Esempio n. 7
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;
}
Esempio n. 8
0
/**
 *  Builds REPLACE statement where cmd->values specify column names.
 * @param sql_cmd SQL statement as a result of this function
 * @param cmd     input for statement creation
 */
static int build_replace_cmd(str* sql_cmd, db_cmd_t* cmd)
{
	db_fld_t* fld;
	int i;
	char* p;

	sql_cmd->len = strings[STR_REPLACE].len;
	sql_cmd->len += cmd->table.len;
	sql_cmd->len += 2; /* " (" */

	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
		sql_cmd->len += strlen(fld[i].name);
		sql_cmd->len += strings[STR_ESC].len;
		if (!DB_FLD_LAST(fld[i + 1])) sql_cmd->len += 2; /* , twice */
	}
	sql_cmd->len += strings[STR_VALUES].len;
    sql_cmd->len += 1; /* ) */

	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_REPLACE]);
	APPEND_STR(p, cmd->table);
	*p++ = ' ';
	*p++ = '(';

	for(i = 0, fld = cmd->vals; !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_VALUES]);

	for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {
		APPEND_STR(p, strings[STR_ESC]);
		if (!DB_FLD_LAST(fld[i + 1])) *p++ = ',';
	}
	*p++ = ')';
	*p = '\0';
	return 0;
}
Esempio n. 9
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);
		}
	}
Esempio n. 10
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;
}
Esempio n. 11
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;
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio 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;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
}
int erlang_srdb2_cmd_exec(db_res_t* res, db_cmd_t* cmd) {
	LM_DBG("erlang_srdb2_cmd_exec %p %p\n",res ,cmd);
	db_fld_t* fld;
	ei_x_buff argbuf;
	int i,cnt;
	char *pbuf=NULL;
	static str con=STR_STATIC_INIT("con1");
	static str regname=STR_STATIC_INIT("echo_server");

	LM_DBG("erlang_srdb2_cmd %p\n",cmd);
//	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, ","));
//	}
	ei_x_new(&argbuf);
	//encode tuple {db_op, table, [cols], [params]}
	ei_x_encode_tuple_header(&argbuf, 5);
	switch(cmd->type) {
	    case DB_PUT: ei_x_encode_atom(&argbuf,"insert"); break;
	    case DB_DEL: ei_x_encode_atom(&argbuf,"delete"); break;
	    case DB_GET: ei_x_encode_atom(&argbuf,"select"); break;
	    case DB_UPD: ei_x_encode_atom(&argbuf,"update"); break;
	    case DB_SQL: ei_x_encode_atom(&argbuf,"rawquery"); break;
	}
	ei_x_encode_atom_len(&argbuf,cmd->table.s,cmd->table.len);
	
	for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {}
	ei_x_encode_list_header(&argbuf, i);
	for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
		ei_x_encode_atom(&argbuf,fld[i].name);
	}
	ei_x_encode_empty_list(&argbuf);
	
	if(cmd->match) {
	    for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {}
	    ei_x_encode_list_header(&argbuf, i);
	    for(i = 0, fld = cmd->match; !DB_FLD_LAST(fld[i]); i++) {
		ei_x_encode_tuple_header(&argbuf, 3);
		ei_x_encode_atom(&argbuf,fld[i].name);
		switch(fld[i].op) {
		    case DB_EQ:  ei_x_encode_atom(&argbuf,"="); break;
		    case DB_NE:  ei_x_encode_atom(&argbuf,"!="); break;
		    case DB_LT:  ei_x_encode_atom(&argbuf,"<"); break;
		    case DB_GT:  ei_x_encode_atom(&argbuf,">"); break;
		    case DB_LEQ: ei_x_encode_atom(&argbuf,"<="); break;
		    case DB_GEQ: ei_x_encode_atom(&argbuf,">="); break;
		}
		ei_x_encode_atom_len(&argbuf,fld[i].v.lstr.s,fld[i].v.lstr.len);
	    }
	    ei_x_encode_empty_list(&argbuf);
	} else {
	    ei_x_encode_list_header(&argbuf, 0);
	}
	if(cmd->vals) {
	    for(i = 0, fld = cmd->vals; !DB_FLD_LAST(fld[i]); i++) {}
	    ei_x_encode_list_header(&argbuf, i);
	    for(i = 0, fld = cmd->result; !DB_FLD_LAST(fld[i]); i++) {
		ei_x_encode_atom(&argbuf,fld[i].name);
	    }
	    ei_x_encode_empty_list(&argbuf);
	} else {
	    ei_x_encode_list_header(&argbuf, 0);
	}
	
	i=0;
	ei_s_print_term(&pbuf, argbuf.buff, &i);
	LM_DBG("message is pbuf='%s' buf.buffsz=%d buf.index=%d i=%d\n", pbuf, argbuf.buffsz,argbuf.index,i );
	free(pbuf);pbuf=NULL;
	erl_bind.do_erlang_call(&con,&regname, &argbuf, NULL);
	ei_x_free(&argbuf);
	return 0;
};
Esempio n. 18
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;
}