/[cvs]/nfo/php/libs/com.newsblob.phphtmllib/widgets/data_source/GenericDataSource.inc
ViewVC logotype

Annotation of /nfo/php/libs/com.newsblob.phphtmllib/widgets/data_source/GenericDataSource.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Sat Mar 1 21:47:15 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
renamed from AbstractDataSource.inc

1 joko 1.1 <?php
2     /**
3     * This file contains the GenericDataSource child class
4     * that may use arbitrary code modules as database handlers.
5     * It's aims are to get together:
6     * o phpHtmlLibs "source-handlers"
7     * o PEAR's database handlers
8     * o custom ones (e.g. Data::Driver::Proxy object, which talks to a remote rpc server)
9     *
10     * @author Andreas Motl <andreas.motl@ilo.de>
11     * @package phpHtmlLib
12     * @module GenericDataSource
13     *
14     */
15    
16     /**
17     * $Id: AbstractDataSource.inc,v 1.1 2003/03/01 20:17:15 joko Exp $
18     *
19     * $Log: AbstractDataSource.inc,v $
20     * Revision 1.1 2003/03/01 20:17:15 joko
21     * renamed from GenericDataSource.inc
22     * replaced '_proxy' through '_handler' to better associate the ability to act as a generic dispatcher handler
23     *
24     * Revision 1.3 2003/03/01 15:36:11 joko
25     * + debugging
26     * + renamed some methods regarding new proposal (build_handler_options, fetch_result, etc.)
27     *
28     * Revision 1.2 2003/03/01 04:50:27 joko
29     * encapsulated all output into tracing mode
30     * disabled tracing
31     *
32     * Revision 1.1 2003/03/01 03:10:40 joko
33     * + initial commit
34     *
35     *
36     */
37    
38     /**
39     * This requires the MemoryDataSource base class
40     *
41     */
42     // V1: compile-time-include, stable since years ;-)
43     include_once($phphtmllib."/widgets/data_source/MemoryDataSource.inc");
44     // V2: runtime-load proposal, more flexible
45     // loadModule('MemoryDataSource', 'inc'); // doesn't work (would do if basepath of module is in libpath)
46     // loadModule($phphtmllib . '::widgets::data_source::MemoryDataSource', 'inc'); // works (by accident)
47     // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource", "inc"); // works (should be stable)
48     // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource.inc", null); // works (should be stable)
49    
50    
51    
52     /**
53     * Have to have PEAR and DB included
54     * the pear dir must be in the
55     * include path.
56     */
57     // require_once("PEAR.php"); // FIXME: what about PEAR::XML::RPC?
58     // require_once("DB.php");
59    
60     /**
61     * This GenericDataSource child class is *completely* independent
62     * of a specific storage implementation and intended to be a wrapper
63     * class on the way from phpHtmlLib to Xyz.
64     * ("Yyz" gets represented by Data::Storage by now.....)
65     *
66     * GenericDataSource interacts with an intermediate "proxy" object
67     * (e.g. Data::Driver::Proxy) when doing queries.
68     * Don't mix this up with a persistent database handle which gets
69     * reused each and every time for different queries.
70     * Here *is* a new instance of Data::Driver::Proxy for *each* query.
71     *
72     * But the point is: Caching! The actual *data* isn't read redundant!
73     *
74     *
75     * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
76     *
77     * Data::Driver::Proxy instantiates "handlers" below itself
78     * which act as encapsulated workers to actually do the stuff to do.
79     * It can cache data for "disconnected mode" using the
80     * php PEAR DB abstraction objects.
81     * One worker already implemented is Data::Driver::RPC::Remote, which
82     * talks to a RPC::XML server (todo: talk SOAP!) using PEAR::XML::RPC.
83     *
84     * --- refactored here, but: redundant somehow ---
85     * Data::Driver::Proxy uses a PEAR XML::RPC object to actually
86     * talk HTTP and serialize data chunks to and from XML,
87     * but adds some caching to this "process of fetching data from a remote side".
88     * It "proxies" arbitrary data chunks a) inside a native php4 session,
89     * b) by talking to a rdbms (single proxy-table) or c) [TODO] using PEAR::Cache.
90     * --- refactored here, but: redundant somehow ---
91     *
92     * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
93     *
94     *
95     * How to use?
96     *
97     * Pass an array holding "locator metadata" to the constructor.
98     * GenericDataSource takes care of the rest.
99     *
100     * Pass an array to the constructor: (e.g.)
101     *
102     * 1. doing rpc-calls....
103     * $locator = array(
104     * type => 'rpc',
105     * metadata => array( Host => 'localhost', Port => '8765' ),
106     * );
107     * $source = new GenericDataSource($locator);
108     * $this->set_data_source( &$source );
109     *
110     * 2. [proposal] common datahandles....
111     * $locator = array(
112     * type => 'mysql',
113     * dsn => 'known dsn markup',
114     * );
115     * $source = new GenericDataSource($locator);
116     * $this->set_data_source( &$source );
117     *
118     * @author Andreas Motl <andreas.motl@ilo.de>
119     * @author Sebastian Utz <seut@tunemedia.de>
120     * @copyright (c) 2003 - All Rights reserved.
121     * @license GNU LGPL (GNU Lesser General Public License)
122     *
123     * @author-url http://www.netfrag.org/~joko/
124     * @author-url http://www.netfrag.org/~jonen/
125     * @license-url http://www.gnu.org/licenses/lgpl.txt
126     *
127     * @package phpHtmlLib
128     * @module GenericDataSource
129     *
130     */
131    
132     /**
133     * Todo:
134     *
135     * o mungle this to be able to be wrapped around phpHtmlLib's own storage-handles
136     * o implement another Data::Driver::Proxy container
137     *
138     */
139    
140    
141     class GenericDataSource extends MemoryDataSource {
142    
143     /**
144     * This var holds the locator metadata hash
145     * that is used to feed metadata to a per-query-instance
146     * of a Data::Driver::Proxy object.
147     *
148     */
149     var $_locator = NULL;
150    
151    
152     /**
153     * This var holds the query hash
154     * that is used to feed as query to a per-query-instance
155     * of a Data::Driver::Proxy object.
156     *
157     */
158     var $_query = NULL;
159    
160    
161     /**
162     * This var holds the Handler object
163     * that is used to do the work.
164     * It acts as a dispatcher combining result caching.
165     * It is assumed that this provides 4 methods:
166     * queryData() - execute a query against a data storage
167     * querySchema() - execute a query against underlying storage metadata
168     * sendCommand() - send a command against an arbitrary execution engine
169     * ... or others! (these are just proposals for convenience)
170     *
171     */
172     var $_handler = NULL;
173    
174    
175     /**
176     * This var holds options fed to the Proxy object
177     * These are built from locator metadata (_locator) and query arguments (_query)
178     * It's a simple structured hash:
179     * $proxy_options = array(
180     * method => '<remote-method-name>',
181     * args => array('list', 'of', 'arguments')
182     * );
183     *
184     */
185     var $_handler_options = NULL;
186    
187    
188     /**
189     * this holds the query result from the
190     * Data::Driver::Proxy->queryXyz() call
191     *
192     */
193     var $_result = NULL;
194    
195     /**
196     * This holds some information about the tracing level.
197     *
198     */
199     var $_debug = array(
200     notice => 0,
201     trace => 0,
202     payload => 0,
203     );
204    
205    
206     /**
207     * The constructor is used to pass in the
208     * locator metadata hash.
209     *
210     * @param LocatorMetadataHash array - layout: array( type => '', metadata => '', dsn => '' )
211     * @param Query array - layout: array( type => '', metadata => '', dsn => '' )
212     */
213     function GenericDataSource( &$locator, $query ) {
214    
215     $this->set_locator( $locator );
216     $this->set_query( $query );
217     }
218    
219     /**
220     * Set the locator metadata hash we will feed *partly*
221     * to an encapsulated Data::Driver::Proxy instance.
222     *
223     * @param LocatorMetadataHash array -
224     *
225     */
226     function set_locator( &$locator ) {
227     $this->_locator = &$locator;
228     }
229    
230     /**
231     * Set the query metadata hash we will feed *completely*
232     * to an encapsulated Data::Driver::Proxy instance.
233     *
234     * @param QueryDeclaration array -
235     *
236     */
237     function set_query( $query ) {
238     $this->_query = $query;
239     }
240    
241     /**
242     * Directly inject a Data::Driver::Proxy instance to use.
243     *
244     * @param Data::Driver::Proxy object - &$proxy
245     *
246     */
247     function set_handler( &$proxy ) {
248     $this->_handler = &$proxy;
249     }
250    
251     /**
252     * Issue remote/proxy call
253     * Stolen from Application_AbstractBackend::_remote_method (RefactoringProposal?)
254     * Tweaked a bit: proxy package now taken from $this->_handler_name
255     *
256     * Create a new instance of a proxy and store it for later reuse.
257     * Read the locator metadata hash and create
258     * the proxy handler instance using passed-in name.
259     *
260     * @param string - $proxy_name (namespaced classname - perl syntax - e.g.: Data::Driver::Proxy)
261     *
262     */
263     function do_handler_call() {
264    
265    
266     // 1. read args
267    
268     $arg_list = func_get_args();
269     $command = array_shift($arg_list);
270     $cache_key = join("-", array(session_id(), $command, join('_', $arg_list) ));
271     //print "cache_key: $cache_key<br>";
272    
273     // FIXME: what if arg_list still contains more elements after doing this?
274     $query = array_shift($arg_list);
275    
276    
277     // 2. prepare proxy-options
278    
279     // read from locator metadata
280     $proxy_name = $this->_locator[metadata][package];
281     $rpcinfo = array( Host => $this->_locator[metadata][Host], Port => $this->_locator[metadata][Port] );
282    
283     // FIXME! implement this into Data::Driver::RPC::Remote!
284     //$rpcinfo[to_latin] = 1;
285    
286     // FIXME! patch query
287     if (sizeof($query) == 1) {
288     $query = $query[0];
289     }
290    
291     // -------------------- clone this & modify ----------
292     $proxy = mkObject($proxy_name, $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
293     $this->set_handler( $proxy );
294     //$result = $resultHandle->getAttributes();
295     //return $result;
296     //$this->_result = $resultHandle->getAttributes();
297     //$this->_result = $this->_handler->getAttributes();
298     // -------------------- clone this & modify ----------
299    
300     }
301    
302     function O_do_query() {
303     $this->_result = $this->_db->query($this->_query);
304     if (DB::isError($this->_result)) {
305     $msg = $this->_result->getMessage();
306     user_error("PEARSQLDataListSource::do_query() - query failed : ".$msg);
307     }
308     }
309    
310     function build_handler_options() {
311    
312     //print Dumper($this->_query);
313     //exit;
314    
315     // make up a command from metadata
316     // FIXME: abstract this some more (e.g. via a CommandMapper|Registry)
317     switch ($this->_query[metatype]) {
318     case 'data':
319     //$command = 'queryData';
320     $command = 'getObjects'; // FIXME!!!
321     $args = array();
322     switch ($this->_query[vartype]) {
323     case 'object':
324     if (!$this->_query[classname]) {
325     $msg = "_query[vartype] == 'object' requires _query[classname]";
326     user_error("GenericDataSource::do_query() - failed: " . $msg);
327     }
328     array_push($args, $this->_query[classname]);
329     break;
330     }
331     break;
332     case 'schema':
333     $command = 'querySchema';
334     break;
335     }
336    
337     // trace
338     $this->debug(null, '<b>= = = = = = = = = = = = = = = = = = = = = =</b>');
339     $this->trace('build_handler_options', array(
340     "_locator" => $this->_locator,
341     "_query" => $this->_query,
342     "command" => '<b>' . $command . "</b>",
343     "args" => $args
344     ));
345    
346     $this->_handler_options = array(
347     method => $command,
348     args => $args,
349     );
350    
351     }
352    
353     function fetch_result() {
354    
355     $this->build_handler_options();
356     $method = $this->_handler_options[method];
357     $args = $this->_handler_options[args];
358    
359     // pre-flight checks
360     if (!$method) {
361     $msg = "Remote command could not be resolved, please pass in or check configuration.";
362     user_error("GenericDataSource::do_query() - failed: " . $msg);
363     return;
364     }
365    
366     // do remote call here and get result
367     // FIXME: handle synchronous/asynchronous mode here!!!
368     $this->do_handler_call($method, $args);
369     // TODO: ... = $this->poll_handler_result and $this->get_handler_result
370     $this->_result = $this->_handler->getAttributes();
371    
372     // trace
373     if ($this->_debug[notice]) {
374     //print "_result = " . Dumper($this->_result);
375     print "_result - count = " . sizeof($this->_result) . "<br/>";
376     }
377    
378     }
379    
380    
381     function do_query() {
382     //print "query!<br/>";
383     $this->fetch_result();
384     $this->handle_result();
385     }
386    
387     function get_header() {
388     $this->fetch_result();
389     $this->read_labels_from_result();
390     return $this->get_labels();
391     }
392    
393    
394     function O_do_prequery() {
395     //print "prequery!<br/>";
396     // HACK!!!
397     // modify behaviour here: for now it is needed to call for the schem
398     // eventually modify here to get schema from some registry component (already locally available)
399     $this->fetch_result();
400     //print Dumper($this->_result);
401     //print Dumper($this->_result[0]);
402     //exit;
403    
404     //$this->_get_header();
405     }
406    
407    
408     function O_get_header() {
409     //$this->do_prequery();
410     // FIXME: prevent multi-calls by base class
411     $this->fetch_result();
412     foreach($this->_result[0] as $key => $value) {
413     array_push($this->_data_keys, $key);
414     }
415    
416     $this->set_schema($this->_result[0]);
417    
418     //$this->_get_header();
419     //return $this->_data_keys;
420    
421     }
422    
423    
424    
425    
426    
427    
428    
429    
430    
431    
432     /**
433     * This function gets the next data row
434     * from the query()
435     *
436     * @return array()
437     */
438     function O_get_next_data_row() {
439     return $this->_result->fetchRow(DB_FETCHMODE_ASSOC);
440     }
441    
442     /**
443     * This function builds the limit
444     * clause portion of a DB query.
445     *
446     * @return string - the limit portion of
447     * the query.
448     */
449     function O_build_limit_clause($offset, $limit) {
450     if ($this->get_limit() != -1 ) {
451     if ($offset == '' || $offset == "none") {
452     $offset = 0;
453     }
454     switch(get_class($this->_db)) {
455     case "db_mysql":
456     $clause = " LIMIT $offset, $limit ";
457     break;
458     case "db_pgsql":
459     $clause = " LIMIT $limit, $offset ";
460     break;
461     default:
462     $clause = " LIMIT $offset, $limit ";
463     break;
464     }
465     return $clause;
466     } else {
467     return NULL;
468     }
469     }
470    
471     /**
472     * find the number of rows to be returned
473     * from a query from a table and where clause
474     *
475     * @param string $table - the table to count from
476     * @param string $where_clause - a where clause
477     *
478     * @return int the # of rows
479     */
480     function O_count($tables, $where_clause='', $count_clause='*') {
481     $query = "select count(".$count_clause.") as COUNT from ".$tables." ".$where_clause;
482     $result = $this->_db->query($query);
483     if (DB::isError($this->_result)) {
484     $msg = $result->getMessage();
485     user_error("PEARSQLDataListSource::count() - query failed : ".$msg);
486     }
487     $value = $result->fetchRow(DB_FETCHMODE_ASSOC);
488     return ($value ? (int)$value["COUNT"] : NULL);
489     }
490    
491     }
492    
493     ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed