Annotation of parser3/src/classes/hash.C, revision 1.21
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.21 ! parser 7: $Id: hash.C,v 1.20 2001/10/11 11:52:55 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:
1.21 ! parser 97: static void _create_or_append(Request& r, const String& method_name, MethodParams *params) {
1.20 parser 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: }
105: }
106:
1.2 parser 107: static void _sql(Request& r, const String& method_name, MethodParams *params) {
108: Pool& pool=r.pool();
109:
110: if(!r.connection)
111: PTHROW(0, 0,
112: &method_name,
113: "without connect");
114:
1.10 parser 115: Value& statement=params->as_junction(0, "statement must be code");
1.2 parser 116:
117: ulong limit=0;
118: if(params->size()>1) {
1.10 parser 119: Value& limit_code=params->as_junction(1, "limit must be expression");
1.2 parser 120: limit=(uint)r.process(limit_code).as_double();
121: }
122:
123: ulong offset=0;
124: if(params->size()>2) {
1.10 parser 125: Value& offset_code=params->as_junction(2, "offset must be expression");
1.2 parser 126: offset=(ulong)r.process(offset_code).as_double();
127: }
128:
129: Temp_lang temp_lang(r, String::UL_SQL);
130: const String& statement_string=r.process(statement).as_string();
131: const char *statement_cstr=
132: statement_string.cstr(String::UL_UNSPECIFIED, r.connection);
1.11 parser 133: Hash& hash=static_cast<VHash *>(r.self)->hash();
134: hash.clear();
135: Hash_sql_event_handlers handlers(pool, method_name,
136: statement_string, statement_cstr, hash);
1.2 parser 137: bool need_rethrow=false; Exception rethrow_me;
138: PTRY {
139: r.connection->query(
140: statement_cstr, offset, limit,
1.11 parser 141: handlers);
1.2 parser 142: }
1.3 parser 143: PCATCH(e) { // query problem
1.2 parser 144: rethrow_me=e; need_rethrow=true;
145: }
146: PEND_CATCH
147: if(need_rethrow)
148: PTHROW(rethrow_me.type(), rethrow_me.code(),
149: &statement_string, // setting more specific source [were url]
150: rethrow_me.comment());
151: }
152:
1.9 parser 153: static void keys_collector(const Hash::Key& key, Hash::Val *value, void *info) {
154: Table& table=*static_cast<Table *>(info);
155: Pool& pool=table.pool();
156:
157: Array& row=*new(pool) Array(pool);
158: row+=&key;
159: table+=&row;
160: }
161: static void _keys(Request& r, const String& method_name, MethodParams *) {
162: Pool& pool=r.pool();
163:
164: Array& columns=*new(pool) Array(pool);
165: columns+=new(pool) String(pool, "key");
166: Table& table=*new(pool) Table(pool, &method_name, &columns);
167:
168: static_cast<VHash *>(r.self)->hash().for_each(keys_collector, &table);
169:
170: VTable& result=*new(pool) VTable(pool, &table);
171: result.set_name(method_name);
172: r.write_no_lang(result);
173: }
174:
1.16 parser 175: static void _count(Request& r, const String& method_name, MethodParams *) {
176: Pool& pool=r.pool();
177:
178: Value& value=*new(pool) VInt(pool, static_cast<VHash *>(r.self)->hash().size());
179: value.set_name(method_name);
180: r.write_no_lang(value);
181: }
182:
1.1 paf 183: // constructor
184:
185: MHash::MHash(Pool& apool) : Methoded(apool) {
1.2 parser 186: set_name(*NEW String(pool(), HASH_CLASS_NAME));
1.20 parser 187:
1.21 ! parser 188: // ^hash::create[[copy_from]]
! 189: add_native_method("create", Method::CT_DYNAMIC, _create_or_append, 0, 1);
! 190: // ^hash::append[[copy_from]]
! 191: add_native_method("append", Method::CT_DYNAMIC, _create_or_append, 1, 1);
1.2 parser 192:
193: // ^hash:sql[query][(count[;offset])]
194: add_native_method("sql", Method::CT_DYNAMIC, _sql, 1, 3);
195:
1.14 parser 196: // ^hash._keys[]
1.13 parser 197: add_native_method("_keys", Method::CT_DYNAMIC, _keys, 0, 0);
1.16 parser 198:
199: // ^hash._count[]
200: add_native_method("_count", Method::CT_DYNAMIC, _count, 0, 0);
1.1 paf 201: }
202:
203: // global variable
204:
205: Methoded *hash_base_class;
206:
207: // creator
208:
209: Methoded *MHash_create(Pool& pool) {
210: return hash_base_class=new(pool) MHash(pool);
211: }
E-mail: