
Proposed Stages

a) skeleton class
 - with new configuration format   static PDO_DataObject::$config[....] 
 - with constants.  
      PDO_DataObject::INT etc...
      PDO_DataObject::ERROR_INVALIDARGS
      PDO_DataObject::WHEREADD_ONLY

 - connect => PDO() 


- globals replacements
     CONFIG:: -> PDO_DataObject::$config
     RESULTS:: ?? not needed? << use private $_result
     RESULTSEQ:: ?? not needed...
     RESULTFIELDS:: probably not needed - info available from $_result->fields 
     
     CONNECTIONS:: PDO_DataObject::$connections
     INI:: PDO_DataObject::$ini
     LINKS:: PDO_DataObject::$links
     SEQUENCE:: PDO_DataObject::$sequence ??? -- cache of sequence keys (modifyable)
     LASTERROR  removed 
     CACHE removed -- part of staticGet? - should we remove this?
     OVERLOADED -- removed
     QUERYENDTIME -- stored in $this->_result->time_query_end;

    debug - callinging LoadConfig with 'debug' - sets self::$debug (not stored in self::$config['debug'])
    

- utilFunctions
     quoteIdentifier 
     dbType $pdo->getAttribute(PDO::ATTR_DRIVER_NAME); -- not needed, just do this...
  

Tests:
    connect  method ::PDO() 
    quoteIdentifer
    
Target:END OF WEEK 1 (est. 2 days) - COMPLETED
-------------------------
b) PDO_DataObjects_Introspection 


     databaseStructure -- all conditions except plain 'ini' 
  
 - may require sub 'versions' PDO_DataObjects_Introspection_Mysql .. Pgsql .. msql .. sqlite (maybe others from DB)
 - implementations of 
      getListOf('schema.tables');
      getListOf('tables'); 
      getListOf('views');
      tableInfo()
      


Tests:
   $do = new PDO_DataObjects( array( 'table' => 'test', 'database' => 'xxxx' )); ?? for testing only?
   or  new PDO_DataObjects('xxxx/test');

   $x = new PDO_DataObjects_Introspection($do);
   $x->getListOf(...)
   == do a test of all the methods... - based on dummy $pdo ? 
  -- these tests are not relivant to compatibility..

-- errors?
  -- ini file does not exist in paths.




Target:END OF WEEK 3 (est. 4 days) - COMPLETED
-------------------------
c) Query  / fetch methods of PDO_DataObject
  -- needed for generator?
   modifyLimitQuery (used by find() , delete() and 
   escape() // uses DB->escapeSimple  DONE... (PDO::quote
   limit() - so we can test modifylimitQuery
Tests:
  -- make sure simple fake tests work... 
  

Target:END OF WEEK 4 (est. 2 days) - COMPLETED
-------------------------
d) Generator
 - creating .ini files / generating code etc...

---
  * start - DONE
  * databaseStructureProxy -- from previous work.
  * _readTableList - DONE - need test
  * _readForeignKeys - DONE - need test
  * generateINI - DONE - need test  (was generateDefinitions)

  * _generateClassTable($oldcontents) -- PHP ?
     _generateGetters($oldcontents);
     _generateSetters($oldcontents);
     _generateLinkMethods($oldcontents);
     _generateDefinitionsTable();     << converts the 'table def' into a 'standard'?
     _generateTableFunction($def['table']);
     _generateKeysFunction($def['keys']);
     _generateSequenceKeyFunction($def);
     _generateDefaultsFunction($this->table, $def['table']);
    // empty functions - to add comments etc.. above code.
    derivedHookFunctions
    derivedHookClassDocBlock
    derivedHookVar
    derivedHookPostVar
    derivedHookPageLevelDocBlock
    derivedHookExtendsDocBlock

  fillTableSchema << used by databaseStructureProxy
   

** what does it do?
  - converts schema from database into
    table
       with columns
       with indexes (foriegn keys etc)
  - uses that information to generate
       INI files
       LINK files
       PHP code

Table Introspecton
 - now outputs Foreign key information (pgsql - tested)
 
 
New Generator methods
  start()  - as before...
  readTableList
  toIni / toPHP / toLinksIni etc...
  generate(Ini|ForeignKeys|Php
  


Tests:
   == do a test of all the methods... - based on dummy $pdo ? 
  -- tests can be run against old + new...
  -- these tests should generate compatible code.


Target:END OF WEEK 6 (est. 4 days) - COMPLETED
-------------------------
e) PDO_DataObject class

  * factory  DONE  
    * databases[] set, but no database - should scan ini to determine which db to use... DONE
  * loadClass   DONE (private) was _autoloadClass
  * get()  DONE 
  * pid()  DONE  

  
  * where()  = new 'chained version'  DONE 
  * whereAdd()  DONE (tested as part of where...)
  * whereIn() = new 'chained version'  DONE  
  * whereAddIn()  DONE (tested as part of whereIn...)
  * orderBy()  DONE  
  * groupBy()  DONE  
  * having()  DONE  
  * unionAdd()  DONE (part of union)
  * union()  = new 'chained verison'  DONE
  * limit() DONE (part of modify Limit Query)

  * select/selectAdd  DONE 
  * selectAs DONE  
  * toSelectSQL() (was _build_select) ->     DONE (part of all above tests..)

  * find() DONE  
  *   support for un-buffered mysql queries?? DONE 

  * fetch() DONE   
  * fetchAll() DONE  /  tested by earlier code ?? 
  * fetchall(CALLABLE) same as foreach, but runs a method on each object... DONE 
  * fetchall(false,true) associative with key==pid()
  * fetchall(false,COLNAME) associative with key==COLNAME

  * fetchAllAssoc() DONE - alias to fetchAll(false,false,true);


  * insert() DONE  
      -- emulated sequence are not supported at present!!
  * update() DONE  
  * delete() DONE 


  * count() DONE  

  * load() DONE chainable get
  * save() DONE   generic update/insert
  * snapshot() DONE (this is auto called on load()) ...
  * NULL/cast? values in INSERT/UPDATE - DONE  

 
  * keys()   DONE  tested as part of insert/update...
  * sequenceKey() DONE tested as part of insert/update...
  * whereToString() (was _build_condition) DONE testing as part of select/selectAdd..
  
  * sqlValue() - DONE 
  * PDO_DataObject_Cast ( $DB == PDO object...)  DONE  

  * setFrom() DONE  
  * set() << chained version of setFrom? DONE 
  * fromValue() DONE 

  * toArray() DONE  
  * formatValue()   DONE  - was toValue() (date formating is not compatible)
  * validate()  DONE   moved to seperate class...
  * raise  (was raiseError) -- DONE - tests all over the place......
  

  * joinAdd() DONE  
  * autoJoin() DONE  

  * links() DONE 
  * tableColumns() - was table()   DONE  tested as part of insert/update...

  * link DONE
  
  * applyLinks DONE / DEPRICATED - not testing
  * linkArray DONE / DEPRICATED - not testing
      PDO_DataObject_Links ( )  DONE

  * PDO_DataObject_Exception ( )   DONE - tested most places..
  * transactions BEGIN/ROLLBACK/COMMIT - DONE 
 


--- >  *

  * config DONE / NEEDS TESTING - of various settings...
   


Tests:
  needs fake DB and PDO objects
  test both DB_DAtaObject and PDO_DataObject for compatibility
  test settings like compatibilitylevel (eg. lowercase everything)
  test settings like null???
  test of query conditions
  test of fetch all/fetch 
  test of update
  test return values of sequencekey 
Existing tests
  bug6953 = last row fetch of joined query (have column data)
  simple.phpt - split into small tests (use fakedb)

  

Target:END OF WEEK 8 (est. 4 days)


-------------------------
Namespaces?? autoloading? packaging

autoloading: in general we still prefer require_once however make the code compatible with class_exists...
class_exists(...) ? '': require_once '....'; << 

For namespacing - we will not bother at this point, I'd rather go with some 'automated' code parse to convert it to 
namespaces.. -  could be PDO\DataObject ? not much real benefit though at present...

Plan is to propose to PEAR? although we can set up a pear channel easily
probably also include a composer file. 

------------------


Migrating DataObjects to use PDO
?? change to PDO_DataObject ???   in theory DB_DataObject extends PDO_DataObjects can be used to support it?

** replaces DB as the backend?


-------------------------
Testing strategy

Develop a test plan
* using phpt http://qa.php.net/write-test.php
* how can we compare 'old' Dataobjects to 'new' one?
* for the tests running against the old version? - support fake 'DB'?
* add an extra setting (unittest={fake pdo object})
   - so any pdo work uses the fake pdo object if in unittest mode..
   

-------------------------
Run throught of DataObject.php


fetch
-> use of result->fetchRow() (query and statement object in pdo)
-> catching of end of results.
-> clearing resultfields 
-> in theory it could fetch into the object.?? = however we covert '.' to '_' ... may be an issue in some scenarios?
BC?


selectAs
-> quoteIdentifier

insert
-> determine Dbtype ( for empty insert)
-> quoteIdentifier
-> sequence inserts and setOption seqname_format..... ??
-> dbtype - used to deterime method to get inserted id
-- sequence handling?? see config options? is there anything more we do about sequences relating to pear?

update
-> quoteIdentifier

delete
-> quoteIdentifier
-> modifyLimitQuery / setLimit ??

count
-> quoteIdentifier 
-> result->fetchRow

escape
-> escapeSimple

_quote  (is this still used?) - it says private?
-> quotesmart?

_connect .... 
-> change over to PDO...
-> connection options??? -- check what we use?

_query
-> transaction begin / autocommit?  PDO::beginTransaction
-> query/exec
-> set 'N' using result->numRows()
-> return $DB->affectedRows();  if insert/update etc...

_build_condition
-> quoteIdentifier


joinAdd / autoJoin -- move code to PDO_DataObject_Join()

toArray - needs resultfields - to determine fields that where returned..
-> ?? depricate link_loaded?? - it's so not recomended to use this.





-----
Things that need implementations (not really provided by PDO?)
quoteIdentifiers
modifyLimitQuery
escapeSimple
dbtype - standard PDO call...


------------------------
Introspection

-- Pro/Cons on splitting this - it's called quite a bit.. so basically esential to operations.
--- contains quite a bit of code 
  ** we could go on the principle, that anything that relates to 'real instrospection goes in it' - and move new getListof stuff
  ** then if stuff is cached, then we can not call it...
  ** if you are being clever and using the keys() -> to set data -> then use the extra class..
  ** basically the base class should provide 90% usages without loading the introspection...


databaseStructure
-> ?? move to DataObject_Introspection?
-> DB->getListOf('tables')
(( calls generator 

??? do we factory/ctor  

keys() -- introspection??  
table() -- introspection?
links() -- introspection?
databaseStructure() -> introspection..


--------------------
_call (move to DB_DataObject_Overload.... )

fromValue/toValue ? used by call really, but are kind of usefull?


---------------------------------- 

Other Changes
-> move globals -> static instances props..
-> constants to -> object constants..

storing resultobject in DO?? - how does that affect print_r ?



?? overload support ?? 
 -- removed - in theory you can just wrap dataobjects, and add the two methods....
 ** we can remove _call and  why is __sleep defined as it is??


fetchRow
-> ?? should we even support this??? depricate?


----------------------------------------------
DB_DataObject_Cast->PDO_DataObject_Cast
** change constants to refer to PDO object...
** needs knowledge of database type (from 'db')

DB_DataObject_Error->PDO_DataObject_Error  -- trivial changes
DB_DataObject_Links->PDO_DataObject_Error  -- minor changes

-------------------------------------------
DB_DataObject_Generator->PDO_DataObject_Generator
** needs access to dbtype.
-> getListOf('scshema.tables'); or  getListOf('tables'); 
->  $__DB->getListOf(is_string($options['build_views']) ?
                                    $options['build_views'] : 'views');


->$__DB->quoteIdentifier()
->$DB->tableInfo()

_createForiegnKeys
-> runs queries to seleect various details for postgres...



-------------------------------------
Configuration / settings..

All configuration will be 
   DB_DataObject::$config[....]   
   -- defaults values set where possible.
   -- avoid 'empty' checks in code where possible.
   -- we can document configuration options in there...



?? config? - 
 - reduce empty checks / set defaults on config values, so that we can just check booleans.

DB portability -- lowercase ?? and other stuff???


database -> new format? 
need to support 'username' & 'password' ?
db_driver << not needed anymore..
dont_use_pear_sequences <<??? need to work out how this affects our code.!?!?



-----------
New Methods
PDO()
result()
reset() - not for general usage.. - clears all 'cached' db connections?? - does not clear 

-----------
Backward Compatibility Breaks. / removed features..


configuration - no longer uses PEAR::getStaticProperty  use PDO_DataObject::config(array(....));
getDatabaseConnection() removed -- use PDO() - however API is different... (IMPORTANT)
getDatabaseResult() - renamed - result() - returns a different object....
database() - renamed databaseNickname -
     as it is not guarenteed to be the actually database name you can get the real database name using
      ( PDO()->dsn[database_name]

table() - renamed to tableColumns() 
factory() - without arguments will not work (PHP change) - use factorySelf()


staticGet -- removed? - create your own cache layer .. it's pretty trivial.
fetchRow  -- removed (use PDO()->fetch(...))
links() - previously calling it with arguments set the global links for that object.
          It now only set's it for that instance, use  

link() - second argument can not be an array (not sure why that was ever supported - it just read the first item in the array?!?

getLink - removed - used link()
getLinkArray - renamed - linkArray()
getLinks - renamed - applyLinks()

Private methods removed/renamed..
_connect() -> public PDO()

$do->_database_dsn - removed - this was a security hole wating to fail... (Accidental print_r's etc...)
$do->_DB_resultid removed
$do->_lastError - removed - ?? Not sure if this is every used anymore..

config changes
debug_ignore_updates << removed. use config[PDO] == {fake PDO}
sequence_***** << no longer used - override sequenceKey() 
ignore_sequence_keys  << no longer used - override sequenceKey() 
dont_use_pear_sequences << not relivant.. 
links_**** not used
ini_**** not used  - use schema_location[database] = .....

keep_query_after_fetch = removed - behaviour was inconsistant - and unpredictable... (just clone before find/fetch)

-- Debug Levels
1 - basic QUERY and results.
2 - Timers
3 - Detail returned data
4 - Full connection details (including DSN with password)
----------------------------------------------------





STAGE 2:
- use 'prepared' statements rather than constructing the SQL
  ** this may be problematic as methods may need changing... like 'whereAdd' etc...
  ** hence postpone this and ignore at present.
