--- parser3/src/classes/table.C 2012/06/08 11:44:02 1.288 +++ parser3/src/classes/table.C 2013/10/04 21:21:54 1.296 @@ -21,7 +21,7 @@ #include "pa_vbool.h" #include "pa_array.h" -volatile const char * IDENT_TABLE_C="$Id: table.C,v 1.288 2012/06/08 11:44:02 misha Exp $"; +volatile const char * IDENT_TABLE_C="$Id: table.C,v 1.296 2013/10/04 21:21:54 moko Exp $"; // class @@ -268,20 +268,24 @@ static lsplit_result lsplit(char** strin char *write; write=read=string; char c; - while((c=*read++)) { + // we are enclosed, searching for second encloser + while(c=*read++) { if(c==encloser) { - char n=*read; - if(n==encloser) // double-encloser stands for encloser + if(*read==encloser) // double-encloser stands for encloser read++; - else if(n==delim1 || n==delim2) { - result.delim=n; - read++; - break; - } + else + break; // note: skipping encloser } - *write++=c; } + // we are no longer enclosed, searching for delimiter, skipping extra enclosers + while(c=*read++) { + if(c==delim1 || c==delim2) { + result.delim=c; + break; + } else if(c!=encloser) + *write++=c; + } *write=0; // terminate *string_ref=c? read: 0; result.piece=string; @@ -626,12 +630,12 @@ static void _menu(Request& r, MethodPara Value* delim_maybe_code=params.count()>1?¶ms[1]:0; Table& table=GET_SELF(r, VTable).table(); - int saved_current=table.current(); - int size=table.count(); + size_t saved_current=table.current(); + size_t size=table.count(); if(delim_maybe_code) { // delimiter set bool need_delim=false; - for(int row=0; row0) { - if(HashStringValue* options=params.as_hash(param_index)){ // options where specified + if(HashStringValue* options=params.as_no_junction(param_index, PARAM_MUST_NOT_BE_CODE).get_hash()){ // can't use .as_has because the 2nd param could be table so .as_hash throws an error --param_index; int valid_options=0; if(Value* vdistinct_code=options->get(sql_distinct_name)) { // $.distinct ? @@ -801,6 +805,9 @@ static void _hash(Request& r, MethodPara } } + if(param_index==2) // options was specified but not as hash + throw Exception(PARSER_RUNTIME, 0, "options must be hash"); + Array value_fields; if(param_index==0){ // list of columns wasn't specified if(value_type==C_STRING) // $.type[string] @@ -926,8 +933,7 @@ static void _sort(Request& r, MethodPara } // sort keys - _qsort(seq, old_count, sizeof(Table_seq_item), - key_values_are_strings?sort_cmp_string:sort_cmp_double); + qsort(seq, old_count, sizeof(Table_seq_item), key_values_are_strings?sort_cmp_string:sort_cmp_double); // reorder table as they require in 'seq' for(i=0; i3?¶ms[3]:0; + + Table& table=GET_SELF(r, VTable).table(); + size_t saved_current=table.current(); + size_t size=table.count(); + + const String* rownum_var_name=rownum_name.is_empty()? 0 : &rownum_name; + const String* value_var_name=value_name.is_empty()? 0 : &value_name; + + Value* var_context=r.get_method_frame()->caller(); + + if(delim_maybe_code) { // delimiter set + bool need_delim=false; + for(size_t row=0; rowput_element(*rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN))); + if(value_var_name) + var_context->put_element(*value_var_name, new VTable(&table)); + + StringOrValue sv_processed=r.process(body_code); + Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); + + const String* s_processed=sv_processed.get_string(); + if(s_processed && !s_processed->is_empty()) { // we have body + if(need_delim) // need delim & iteration produced string? + r.write_pass_lang(r.process(*delim_maybe_code)); + else + need_delim=true; + } + + r.write_pass_lang(sv_processed); + + if(lskip==Request::SKIP_BREAK) + break; + } + } else { + for(size_t row=0; rowput_element(*rownum_var_name, new VString(*new String(String::Body::Format(row), String::L_CLEAN))); + if(value_var_name) + var_context->put_element(*value_var_name, new VTable(&table)); + + r.process_write(body_code); + Request::Skip lskip=r.get_skip(); r.set_skip(Request::SKIP_NOTHING); + + if(lskip==Request::SKIP_BREAK) + break; + } + } + table.set_current(saved_current); +} + static void _append(Request& r, MethodParams& params) { Temp_lang temp_lang(r, String::L_PASS_APPENDED); const String& string=r.process_to_string(params[0]); @@ -1082,7 +1152,7 @@ public: } bool add_row_cell(SQL_Error& error, const char* str, size_t ) { try { - *row+=new String(str, String::L_TAINTED /* no length as 0x00 can be inside */); + *row+=str?new String(str, String::L_TAINTED /* no length as 0x00 can be inside */):&String::Empty; return false; } catch(...) { error=SQL_Error("exception occured in Table_sql_event_handlers::add_row_cell"); @@ -1164,11 +1234,7 @@ static void _sql(Request& r, MethodParam const char* statement_cstr=statement_string.untaint_cstr(r.flang, r.connection()); Table_sql_event_handlers handlers; -#ifdef RESOURCES_DEBUG - struct timeval mt[2]; - //measure:before - gettimeofday(&mt[0],NULL); -#endif + r.connection()->query( statement_cstr, placeholders_count, placeholders, @@ -1176,17 +1242,6 @@ static void _sql(Request& r, MethodParam handlers, statement_string); -#ifdef RESOURCES_DEBUG - //measure:after connect - gettimeofday(&mt[1],NULL); - - double t[2]; - for(int i=0;i<2;i++) - t[i]=mt[i].tv_sec+mt[i].tv_usec/1000000.0; - - r.sql_request_time+=t[1]-t[0]; -#endif - if(bind) unmarshal_bind_updates(*bind, placeholders_count, placeholders); @@ -1336,6 +1391,10 @@ MTable::MTable(): Methoded("table") { // ^table.flip[] add_native_method("flip", Method::CT_DYNAMIC, _flip, 0, 0); + // ^table.foreach[row-num;value]{code} + // ^table.foreach[row-num;value]{code}[delim] + add_native_method("foreach", Method::CT_DYNAMIC, _foreach, 3, 4); + // ^table.append{r{tab}e{tab}c{tab}o{tab}r{tab}d} add_native_method("append", Method::CT_DYNAMIC, _append, 1, 1);