memset(column_value_coded,0,FIELDBUFSIZE);
memset(column_value_js_encoded,0,FIELDBUFSIZE);

__SEND_MESG_DEBUG("ENTERING SelectX")

__CREATE_QUERY("SELECT ");

NGetNames = coa_GetElementCount(cnx, get_class_names);

for(i=0; i<NGetNames; i++)
{
char * as_fields;
if(i==0)
{
snprintf(start_string,10,"\n");
}
if(i==1)
{
snprintf(start_string,10," , \n");
}

__SEND_MESG_DEBUG("We are going to parse field: %s", coa_GetStringElement(cnx, get_prop_names, i))

in_fields = ap_pstrdup(p, coa_GetElement(cnx, get_prop_names, i));
as_fields = ap_pstrdup(p, coa_GetElement(cnx, get_prop_names, i));

field_elems = cou_split(in_fields, fields, ">", MAXFIELDNUMBER);

__ASSERT(field_elems>0 , "In selectX error in parsing field: %s", in_fields)

cur_class_name = coa_GetElement(cnx, get_class_names, i);
as_field_name = ap_psprintf(p, "cov_%s_%s.%s", par_area, cur_class_name, fields[0]);

if(field_elems>1)
{
for(j=1; j<field_elems; j+=3)
{
as_field_name = ap_psprintf(p, "%s(lhlo_%s_%s_%s(%s))", fields[j+2], par_area, fields[j+1], fields[j], as_field_name);
}
if(get_prop_aggregates!=NULL)
{
as_field_name = ap_psprintf(p, "%s(%s)", (char*)coa_GetElement(cnx, get_prop_aggregates, i), as_field_name);
}
__APPEND_TO_QUERY(" %s %s AS \"%s\"", start_string, as_field_name, as_fields);
}
else
{
if(get_prop_aggregates!=NULL)
{
as_field_name = ap_psprintf(p, "%s(%s)", (char*) coa_GetElement(cnx, get_prop_aggregates, i), as_field_name);
}
if(strcmp(fields[0],"*")==0)
{
__APPEND_TO_QUERY(" %s %s ", start_string, as_field_name);
}else
{
__APPEND_TO_QUERY(" %s %s AS \"%s\"", start_string, as_field_name, as_fields);
}
} //ifelse
} // for get_class_names

__SEND_MESG_DEBUG("We have field part of SQL: %s", SQLString)

sql_from_start = strlen(SQLString);
__APPEND_TO_QUERY(" FROM cov_%s_%s ", par_area, (char *) coa_GetElement(cnx, get_class_names, 0));
for(i=1; i<NGetNames;i++)
{
cur_class_name = coa_GetElement(cnx, get_class_names, i);
/* all table names we are taking only once*/
if(0==strstr(SQLString+sql_from_start, cur_class_name))
{
__APPEND_TO_QUERY(" , cov_%s_%s ", par_area, cur_class_name);
}
}

__SEND_MESG_DEBUG("We are after get_class_names")

NFilterNames = coa_GetElementCount(cnx, filter_class_names);
for(i=0; i<NFilterNames; i++)
{
cur_filter_name = coa_GetElement(cnx, filter_class_names, i);
/* all table names we are taking only once*/
if(0==strstr(SQLString+sql_from_start, cur_filter_name))
{
__APPEND_TO_QUERY(" , cov_%s_%s ", par_area, cur_filter_name);
}
}

__SEND_MESG_DEBUG("We are after filter_class_names")

if(filter_r_class_names!=NULL)
{
NElems = coa_GetElementCount(cnx, filter_r_class_names);
for(i=0; i<NElems; i++)
{
cur_elem = coa_GetElement(cnx, filter_r_class_names, i);
/* all table names we are taking only once*/
if(0==strstr(SQLString+sql_from_start, cur_elem) && strlen(cur_elem)>0)
{
__APPEND_TO_QUERY(" , cov_%s_%s ", par_area, cur_elem);
}
}
}

__SEND_MESG_DEBUG("We are after filter_r_class_names")

more_compare = 0;
if(filter_compare != NULL) more_compare = 1;
NElems = coa_GetElementCount(cnx, filter_prop_names);
for(i=0; i<NElems; i++)
{
char * curr_filter_class_names = coa_GetElement(cnx, filter_class_names, i);
char * curr_filter_prop_names = coa_GetElement(cnx, filter_prop_names, i);
char * curr_filter_operators = coa_GetElement(cnx, filter_operators, i);
char * curr_filter_values = coa_GetElement(cnx, filter_values, i);

// these can be NULL
char * curr_filter_compare = (filter_compare == NULL ? NULL : coa_GetElement(cnx, filter_compare, i));
char * curr_filter_r_class_names= (filter_r_class_names == NULL ? NULL : coa_GetElement(cnx, filter_r_class_names, i));
char * curr_filter_r_prop_names = (filter_r_prop_names == NULL ? NULL : coa_GetElement(cnx, filter_r_prop_names, i));

if(i==0)
{
snprintf(start_string,10," WHERE \n");
}
if(i==1)
{
snprintf(start_string,10, " AND \n");
}
if(more_compare && curr_filter_compare==NULL) more_compare=0;
if(more_compare && strcmp(curr_filter_compare, "1")==0)
{
if(strcmp(curr_filter_operators,"LOOSE")==0)
{
__APPEND_TO_QUERY(" %s (cov_%s_%s.%s = cov_%s_%s.%s OR cov_%s_%s.%s = '' ) \n", start_string, par_area,
curr_filter_class_names, curr_filter_prop_names, par_area, curr_filter_r_class_names, curr_filter_r_prop_names,
par_area, curr_filter_r_class_names, curr_filter_r_prop_names);
}
else
{
__APPEND_TO_QUERY(" %s cov_%s_%s.%s %s cov_%s_%s.%s ", start_string, par_area,
curr_filter_class_names, curr_filter_prop_names, curr_filter_operators, par_area, curr_filter_r_class_names, curr_filter_r_prop_names);
}
}
else
{

field_elems = cou_split(curr_filter_prop_names, fields, ">", MAXFIELDNUMBER);

__ASSERT(field_elems>0 , "In selectX error in parsing filter props: %s", curr_filter_prop_names)

as_field_name = ap_psprintf(p, "cov_%s_%s.%s", par_area, curr_filter_class_names, fields[0]);

if(field_elems>1)
{
for(j=1; j<field_elems; j+=3)
{
as_field_name = ap_psprintf(p, "%s(lhlo_%s_%s_%s(%s))", fields[j+2], par_area, fields[j+1], fields[j], as_field_name);
}
}
if (strcasecmp(curr_filter_operators,"IN")==0)
{
__APPEND_TO_QUERY(" %s %s %s %s ", start_string, as_field_name, curr_filter_operators, curr_filter_values);
}
else
{
if (strcasecmp(curr_filter_operators,"LIKE")==0) // case-insensitive LIKE
{
// heve to optimize this (evaluate upper('%s') in c code
__APPEND_TO_QUERY(" %s upper(text(%s)) LIKE upper(text(\'%s\')) ", start_string, as_field_name, curr_filter_values);
}
else
{
__APPEND_TO_QUERY(" %s %s %s \'%s\' ", start_string, as_field_name, curr_filter_operators, curr_filter_values);
}
}
}
}

__SEND_MESG_DEBUG("We are after WHERE")

if(group_by_class_names != NULL && group_by_prop_names != NULL && get_prop_aggregates!=NULL && coa_GetElementCount(cnx, get_prop_aggregates)>0)
{
NElems = coa_GetElementCount(cnx, group_by_class_names);
__ASSERT(NElems>=0, "error getting ElementCount on group_by")
__ASSERT(NElems == coa_GetElementCount(cnx, group_by_prop_names), "different number of group_by_class_names and group_by_prop_names")

for(i=0; i<NElems; i++)
{
if(i==0)
{
snprintf(start_string,10," GROUP BY ");
}
if(i==1)
{
snprintf(start_string,10, " , \n");
}
__APPEND_TO_QUERY(" %s cov_%s_%s.%s ", start_string, par_area, coa_GetStringElement(cnx, group_by_class_names, i),
coa_GetStringElement(cnx, group_by_prop_names, i))
}
}

__SEND_MESG_DEBUG("We are after GROUP BY")

if(get_prop_aggregates==NULL || coa_GetElementCount(cnx, get_prop_aggregates)==0)
{
if(order_by_class_names != NULL && order_by_prop_names != NULL)
{
more_desc = 0;
if(order_by_desc != NULL) more_desc = 1;
NElems = coa_GetElementCount(cnx, order_by_class_names);
for(i=0; i<NElems; i++)
{
char * curr_order_by_class_names = coa_GetElement(cnx, order_by_class_names, i);
char * curr_order_by_prop_names = coa_GetElement(cnx, order_by_prop_names, i);
char * curr_order_by_desc = coa_GetElement(cnx, order_by_desc, i);

if(i==0)
{
snprintf(start_string,10," ORDER BY ");
}
if(i==1)
{
snprintf(start_string,10, " , \n");
}
if (*curr_order_by_class_names) {
__APPEND_TO_QUERY("\n %s cov_%s_%s.%s ", start_string, par_area, curr_order_by_class_names, curr_order_by_prop_names);
} else {
__APPEND_TO_QUERY("\n %s \"%s\" ", start_string, curr_order_by_prop_names);
}

if(more_desc && curr_order_by_desc == NULL) more_desc=0;
if(more_desc && curr_order_by_desc != NULL && strcmp(curr_order_by_desc,"1")==0)
{
__APPEND_TO_QUERY(" DESC ");
}
}
}

if(limit>0) { __APPEND_TO_QUERY(" LIMIT %d ", limit); }
if(offset>0) { __APPEND_TO_QUERY(" OFFSET %d ", offset); }
} // if(get_prop_aggregates!=NULL)

__SEND_MESG_DEBUG("SELECT SQL: %s ", SQLString)

__GET_RESULT_AND_CREATE_JS

// We set field names "manualy" to be sure that they are not cutted to POstgres limit size

if(strcmp("*", coa_GetElement(cnx, get_prop_names, 0))!=0)
{
NGetNames = coa_GetElementCount(cnx, get_class_names);
for(i=0; i<NGetNames; i++)
{
cor_SetFieldName(cnx, corec, i, ap_pstrdup(p, coa_GetElement(cnx, get_prop_names, i)));
}
}