Annotation of parser3/src/classes/hash.C, revision 1.20
1.1 paf 1: /** @file
2: Parser: @b hash parser class.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.19 parser 5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.1 paf 6:
1.20 ! parser 7: $Id: hash.C,v 1.19 2001/09/26 10:32:25 parser Exp $
1.1 paf 8: */
9:
10: #include "classes.h"
11: #include "pa_request.h"
12: #include "pa_vhash.h"
1.6 parser 13: #include "pa_vvoid.h"
1.2 parser 14: #include "pa_sql_connection.h"
1.9 parser 15: #include "pa_vtable.h"
1.2 parser 16:
17: // defines
18:
19: #define HASH_CLASS_NAME "hash"
1.1 paf 20:
21: // class
22:
23: class MHash : public Methoded {
1.2 parser 24: public: // VStateless_class
25: Value *create_new_value(Pool& pool) { return new(pool) VHash(pool); }
26:
1.1 paf 27: public:
28: MHash(Pool& pool);
29: public: // Methoded
1.2 parser 30: bool used_directly() { return true; }
1.1 paf 31: };
32:
33: // methods
34:
1.11 parser 35: #ifndef DOXYGEN
36: class Hash_sql_event_handlers : public SQL_Driver_query_event_handlers {
37: public:
38: Hash_sql_event_handlers(Pool& apool, const String& amethod_name,
39: const String& astatement_string, const char *astatement_cstr,
40: Hash& arows_hash) :
41: pool(apool),
42: method_name(amethod_name),
43: statement_string(astatement_string),
44: statement_cstr(astatement_cstr),
45: rows_hash(arows_hash),
46: columns(pool),
47: row_index(0) {
48: }
49: void add_column(void *ptr, size_t size) {
50: String *column=new(pool) String(pool);
51: column->APPEND_TAINTED(
52: (const char *)ptr, size,
53: statement_cstr, 0);
54: columns+=column;
55: }
56: void before_rows() {
57: if(columns.size()<=1)
58: PTHROW(0, 0,
59: &method_name,
60: "column count must be more than 1 to create a hash");
61: }
62: void add_row() {
63: column_index=0;
64: }
65: void add_row_cell(void *ptr, size_t size) {
66: String *cell=new(pool) String(pool);
67: if(size)
68: cell->APPEND_TAINTED(
69: (const char *)ptr, size,
70: statement_cstr, row_index++);
71: if(column_index==0) {
72: VHash *row_vhash=new(pool) VHash(pool);
73: row_hash=row_vhash->get_hash();
74: rows_hash.put(*cell, row_vhash);
75: } else
76: row_hash->put(*columns.get_string(column_index), new(pool) VString(*cell));
1.12 parser 77: column_index++;
1.11 parser 78: }
79:
80: private:
81: Pool& pool;
82: const String& method_name;
83: const String& statement_string; const char *statement_cstr;
84: Hash& rows_hash;
85: Hash *row_hash;
86: int column_index;
87: Array columns;
88: int row_index;
89: };
90: #endif
91:
1.20 ! parser 92: static void copy_pair_to(const Hash::Key& key, Hash::Val *value, void *info) {
! 93: Hash& dest=*static_cast<Hash *>(info);
! 94: dest.put(key, value);
! 95: }
! 96:
! 97: static void _create(Request& r, const String& method_name, MethodParams *params) {
! 98: Pool& pool=r.pool();
! 99:
! 100: if(params->size()) {
! 101: Value& vsrc=params->as_no_junction(0, "copy_from must be hash");
! 102: if(Hash *src=vsrc.get_hash())
! 103: src->for_each(copy_pair_to, &static_cast<VHash *>(r.self)->hash());
! 104: else
! 105: PTHROW(0, 0,
! 106: &method_name,
! 107: "copy_from must be hash");
! 108: }
! 109: }
! 110:
1.2 parser 111: static void _sql(Request& r, const String& method_name, MethodParams *params) {
112: Pool& pool=r.pool();
113:
114: if(!r.connection)
115: PTHROW(0, 0,
116: &method_name,
117: "without connect");
118:
1.10 parser 119: Value& statement=params->as_junction(0, "statement must be code");
1.2 parser 120:
121: ulong limit=0;
122: if(params->size()>1) {
1.10 parser 123: Value& limit_code=params->as_junction(1, "limit must be expression");
1.2 parser 124: limit=(uint)r.process(limit_code).as_double();
125: }
126:
127: ulong offset=0;
128: if(params->size()>2) {
1.10 parser 129: Value& offset_code=params->as_junction(2, "offset must be expression");
1.2 parser 130: offset=(ulong)r.process(offset_code).as_double();
131: }
132:
133: Temp_lang temp_lang(r, String::UL_SQL);
134: const String& statement_string=r.process(statement).as_string();
135: const char *statement_cstr=
136: statement_string.cstr(String::UL_UNSPECIFIED, r.connection);
1.11 parser 137: Hash& hash=static_cast<VHash *>(r.self)->hash();
138: hash.clear();
139: Hash_sql_event_handlers handlers(pool, method_name,
140: statement_string, statement_cstr, hash);
1.2 parser 141: bool need_rethrow=false; Exception rethrow_me;
142: PTRY {
143: r.connection->query(
144: statement_cstr, offset, limit,
1.11 parser 145: handlers);
1.2 parser 146: }
1.3 parser 147: PCATCH(e) { // query problem
1.2 parser 148: rethrow_me=e; need_rethrow=true;
149: }
150: PEND_CATCH
151: if(need_rethrow)
152: PTHROW(rethrow_me.type(), rethrow_me.code(),
153: &statement_string, // setting more specific source [were url]
154: rethrow_me.comment());
155: }
156:
1.9 parser 157: static void keys_collector(const Hash::Key& key, Hash::Val *value, void *info) {
158: Table& table=*static_cast<Table *>(info);
159: Pool& pool=table.pool();
160:
161: Array& row=*new(pool) Array(pool);
162: row+=&key;
163: table+=&row;
164: }
165: static void _keys(Request& r, const String& method_name, MethodParams *) {
166: Pool& pool=r.pool();
167:
168: Array& columns=*new(pool) Array(pool);
169: columns+=new(pool) String(pool, "key");
170: Table& table=*new(pool) Table(pool, &method_name, &columns);
171:
172: static_cast<VHash *>(r.self)->hash().for_each(keys_collector, &table);
173:
174: VTable& result=*new(pool) VTable(pool, &table);
175: result.set_name(method_name);
176: r.write_no_lang(result);
177: }
178:
1.16 parser 179: static void _count(Request& r, const String& method_name, MethodParams *) {
180: Pool& pool=r.pool();
181:
182: Value& value=*new(pool) VInt(pool, static_cast<VHash *>(r.self)->hash().size());
183: value.set_name(method_name);
184: r.write_no_lang(value);
185: }
186:
1.1 paf 187: // constructor
188:
189: MHash::MHash(Pool& apool) : Methoded(apool) {
1.2 parser 190: set_name(*NEW String(pool(), HASH_CLASS_NAME));
1.20 ! parser 191:
! 192: // ^hash::create[[default value]]
! 193: add_native_method("create", Method::CT_DYNAMIC, _create, 0, 1);
1.2 parser 194:
195: // ^hash:sql[query][(count[;offset])]
196: add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 3);
197:
1.14 parser 198: // ^hash._keys[]
1.13 parser 199: add_native_method("_keys", Method::CT_DYNAMIC, _keys, 0, 0);
1.16 parser 200:
201: // ^hash._count[]
202: add_native_method("_count", Method::CT_DYNAMIC, _count, 0, 0);
1.1 paf 203: }
204:
205: // global variable
206:
207: Methoded *hash_base_class;
208:
209: // creator
210:
211: Methoded *MHash_create(Pool& pool) {
212: return hash_base_class=new(pool) MHash(pool);
213: }
E-mail: