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