--- parser3/src/classes/hash.C 2002/08/15 10:38:18 1.45 +++ parser3/src/classes/hash.C 2002/09/17 10:58:23 1.49 @@ -5,7 +5,7 @@ Author: Alexandr Petrosian (http://paf.design.ru) */ -static const char* IDENT_HASH_C="$Date: 2002/08/15 10:38:18 $"; +static const char* IDENT_HASH_C="$Date: 2002/09/17 10:58:23 $"; #include "classes.h" #include "pa_request.h" @@ -35,11 +35,13 @@ class Hash_sql_event_handlers : public S public: Hash_sql_event_handlers(Pool& apool, const String& amethod_name, const String& astatement_string, const char *astatement_cstr, + bool adistinct, Hash& arows_hash) : pool(apool), method_name(amethod_name), statement_string(astatement_string), statement_cstr(astatement_cstr), + distinct(adistinct), rows_hash(arows_hash), columns(pool), row_index(0) { @@ -69,7 +71,11 @@ public: if(column_index==0) { VHash *row_vhash=new(pool) VHash(pool); row_hash=row_vhash->get_hash(0); - rows_hash.put(*cell, row_vhash); + if(rows_hash.put_dont_replace(*cell, row_vhash)) // put. existed? + if(!distinct) + throw Exception("parser.runtime", + cell, + "duplicate key"); } else row_hash->put(*columns.get_string(column_index), new(pool) VString(*cell)); column_index++; @@ -79,6 +85,7 @@ private: Pool& pool; const String& method_name; const String& statement_string; const char *statement_cstr; + bool distinct; Hash& rows_hash; Hash *row_hash; int column_index; @@ -192,14 +199,28 @@ static void _sql(Request& r, const Strin ulong limit=0; ulong offset=0; + bool distinct=false; if(params->size()>1) { Value& voptions=params->as_no_junction(1, "options must be hash, not code"); if(!voptions.is_string()) if(Hash *options=voptions.get_hash(&method_name)) { - if(Value *vlimit=(Value *)options->get(*sql_limit_name)) + int valid_options=0; + if(Value *vlimit=(Value *)options->get(*sql_limit_name)) { + valid_options++; limit=(ulong)r.process_to_value(*vlimit).as_double(); - if(Value *voffset=(Value *)options->get(*sql_offset_name)) + } + if(Value *voffset=(Value *)options->get(*sql_offset_name)) { + valid_options++; offset=(ulong)r.process_to_value(*voffset).as_double(); + } + if(Value *vdistinct=(Value *)options->get(*sql_distinct_name)) { + valid_options++; + distinct=r.process_to_value(*vdistinct).as_bool(); + } + if(valid_options!=options->size()) + throw Exception("parser.runtime", + &method_name, + "called with invalid option"); } else throw Exception("parser.runtime", &method_name, @@ -213,7 +234,9 @@ static void _sql(Request& r, const Strin Hash& hash=static_cast(r.self)->hash(&method_name); hash.clear(); Hash_sql_event_handlers handlers(pool, method_name, - statement_string, statement_cstr, hash); + statement_string, statement_cstr, + distinct, + hash); r.connection(&method_name)->query( statement_cstr, offset, limit, @@ -272,17 +295,17 @@ static void one_foreach_cycle(const Hash Foreach_info& i=*static_cast(info); i.vkey->set_string(akey); - i.r->root->put_element(*i.key_var_name, i.vkey, false); - i.r->root->put_element(*i.value_var_name, static_cast(avalue), false); + i.r->method_frame->put_element(*i.key_var_name, i.vkey, false); + i.r->method_frame->put_element(*i.value_var_name, static_cast(avalue), false); - StringOrValue processed_body=i.r->process(*i.body_code); - if(i.delim_maybe_code) { // delimiter set? - const String *string=processed_body.get_string(); - if(i.need_delim && string && string->size()) // need delim & iteration produced string? + StringOrValue sv_processed=i.r->process(*i.body_code); + const String *s_processed=sv_processed.get_string(); + if(i.delim_maybe_code && s_processed && s_processed->size()) { // delimiter set and we have body + if(i.need_delim) // need delim & iteration produced string? i.r->write_pass_lang(i.r->process(*i.delim_maybe_code)); i.need_delim=true; } - i.r->write_pass_lang(processed_body); + i.r->write_pass_lang(sv_processed); } static void _foreach(Request& r, const String& method_name, MethodParams *params) { Pool& pool=r.pool();