| /* webfan (C) Till Wehowski, Webfan.de - All rights reserved. */
 'use strict'
 
function preloadFromFilesystem(tStr, columns, _keys, defData, timeout){
	    
 'use strict';
 
(function(){ 
  
  
 var fs =  require('fs'); 
 var parts = frdl.explode('.', tStr);
 if(2 !== parts.length){
 	console.error('Cannot preload table ' + tStr + ', required syntax: db.table (one dot required)');
 	return;
 }   
 var DB = parts[0];
 var table = parts[1];
 
 var __loaded = false;
 var Cols = columns;  
 var keys_ = _keys;
 
 if(!timeout)var timeout = 1000;
 
 
 if(!defData || !Array.isArray(defData) || false===defData instanceof Array){
 	defData = [];
 }else if(defData && defData.length && 0<defData.length && Array.isArray(Cols)){
 	if(defData[0].length !== Cols.length){
 	 console.error('Cannot preload table ' + tStr + ', invalid data format (cols do not fit)');
 	 return;		
	}
 }
  
      
function setDefaults(){
 if(!!__loaded)return;
 __loaded=true;	
 if(!Array.isArray(Cols)){
 	console.error('Cannot preload table ' + tStr + ', no columns defined');
 	return;
 }
	
 var DB_DEFAULT = {};
 DB_DEFAULT[DB]={}	;
 DB_DEFAULT[DB][table] = {
 	 KEYINDEX : keys_,
     columns :  Cols,
     data  : defData
  };
 
 frdl.sql.connect(DB_DEFAULT, function(err, server){
	if(err){
		console.error(err);
		if(!!frdl.alert)frdl.alert.error(err);
		return;
	}
   if(0<frdl.debug.mode())console.log('sql connect...');
   
   process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
   fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(err,dirEntry) {        
      if(err){
	 	console.error(err);
	 //	return;
	 }
	 
		          process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
	              fs.writeFile('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'KEYINDEX.json', JSON.stringify(DB_DEFAULT[DB][table].KEYINDEX), function(err, data){
  	                      if(err){
	    	                 console.error(err);
	     	              // return;
	                     }
                    });   
	 
	 
	              process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
	              fs.writeFile('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'columns.json', JSON.stringify(DB_DEFAULT[DB][table].columns), function(err, data){
  	                      if(err){
	    	                 console.error(err);
	     	              // return;
	                     }
                    });  
	 
	        process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
	        fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'data'
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(__err,__DataDirEntry) {
                                  	
                 if(__err){
	            	console.error(__err);
	 	          //  return;
	             }         
	             
	             
	            process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	 
	            fs.readdir( __DataDirEntry, function(err, tableFiles){
       	
       	          process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
                  fs.writeFile('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'data'
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'rows.'+(tableFiles.length + 1).toString()+'.json', JSON.stringify(defData), function(err, data){
  	                      if(err){
	    	                 console.error(err);
	     	            //   return;
	                     }
                    });                         	
                });                   	                      	
            });                      	 
	 
	 
   });
   
 }); 	
}
try{
	
 var DB_DEFAULT = {};
 DB_DEFAULT[DB]={}	;	
 DB_DEFAULT[DB][table] = {};  
  	
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	  	
fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(err,dirEntry) { 	
                
                                  
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(err,dirEntry) { 
                               
                                  
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	                                  	
fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(err,dirEntry) {        
    if(err){
	 	//setDefaults();
	 	console.warn(err);
	 }
	 
   if(1<frdl.debug.mode()) console.dir(dirEntry);
   
   
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	    
fs.readdir( '1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR, function(err, entries){
         	  if(err){
			  	console.error(err);
			  	return setDefaults();
			  }
              if(0===entries.length){
	 		     return setDefaults();
	          }
	          
	          
	          
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);
fs.readFile('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + 'KEYINDEX.json', function(ierr, idata){
         	if(ierr){ 
       	    if(0<frdl.debug.mode()) console.warn(ierr);
       	     return;
		   }              
		   
	try{
    	keys_ = JSON.parse(idata);
	    DB_DEFAULT[DB][table].KEYINDEX = keys_;		
	}catch(err){
		console.warn(err);
	}	   
		                     	
});	
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);		          
fs.readFile('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + 'columns.json', function(colerr, coldata){
       	   if(colerr){ 
       	    if(0<frdl.debug.mode()) console.warn(colerr);
       	     return setDefaults();
		   }else{
		   	if(!__loaded){
			   __loaded=true;
			   try{
		         Cols = JSON.parse(coldata);	
	             DB_DEFAULT[DB][table].columns = Cols;	
		       }catch(err){
	           	console.warn(err);
	           }	              
	        } 	   	
		   }
		   
            
process.cwd(frdl.fs5.polyfill.getFiler().fs.root);	
fs.mkdir('1.3.6.1.4.1.37553.8.1.8.8.10.2.1'+frdl.DIRECTORY_SEPARATOR
                                  + 'dbs' 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + DB 
                                  +frdl.DIRECTORY_SEPARATOR 
                                  + table
                                  +frdl.DIRECTORY_SEPARATOR
                                  + 'data'
                                  +frdl.DIRECTORY_SEPARATOR,  '0755',  function(__err,__DataDirEntry) {
                                  				  
fs.readdir( __DataDirEntry, function(_err, dataEntries){			  
	// console.dir(entries); 
var c =0;
frdl.each(dataEntries, function(i, dataFile){
 if(!dataFile.isFile)return true;
 	
 fs.readFile(dataFile, function(err, TableData){
 	__loaded=true;
 	c++;
 	
       	   if(err){ 
       	     console.error(err);
		   	 return;
		   }
		   
		   if(!DB_DEFAULT[DB][table].data){
		   	  DB_DEFAULT[DB][table].data=[];
		   }
    try{  
      // TableData = JSON.parse(TableData);
      DB_DEFAULT[DB][table].data=JSON.parse(TableData);
     //  frdl.each(TableData, function(i, row){
     //    	if(-1===DB_DEFAULT[DB][table].data.indexOf(row))DB_DEFAULT[DB][table].data.push(row);
     //  });	
     }catch(err){
	     	console.warn(err);
	 }       
  	
 if(c === dataEntries.length){
   frdl.sql.connect(DB_DEFAULT, function(err, server){
	 if(err){
	  	console.error(err);
		if(!!frdl.alert)frdl.alert.error(err);
		return;
	}
    if(0<frdl.debug.mode())console.log('sql connect...');
  });  	
 }
		   
 });
});
});	
});   		   
});	
});  
}); 
}); 	
});  
  webfan.$Async(function(){
  	  webfan.$Async(function(){
  	     if(!!__loaded)return;
  	     setDefaults();	
  	  },1);	 
  },timeout);	
	
}catch(err){
	console.warn(err);
    setDefaults();
}
}()); 
}
  
 
function load(THAT, m){
	
	 //THAT.LinqLib && THAT.linq && THAT.sql
	
   if(!m || 'sql' === m){
 	 if( !THAT.sql ){
 	 	try{
			frdl.UI.progress().start();
			var p = true;
		}catch(err){
			
		}
	try{	
 	 	  THAT.sql = frdl.require('nquery/forked-frdl-1/index');
 	 	  if(!!p)frdl.UI.progress().complete();
		}catch(err){
		  console.warn(err);	
		} 	 	
 	 	
	 }	
  }		
  
   if(!m || 'linq' === m){
 	 if( !THAT.LinqLib || !THAT.linq ){
 	 	try{
			frdl.UI.progress().start();
			var p = true;
		}catch(err){
			
		}
		try{	
 	 	   THAT.LinqLib = frdl.require('typescript-dotnet-commonjs/System.Linq/Linq');
 	 	   THAT.linq = frdl.require('typescript-dotnet-commonjs/System.Linq/Linq').Enumerable;
	       if(!!p)frdl.UI.progress().complete();
		}catch(err){
		  console.warn(err);	
		} 	 	       
	 }   	
   }	
  
  
}
 
 
 
 
 
 
 var SQL = function(){
 	
 };
 
 SQL.prototype = {
 	sql : false,
 	LinqLib : false, 
 	linq : false,
 	
 	
 	preload : function(){
 	 var  THAT = this;
 	 if( THAT.LinqLib && THAT.linq && THAT.sql){
	   THAT.preload = true; 	
	   return;	
	 }
	 
	 
 	 setTimeout(function(){
   	  webfan.$Async(function(){
   	   setTimeout(function(){
   	  	
   	  
 	 if( !THAT.sql ){
 	 	try{
			frdl.UI.progress().start();
			var p = true;
		}catch(err){
			
		}
	  setTimeout(function(){
	  	if( THAT.sql )return;	
 	 	frdl.require('nquery/forked-frdl-1/index', function(nQuery){
 	 		THAT.sql = nQuery;
	 	    if(!!p)frdl.UI.progress().complete();	 		
 	 	});
 	  },10); 	
	 }
	 
	 
		
 	 if( !THAT.LinqLib || !THAT.linq ){
 	 	try{
			frdl.UI.progress().start();
			var p = true;
		}catch(err){
			
		}
	  setTimeout(function(){	
	  if( THAT.LinqLib )return;	
 	 	frdl.require('typescript-dotnet-commonjs/System.Linq/Linq', function(LINQ){
 	 		THAT.LinqLib = LINQ;
 	 	    THAT.linq = frdl.require('typescript-dotnet-commonjs/System.Linq/Linq').Enumerable;
	 	    if(!!p)frdl.UI.progress().complete();	 		
 	 	});
 	  },10); 	
	 }
 
	 
   	  	},10); 
   	  },10);
   },10);	 
	 	
	THAT.preload = true; 		
 }
	
	
};
 
 
 
 var ql = new SQL();
 
 var _get = function(name, THAT){
 	 if(!THAT)var THAT = ql;
     for(var k in THAT){
          if(THAT[k][name]){
		  	return THAT[k][name];
		  }
     } 	 
       
       
    if(THAT[name]){
	   return THAT[name];
	}     
     
    return undefined; 
 };
 
 
 
 var engine = frdl.overload({
 	
 }, function(name, args){
    	if(1<frdl.debug.mode())console.log('resolve: webfan ql: ' + name /* + '(' + args.toString() + ')' */);
     
        var methodFn = _get(name, ql);
    	if('function'===typeof methodFn){
			return methodFn.apply(methodFn, args);
		}
		
			return frdl.when(function(ql)
				{
					if(true !== ql.preload && 'function' === typeof ql.preload){
						var fN = ql.preload;						
						try{
							fN.call(ql);
						}catch(err){
							console.warn(err);
						}
						ql.preload = true;
					}
					return ('function' === typeof _get(name, ql)) ? true : false;
				},
				function()
				{
					return methodFn.apply(_get(name, ql), args);
				},
				ql,
				function()
				{
					console.log('Failed to resolve webfan.ql.'+name+'('+JSON.stringify(args)+')');
				},
				30);
 });
 
 
 engine.__get = function(name){
  	if(1<frdl.debug.mode())console.log('webfan/ql.'+name);
 	load(ql);
    return _get(name, ql)
 };
 
 
 
 	Object.defineProperty(engine, 'Enumerables',
				{
				 'get':function()
					{
						load(ql, 'linq');
						return ql.LinqLib;
					},
					
				 'set':function(v)
					{
					   ql.LinqLib = v;
					}					
					
	});	 	
 
 	Object.defineProperty(engine, 'LinqLib',
				{
				 'get':function()
					{
						load(ql, 'linq');
						return ql.LinqLib;
					},
					
				 'set':function(v)
					{
					   ql.LinqLib = v;
					}					
					
	});	 	
 
 	Object.defineProperty(engine, 'linq',
				{
				 'get':function()
					{
						load(ql, 'linq');
						return ql.linq;
					},
					
				 'set':function(v)
					{
					   ql.linq = v;
					}					
					
	});	 	
 
 
 	Object.defineProperty(engine, 'sql',
				{
				 'get':function()
					{
						load(ql, 'sql');
						return ql.sql;
					},
					
				 'set':function(v)
					{
					   ql.sql = v;
					}					
					
	});	 	
 		
				
exports = module.exports = engine;			
//  exports =  engine;	
	
	/*	
 sqls = [
    //  "SELECT * FROM database1.user AS u WHERE u.name = 'bob' OR u.name = 'alice' GROUP BY u.season ORDER BY u.name ASC",
    //  "SELECT * FROM database1.user AS u ORDER BY u.name ASC LIMIT 0,2",
    //  "SELECT u.name FROM database1.user AS u JOIN database1.testuser AS t ON (u.name=t.name) WHERE type='b'",
    //  "SELECT DISTINCT u.name, t.age, u.money FROM database1.user AS u LEFT JOIN database1.testuser AS t ON (u.name=t.name) WHERE type='b' ORDER BY t.age DESC",
    TODO: "CREATE TABLE mytable (id int, title VARCHAR(256))"
    "CREATE TABLE mytable (id, title )"
  ];
  	
			
var testuser = {
	columns : [
    'id', 'name' , 'type', 'age', 'gender'
  ],
  
  data : [
    ['00', 'alice', 'a', 18, 'male'   ],
    ['01', 'bob',   'b', 18, 'female' ],
    ['02', 'edward','a', 13, 'male'   ],
    ['03', 'selly', 'c', 18, 'female' ],
    ['04', 'miller','a', 12, 'male'   ],
    ['05', 'alice', 'd', 18, 'male'   ],
    ['06', 'edward','a', 12, 'female' ],
    ['07', 'alice', 'e', 18, 'male'   ],
    ['08', 'kenney','a', 12, 'female' ],
    ['09', 'kobe',  'e', 28, 'male'   ],
    ['10', 'kikyou','a', 12, 'female' ],
    ['11', 'onesa',  'e', 28, 'male'  ]
  ]
};
	
var user = {
  columns :  [
    'name' , 'type', 'id', 'season', 'money'
  ],
  data  : [
    ['edward', 'a', 1, 'spring', 100],
    ['bob',    'b', 2, 'spring', 100],
    ['alice',  'b', 3, 'spring', 120],
    ['selly',  'b', 4, 'spring', 120],
    ['kikyou', 'c', 5, 'summer', 220],
    ['kobe',   'c', 6, 'summer', 320],
    ['onesa',  'd', 8, 'summer', 320],
    ['miller', 'd', 9, 'summer', 320]
  ]
};	
	
*/
(function(ql){
var SQLStorage = {
	
	/*
	database1 : {
		user : user,
		testuser : testuser
	}
	*/	
};
var TDriver = function(){
	this.constructor(Array.prototype.slice.call(arguments)[0]);
};
TDriver.prototype.constructor = function(opts){
	this.opts = opts;
	this.name = this.opts.name  = this.opts.name || 'custom frdl.sql TDriver ' + frdl.Guid.newGuid();
	this.hooks = this.opts.hooks  = this.opts.hooks || {};
};
var ___loaded = false;
var ___selected_db = false;
var ___connected = false;
var drivers = [];    
function hook(name, args, storage){
  var _driver, _drivers = Array.prototype.slice.call(drivers);
  while(0<_drivers.length){
  	 _driver = _drivers.shift();
  	 if('function' === typeof _driver.hooks[name]){
	 	 _driver.hooks[name].apply(storage, args);
	 }
  }	
}
function query(str, cb, _dc) {
  var result, Resource = _dc;
  try {
  
	
  var ast = ql.sql.Parser.parse(str);
  var ar  = new ql.sql.AstReader(ast);
  // hook('query', [str, ar], Resource);
/*
  var DB = ar.getDB();	 
  var table = ar.getTableOrig();
  var tableAlias = ar.getTableAlias();
  var type = ar.getType();
  */
  
 // console.dir(ar.getAst());
    	
  	
    result = ql.sql.Executor.doPostFilter(Resource, ar, ql.sql.Context.getctx()) /*runAST(ar.getAst(), nQuery.Context.get(), cb)*/ /* run(str) */; 
  } catch (e) {
    cb(e);
    return;
  }
  
  // get info..._()
  var info = {
  	
  };
  cb(null, frdl.clone(result), info);
}
function loadSQL(ar, ctx, cb) {
	 
  ql.sql.Context.setctx(ctx);
  
  var ast = ar.getAst();
  var str = ql.sql.Adapter.toSQL(ast, ctx);
 
  query(str, function(err, dc, info) {   
     cb(err, dc);
   }, SQLStorage);
}
function driver(opts){
	return new TDriver(opts);
}
function close() {
   SQLStorage = {}; 
   ___connected=false;
}
// ql.sql.Context.setctx(SQLStorage);
function connect(driver, callback, columns, _keys, defData, timeout) {
load(ql, 'sql');	
if(!___loaded){
ql.sql.Executor.setLoader(loadSQL); 
    ___loaded = true;
    require('16:webfan/webfat/js/ql-engine', function(Engine){
        connect(ql.driver(Engine));
    });
      // connect(ql.helper.driver(require('16:webfan/webfat/js/ql-engine')));
    return connect.apply(ql, Array.prototype.slice.call(arguments));  
}
if(!!___connected && 0 === Array.prototype.slice.call(arguments).length){
	return true;
}
 try {	
 
 	
 if(true === driver instanceof TDriver){
     if(-1===drivers.indexOf(driver)){
	 	drivers.push(driver);
	 }else{
	 	if(0<frdl.debug.mode())console.warn('sql driver already installed');
	 }
 }else if('object'===typeof driver && null !== driver){
        _join_storage(SQLStorage, driver);
 }else if('string' === typeof driver && Array.isArray(columns) && 2 === frdl.explode('.', driver).length){
 	preloadFromFilesystem(driver, columns, _keys, defData, timeout);
 }
 
 
  ___connected = true; 
  if('function'===typeof callback)callback(false, drivers);
  
  
 } catch (e) {
 	___connected = false; 
    if('function'===typeof callback)callback(e);
    console.error(e);
    frdl.alert.error(e);
 }   
 	
 return ___connected; 
}
function select_db(db, callback) {
load(ql, 'sql');	
 if('undefined' !== typeof SQLStorage[db]){
 	___selected_db = db;
 	ql.sql.Context.setctx(SQLStorage[___selected_db]);
	if('function'===typeof callback)callback(false, SQLStorage[___selected_db]);
 }else{
	if('function'===typeof callback)callback('sql error: cannot select db ' + db);
 }	
}
   
   
   
   
   
function _join_table(a, b){
  var i;
  if('undefined'!==typeof b.KEYINDEX)a.KEYINDEX = b.KEYINDEX;
  for(i=0;i<b.columns.length;i++){
  	 if(-1===a.columns.indexOf(b.columns[i])){
  	 	a.columns.push(b.columns[i]);
  	 }
  }	
}
function _join_storage(a, b){
	var db, table;
 for(db in b){
 	if('undefined'===typeof a[db]){
		a[db]=b[db];
	}else{
		for(table in b[db]){
			if('undefined'===typeof a[db][table]){
				a[db][table]=b[db][table];
			}else{
				_join_table(a[db][table], b[db][table]);
			}
		}
	}
 }	
	
}
function fetch_row(result){
	if(result.columns && result.data){
		if(!result.stream){
			result.stream = {
			    d : 'ltr',
			    data : []	
			};
		}
		if('ltr' === result.stream.d){
			if(0<result.data.length){
				var row = result.data.shift();
				result.stream.data.push(row);
				return row;
			}else{
				result.stream.d = 'rtl';
				//var r = result.stream.data.shift();
				//result.data.push(r);
				//return r;	
				return false;			
			}
		}else if('rtl' === result.stream.d){
			if(0<result.stream.data.length){
				var row = result.stream.data.shift();
				result.data.push(row);
				return row;
			}else{
				result.stream.d = 'ltr';
				result.stream = undefined;
				return false;				
			}			
		}
	}else{
	   return false;
    }
}
function fetch_object(result){
	if(result.columns && result.data){
		if(!result.stream){
			result.stream = {
			    d : 'ltr',
			    data : []	
			};
		}
		if('ltr' === result.stream.d){
			if(0<result.data.length){
				var row = result.data.shift();
				result.stream.data.push(row);
				var r = {};
				frdl.each(result.columns, function(i, col){
				   r[col] = row[i];
				});
				return r;
			}else{
				result.stream.d = 'rtl';
				return false;			
			}
		}else if('rtl' === result.stream.d){
			if(0<result.stream.data.length){
				var row = result.stream.data.shift();
				result.data.push(row);
				var r = {};
				frdl.each(result.columns, function(i, col){
				   r[col] = row[i];
				});
				return r;			
			}else{
				result.stream.d = 'ltr';
				result.stream = undefined;
				return false;				
			}			
		}
	}else{
	   return false;
    }
}
   
   
function doQuery(sql, callback) {
 load(ql, 'sql');
 return new Promise(function(resolve, reject){
 if(!___connected){
   ql.connect();
   /*
   var sql_def = "CREATE DATABASE public_, private_";
   return doQuery(sql_def, function(err, dc) {
     if (err) {
      console.warn(err);
    } else {
      if(1<frdl.debug.mode())console.log('sql : CREATE DEFAULT DB' + sql_def);
      if(1<frdl.debug.mode())console.dir(dc);
      ql.select_db('usr_web_0', function(err, db){
      	  if(err){
		  	console.error(err);
		  	return;
		  }
		  if(1<frdl.debug.mode())console.log('sql : select_db ' + 'usr_web_0');
		  if(1<frdl.debug.mode())console.dir(db);
      });
    }  	
      resolve(doQuery(sql, callback));
   });
   */
 } 	
 
 var words = sql.split(/\s/);
 var words2 = Array.prototype.slice.call(words);
 words2.shift();
 var cmd = words[0];
 var cmd_lc = cmd.toLowerCase();
 
 var _transaction = 0;
 var _t_history=[];
 	
   var sqlStartFn = {};
   
  
   
   
    sqlStartFn['alter'] = function(sQL, words, words2){
    	if('table'===words2[0].toLowerCase()){
	  	   hook('alter table', Array.prototype.slice.call(arguments), SQLStorage);
	  	   resolve(true);
	  	}  
	  	
	  	if('function'===typeof callback)callback(false, SQLStorage);
    };	
    
   
    sqlStartFn['delete'] = function(sQL, words, words2){
	  	   hook('delete', Array.prototype.slice.call(arguments), SQLStorage);
	  	   resolve(true);
	  	   if('function'===typeof callback)callback(false, SQLStorage);
    };	
    
        
     sqlStartFn['begin'] = function(){
     	   ++_transaction;
     	   _t_history.push(frdl.clone(SQLStorage));
	  	   hook('begin', [_t_history[_t_history.length-1], _transaction], SQLStorage);
	  	   resolve(true);
     };	  
     
      sqlStartFn['commit'] = function(){
      	    --_transaction;
	  	   hook('commit', [_t_history.pop(), _transaction], SQLStorage);
	  	   if(0>=_transaction){
		   	 hook('commit final', [_t_history.pop(), _transaction], SQLStorage);
		   	 _transaction=0;
		   }
	  	   resolve(true);
     };	  
      
      sqlStartFn['rollback'] = function(){
      	   SQLStorage = _t_history.pop();
      	    --_transaction;
      	   hook('rollback', [SQLStorage, _transaction], SQLStorage);
	  	   resolve(true);
     };	  
     
     
   sqlStartFn['create'] = function(sQL, words, words2){
   	
   	   
   	  if('database'===words2[0].toLowerCase()){
   	  	   
   	  	   var toks = Array.prototype.slice.call(words2);
	  	   toks.shift();
	  	   var errs = [];
	  	   var dbs = [];
	  	   frdl.each(toks, function(i, w){
		  	   frdl.each(frdl.explode(',',w), function(j, t){
	  	   	       t = t.trim();
	  	   	       if(''===t)return true;
	  	   	       if('undefined' === typeof SQLStorage[t]){
				   	  SQLStorage[t] = {};
				   	  dbs.push(SQLStorage[t]);
				   	  try{
					  	 hook('create database', [t], SQLStorage);  
					  }catch(err){
					  	 errs.push(err);
					  }
				   	 
				    }else{
				   //	  errs.push('Database '+t+' already exists');
				    }
	  	       });  	   	      
	  	   });
	  	   
	  	   if(0===errs.length){
		   	 if('function'===typeof callback)callback(false, dbs);
		   	 resolve(dbs);
		   	 if('function'===typeof callback)callback(false, dbs);
		   }else{
		   	 if('function'===typeof callback)callback(errs);
		   	 try{
			 	reject(errs.join('\n'));
			    console.warn(errs.join('\n'));
			 }catch(err){
			 	console.warn(err);
			 	reject(err);
			 }
		   	 
		   }
	  	   
	  	
	  	 
	  }else if('table'===words2[0].toLowerCase()){
	  	//   hook('create table', Array.prototype.slice.call(arguments), SQLStorage);
	  	  var ifNotExists =  frdl.strpos(frdl.str_replace('if not exists', 'IF NOT EXISTS',sQL), 'IF NOT EXISTS');
          var words = frdl.str_replace('IF NOT EXISTS', '',sQL).split(/\s/);
          var words2 = Array.prototype.slice.call(words);
          words2.shift();
 	  	  if(false!==ifNotExists){
		  	words2.shift();
		  }
		  
		  	  
   	  	   var toks = Array.prototype.slice.call(words2);
   	  	   toks.shift();
	  	   var table = toks.shift();
	  	   var columns = [];
	  	   frdl.each(toks, function(i, w){
	  	   	   w = frdl.str_replace('(', ' (', w)
		  	   frdl.each(frdl.explode(',',w), function(j, t){
	  	   	       t = t.trim();
	  	   	       t = frdl.str_replace('(', '', t);
	  	   	       t = frdl.str_replace(')', '', t);
	  	   	       if(''===t)return true;
	  	   	       columns.push(t);
	  	       });  	   	      
	  	   });
	  	   
	  	   var t = frdl.explode('.',table);
	  	   if(1===t.length){
		   	  var db = ___selected_db;
		   	  var table = t[0].trim();
		   }else{
		   	  var db = t[0].trim();
		   	  var table = t[1].trim(); 
		   }
	  	   if(!db)db=___selected_db;
  	   
  	   
	  	   var _createTable = function(){
	  	   	 var Table = require('nquery/forked-frdl-1/lib/table'); 
	  	     
	  	    
	  	   	 
		   	 if('undefined' === typeof SQLStorage[db][table]){
		   	 	SQLStorage[db][table] = {
					columns : columns,
					data : []
				};
				  var tbl = new Table(SQLStorage[db][table]);
                  tbl = tbl.get(table); 
                try{
					 hook('create table', [db, table, columns], SQLStorage); 	  
				}  catch(err){
					
				}
                 
                  
				if('function'===typeof callback)callback(false, tbl);
			    resolve(tbl);
			    if('function'===typeof callback)callback(false, tbl);
		   	 }else{
		   	 if('function'===typeof callback)callback('TABLE \''+table+'\' already exists');
		   	   	
		   	 	
		   	  if(false!==ifNotExists){
			  	
			/*  
			   frdl.alert.confirm('<span flow-inx-args="[\''+table+'\']">Table %s already exists, do you like to merge it with your query</span>?', function (e) {
                if (e) {
                   SQLStorage[db][table].columns = $.extend(SQLStorage[db][table].columns, columns); 
				    var tbl = new Table(SQLStorage[db][table]);
                    tbl = tbl.get(table);                   
                   resolve(tbl);
			       if('function'===typeof callback)callback(false, tbl);
                } else {
                   if('function'===typeof callback)callback('CREATE TABLE \''+table+'\' canceled'); 
                   reject('CREATE TABLE \''+table+'\' canceled');
                }
                
                 });
                 */
            
  			   	//  if('function'===typeof callback)callback('TABLE \''+table+'\' already exists');
			   	 // reject('TABLE \''+table+'\' already exists');
			   	     if('function'===typeof callback)callback(false, false);  
			   	     resolve('TABLE \''+table+'\' already exists');          
               }else{
                 //  SQLStorage[db][table].columns = $.extend(SQLStorage[db][table].columns, columns); 
				  //  var tbl = new Table(SQLStorage[db][table]);
                 //   tbl = tbl.get(table);                   
                 //  resolve(tbl);
			    //   if('function'===typeof callback)callback(false, tbl); 
			    	  if('function'===typeof callback)callback('TABLE \''+table+'\' already exists');
			   	      reject('TABLE \''+table+'\' already exists');    
			   }
			   	
              frdl.translate();
              frdl.inX.translate();	 	
			 }
		   };
		   
	  	   var _creatDb = function(){
		   	  SQLStorage[db] = {};
		   	  _createTable();
		   };	
		   		   
		   if('undefined' === typeof SQLStorage[db]){
		   	
		    	//	if(false===ifNotExists){
			 	//	
			
		   	 	//   frdl.alert.confirm('<span flow-inx-args="[\''+db+'\']">Database %s does not exist, do you like to create it now</span>?', function (e) {
             	//    if (e) {
             	//        _creatDb();
             	//    } else {
              	//       
              	//   }
             	// });
             	// }else{
			 	reject('Database  \''+db+'\' does not exist');
			    if('function'===typeof callback)callback('Database  \''+db+'\' does not exist'); 
			 	// }
             
              frdl.translate();
              frdl.inX.translate();		 
		   }else{
		   	  _createTable();
		   }
		   
		   
         
	  }
   	  
   	//  console.log('Test create...');
   };
	
   if('function'===typeof sqlStartFn[cmd_lc] )	{
   	   return sqlStartFn[cmd_lc].apply(this, [sql, words, words2]);
   	   //sqlStartFn[cmd_lc].apply(this, [sql, words, words2]);
   }
	
   ql.sql.Query.runSQL(sql, function(err, dc) {
    if (err) {
      console.error(err);
      if('function'===typeof callback)callback(err);
      reject(err);
    } else {
      if(1<frdl.debug.mode())console.log('sql :');
      if(1<frdl.debug.mode())console.log('' + sql);
      if(1<frdl.debug.mode())console.log('\ndata:');
      if(1<frdl.debug.mode())console.dir(dc);
      if('function'===typeof callback)callback(false, dc);
      resolve(dc);
    }
  });
  
 });	 
} 
/**
       while((row = frdl.sql.fetch_row(result)) && false !== row){
	   	 console.dir(row);
	   }
*/	
ql.fetch_row = fetch_row;
ql.fetch_object = fetch_object;
/**
ql.helper = {
  	driver : driver,
  	join_storage : _join_storage,
  	join_table : _join_table,
  	hook : hook
};
*/
  	ql.driver = driver;
  	ql.join_storage = _join_storage;
  	ql.join_table = _join_table;
  	ql.hook = hook;
ql.close = close;	
ql.connect = connect;	
ql.select_db = select_db;	
ql.query = doQuery;	
if(!!Proxy.isPolyfile){
	var _k;
	for(_k in ql){
		engine[_k]=ql[_k];
	}
	// load(ql); 
	try{	
	  webfan.$Async(function(){
	  	   ql.preload();
	  },1);
 	 	
	}catch(err){
		  console.warn(err);	
	}
	
}
window.addEventListener("beforeunload", function() {
	try{
         ql.query('commit');
	}catch(err){
		
	}
}, true);
window.addEventListener("reload", function() {
	try{
         ql.query('commit');
	}catch(err){
		
	}
}, true);
}(ql));					
 |