Project

General

Profile

1
<?php
2

    
3
require_once($help_functions);
4
require_once($model_logger.'/Logger.php');
5
Logger::configure($model_logger.'/log4php.xml');
6
require_once("paths.php");
7
require "./predis/autoload.php";
8

    
9
class MYDB {
10

    
11
	private $db;
12
	public  $stmts = array();
13
	private $schema;
14
	private $facts = array();
15
	private $metadata = array();
16
	private $dimensions = array();
17
	private $log;
18
	private $local_log = array();
19
	private $schema_file;
20
	
21
	private $cache = null; 
22

    
23
//-------------------------------------------------------------------------------------\\
24
//-------------------------------------------------------------------------------------\\
25
//------------------------------CONSTRUCT, SET UP AND FUNCTION-------------------------\\
26
//-------------------------------------------------------------------------------------\\
27
//-------------------------------------------------------------------------------------\\
28
	function __construct() {
29
	
30
		global $redis_host;
31
		global $redis_port;
32
		global $redis_scheme;
33
		
34
		// this creates a logger named "MYDB" 
35
		$this->log = Logger::getLogger(__CLASS__);
36
		
37
		if(class_exists("Predis\Client")){
38
		
39
			try {
40
				
41
				Predis\Autoloader::register();
42
				$this->cache = new Predis\Client(array( 
43
					"scheme" => $redis_scheme,
44
					"host" => $redis_host,
45
        			"port" => $redis_port,
46
					"persistent" => 1,
47
					"read_write_timeout" => 0));
48
        			
49
        		$this->cache->connect(); 
50

    
51
				$this->log->info("redis host: ".$redis_host);
52
				$this->log->info("redis port: ".$redis_port);
53
				
54
			} catch(Exception $e) {
55
				$this->log->error("Error connecting to Redis server: ".$e->getMessage());
56
				$this->cache = null; 
57
			}
58
			
59
		} else {
60
			$this->log->info("Class Predis does not exist\n");
61
		}
62
	}
63

    
64
	// initialises the arrays containing the warehouse schema, via an xml that describes them 
65
	//TODO: insert checks on whether the data in the xml are correct (get schema from db)
66
	function loadSchema($file = null) {
67
		if(file_exists($file)) {
68
			$json = file_get_contents($file);
69
			//$this->log->info('schema of database: '.json_encode((array) simplexml_load_string($json)));
70
			$this->schema = json_decode(json_encode((array) simplexml_load_string($json)),1);
71
		}
72
		else {
73
			echo "loadSchema: could not find the xml";
74
			$this->log->error('loadSchema: could not find the xml');
75
			return -1;
76
		}
77
		foreach ($this->schema['table'] as $table) {
78
			switch ($table['type']) {
79
				case 'fact': array_push($this->facts,$table);
80
					break;
81
				//case 'm': array_push($this->metadata,$table);
82
				//	break;
83
				default: array_push($this->dimensions,$table);
84
					break;
85
			}
86
		}
87
		$this->log->info("loaded schema");
88
	}
89

    
90

    
91
	function doConnect($file) {
92
		try {
93
			switch($GLOBALS['type']){
94
				case 'postgres':
95
					$this->db = new PDO('pgsql:host='.$GLOBALS['host'].';port=5432;dbname='.$GLOBALS['db_name'].';user='.$GLOBALS['username'].';password='.$GLOBALS['password']);
96
					break;
97
				case 'sqlite':
98
					$this->db = new PDO('sqlite:'.$GLOBALS['head'].$GLOBALS['db_name']);
99
					break;
100
				default:
101
					echo "not known database type\n";
102
					break;
103
			}
104
		} catch(Exception $e){
105
			echo "oops..".$e->getMessage()."\n"; 
106
			$this->log->fatal($e->getMessage());
107
			return false;
108
		}
109
		$this->schema_file = $file;
110
		$this->loadSchema($file);
111
	}
112

    
113
	function doDisconnect($save = false) {
114
		if($save) {
115
			$fp = fopen($this->schema_file,"w");
116
			$data = "<schema>\n".toxml($this->schema,"schema",1)."\n</schema>\n";
117
			fwrite($fp,$data);
118
			fclose($fp);
119
		}
120
		$this->db = null;
121
	}
122

    
123
	function beginTrans() {
124
		$this->db->beginTransaction();
125
	}
126
	
127
	function doCommit() {
128
		$this->db->commit();
129
	}
130

    
131
	function doQuery($query, $fetchMode=PDO::FETCH_BOTH){
132
	
133
		if($this->cache != null){
134
		
135
			$myKey = md5($query);
136
			$this->log->debug("Searching for key: ".$myKey);
137
				
138
			if($this->cache->exists($myKey)) { 
139
			
140
				$results = $this->cache->hget($myKey, "results");
141
				return json_decode($results, true);
142
				
143
			} else {
144
			
145
				$this->log->debug("not found in cache"); 
146
				$results = $this->doQueryNoCache($query, $fetchMode);
147
				$this->log->info("adding in cache. key: ".$myKey); 
148
				
149
				if(isset($_GET['persistent']))
150
  					$persistent = $_GET['persistent'];
151
				else
152
  					$persistent = true; //default value is true if not provided
153
  
154
  				if(($this->cache->hmset($myKey, array("query" => $query, "results" => json_encode($results), "persistent" => $persistent, "fetchMode" => $fetchMode))) == false) {
155
  					$this->log->info("adding key ".$myKey." in cache failed."); //predis
156
  				} else {
157
  					$this->cache->save();
158
  				}
159
  				return $results;
160
			}
161
		} else {
162
			return $this->doQueryNoCache($query, $fetchMode);
163
		}
164
	}
165

    
166
	function doQueryNoCache($query, $fetchMode=PDO::FETCH_BOTH) {
167
	
168
		$stmt = $this->db->query($query); 
169
		if(!$stmt){
170
			$arr = $this->db->errorInfo();
171
			$this->log->error($arr[2]);
172
			return null;
173
		}
174
		return $stmt->fetchAll($fetchMode);
175
	}
176

    
177
	function doPrepare($query){
178
		$stmt = $this->db->prepare($query);
179
		if(!$stmt){
180
			$arr = $this->db->errorInfo();
181
			$this->log->error($arr[0]." ".$arr[1]." ".$arr[2]);
182
			return false;
183
		}
184
		return $stmt;
185
	}
186

    
187
	function doExecute($stmt){
188
		if(!$stmt->execute()){
189
			$arr = $stmt->errorInfo();
190
			$this->log->error($arr[2]);
191
			return false;
192
		}
193
		return $stmt;
194
	}
195

    
196
//-------------------------------------------------------------------------------------\\
197
//-------------------------------------------------------------------------------------\\
198
//------------------------------CHECKS, GETTERS, SETTERS-------------------------------\\
199
//-------------------------------------------------------------------------------------\\
200
//-------------------------------------------------------------------------------------\\
201

    
202
	public function printSchema() {
203
		print_r($this->schema);
204
	}
205

    
206
	public function getSchema() {
207
		if(isset($this->schema))
208
			return $this->schema;
209
		return null;
210
	}
211

    
212
	public function getFacts() {
213
		$list = $this->doQuery("select tableName from defaults order by tableorder");
214
		if($list != null){
215
			$sorted = array();
216
			if(isset($this->facts)) {
217
				for($i=0;$i<count($list);$i++) {
218
					foreach($this->facts as $fact){
219
						if($fact['name'] == $list[$i][0]){
220
							$sorted[] = $fact;
221
							break;
222
						}
223
					}
224
				}
225
				return $sorted;
226
			}
227
		}
228
		else
229
			return $this->facts;
230
	}
231

    
232
	public function getDimensions() { 
233
		if(isset($this->dimensions)) {
234
			return $this->dimensions;
235
		}
236
		return null;
237
	}
238

    
239
	public function getFactsNames() {
240
		$names = array();
241
		if(isset($this->facts)) {
242
			foreach($this->facts as $fact) {
243
				array_push($names,$fact['name']);
244
			}
245
			return $names;
246
		}
247
		return null;
248
	}
249

    
250
	function getType($oldType) {
251
		switch ($oldType) {
252
			case 'int':
253
			case 'double':
254
				return 'number';
255
				break;
256
			case 'varchar':
257
			case 'datetime':
258
				return 'string';
259
				break;
260
			case 'bool':
261
				return 'boolean';
262
				break;
263
			default:
264
				return false;
265
		}
266
	}	
267

    
268
	/*returns an array with the triplet (name,type,view) for each of the keys of the dimension table 
269
	or false on failure
270
	type is either number, string or boolean //? need to add more ?*/
271
	function findKeys($table) {
272
		$myarray = array();
273
		if($table == false) {
274
			$this->log->error('findKeys: no table indicated');
275
			return false;
276
		}
277
		if(is_array($table['key'])) {
278
			foreach($table['key'] as $key) {
279
				$keyInfo = $this->findOneField($table,$key,'attrib');
280
				array_push($myarray,$keyInfo);
281
			}
282
		}
283
		else {
284
			$keyInfo = $this->findOneField($table,$table['key'],'attrib');
285
			array_push($myarray,$keyInfo);
286
		}
287
		return $myarray;
288
	}
289

    
290
	//returns an array with the tetraplet (name,type,view,data) for each of the meas of the fact table or false on failure
291
	//type is either number, string or boolean //? need to add more ?
292
	function findMeas($table) {
293
		$myarray = array();
294
		if($table == false) {
295
			$this->log->error('findMeas: no table indicated');
296
			return false;
297
		}
298
		if(isset($table['meas'][0])) {
299
			foreach($table['meas'] as $meas) {
300
				if(isset($meas['view'])) {
301
					$view = $meas['view'];
302
				}
303
				else
304
					$view = $meas['name'];
305
				array_push($myarray,array($meas['name'],$view,$meas['type'],$meas['data']));
306
			}
307
		}
308
		else {
309
			if(isset($table['meas']['view'])) {
310
				$view = $meas['view'];
311
			}
312
			else
313
				$view = $meas['name'];
314
			array_push($myarray,array($meas['name'],$view,$meas['type'],$meas['data']));
315
		}
316
		return $myarray;
317
	}
318

    
319
	function getDims() {
320
		return $this->dimensions;
321
	}
322

    
323
	function findOneField($table,$name,$ftype) {
324
		$field = search($table[$ftype],'name',$name);
325
		if(count($field)!=1) {
326
			$this->log->error('error in xml');
327
			return false;
328
		}
329
	
330
		$type = $this->getType($field[0]['type']); 
331

    
332
		if(isset($field[0]['view'])) {
333
			$view = $field[0]['view'];
334
		}
335
		else 
336
			$view = $field[0]['name'];
337
	
338
		return array($field[0]['name'],$type,$view,$field[0]['data']);
339

    
340
	}
341

    
342
	function getField($table,$name,$ftype) {
343
		$field = search($table[$ftype],'name',$name);
344
		if(count($field)!=1) {
345
			$this->log->error('error in xml');
346
			return false;
347
		}
348
	
349
		return $field[0];
350
	}
351

    
352
	function findTable($name,$type) {
353
		if($type == 'dimension') {
354
			$all_matching_files = search($this->dimensions,'name',$name); 
355
		}
356
		elseif($type == 'fact') {
357
			$all_matching_files = search($this->facts,'name',$name);
358
		}
359
		else {
360
			$this->log->error('findTable: could not recognise type '.$type);
361
			return false;
362
   		}
363
		if(count($all_matching_files)==0) {
364
			$this->log->error('xml file error: table: '.$name.' not found');
365
			return false;
366
		}
367
		$matching_files = search($all_matching_files,'type',$type);
368
		if(count($matching_files)!=1) {
369
			$this->log->error('multiple '.$type.'s with name: '.$name);
370
			return false;
371
		}
372
		return $matching_files[0];
373
		
374
	}
375

    
376
	//checks if a fact table with exactly the given dimensions exist
377
	function searchWarehousebyDims($dims) {
378
		$flag = false;
379
		
380
		foreach($this->facts as $warehouse) {
381
			
382
			//if the number of dims is the same as the given and every dim in the list exists in the given then return the warehouse name
383
			if(count($warehouse['dim']) != count($dims)){
384
				continue;
385
			}
386
			foreach($dims as $dim) {
387
				$res = search($warehouse['dim'], 'name', $dim);
388
				if(count($res) != 0) {
389
					$flag = true;
390
				}
391
				else {
392
					$flag = false;
393
					break;
394
				}
395
			}
396
			if($flag == true)
397
				return $warehouse['name'];
398
		}
399
		//not found
400
		return false;
401
	}
402

    
403
	/*check if a name is already in use for a fact table
404
	if yes, return false, otherwise, return true*/
405
	function checkName($name) {
406
		if(findTable($name,"fact") != false) {
407
			return true;
408
		}
409
		return false;
410
	}
411

    
412
	/*check if a name is already in use for a dimension table
413
	 if yes, return true, otherwise, return false*/
414
	function checkDim($name) {
415
		if(findTable($name,"dimension") != false) {
416
			return true;
417
		}
418
		return false;
419
	}
420

    
421
	function findTableType($name) {
422
		if($this->findTable($name,"dimension") != false) {
423
			return "dimension";
424
		}
425
		if($this->findTable($name,"fact") != false) {
426
			return "fact";
427
		} 
428
		return false;
429
	}
430

    
431
	/*check if a list of dims all exist in the schema
432
		returns a list with all dims that don't exist or true
433
	*/
434
	function checkListofDims($dims) {
435
		$non_existent = array();
436
		$flag = true;
437
		foreach($dims as $dim) {
438
			if(checkDim($dim) == true){
439
				array_push($non_existent,$dim);
440
				$flag = false;
441
			}
442
		}
443
		if($flag == true)
444
			return true;
445
		else
446
			return $non_existent;
447
	}
448

    
449
	function checkMeas($fact, $meas_name) {
450
		//find the fact table
451
		//if there is a meas with the same name
452
		foreach($this->facts as $table)
453
			if($table['name'] == $fact)
454
				foreach($table['meas'] as $meas) {
455
					if($meas['name'] == $meas_name){
456
						return true;
457
					}
458
				}
459
			return false;
460
	}
461

    
462
	function getAllDims() {
463
		$dimnames = array();
464
		foreach($this->dimensions as $dim) {
465
			array_push($dimnames,$dim['name']);
466
		}
467
		return $dimnames;
468
	}
469

    
470
	function getDimsFieldsList($tableName) {
471
		$fields = array();
472
		//find the table
473
		$table = $this->findTable($tableName,'dimension');
474
		if($table == false) {
475
			return false;
476
		}
477
		foreach($table['attrib'] as $field) {
478
			if($field['name'] == 'id')
479
				continue;
480
			if(isset($field['analysed'])) {
481
				$fields = array_merge($fields,$this->getDimsFieldsList($field['analysed']));
482
			}
483
			else {
484
				if(isset($field['view']))
485
					$view = $field['view'];
486
				else 
487
					$view = $field['name'];
488
				array_push($fields,array($tableName.".".$field['name'],$tableName.".".$view,$field['type'],$field['data'])); 
489
			}
490
		}
491
		return $fields;
492
	}
493

    
494
	function getDimsList($tablename) {
495
		$fields = array();
496
		//find the factable
497
		$table = $this->findTable($tablename,'fact');
498
		if($table == false) {
499
			return false;
500
		}
501
		foreach($table['dim'] as $dim) {
502
			$temp = $this->getDimsFieldsList($dim['name']);
503
			$fields = array_merge($fields, $temp);
504
		}
505
		return $fields;
506
	}
507
	
508
	function getDimsKeys($dimName) {
509
		$table = $this->findTable($dimName,'dimension');
510
		if($table == false) {
511
			return false;
512
		}
513
		return $table['key'];
514
	}
515
  
516
//-------------------------------------------------------------------------------------\\
517
//-------------------------------------------------------------------------------------\\
518
//----------------------------------DATA READING---------------------------------------\\
519
//-------------------------------------------------------------------------------------\\
520
//-------------------------------------------------------------------------------------\\
521

    
522
function getMeasMetadata($table) {
523
	$query = 'select name, source, sourceUrl, definition, unit from Metadata where inTable="'.$table.'"';
524
	$this->log->info("getMeasMetadata -> generated query: ".$query);
525
	$res = $this->doQuery($query);
526
	if($res == null)
527
		return "false";
528
	
529
	return $res;
530
}
531

    
532
/*
533
gets the name of a fact table and the name of a measurement and returns the minimun, maximum and count distinct values for it
534
*/
535
function measRangeData($facttable, $measurement) {
536
	$query = "SELECT min($measurement), max($measurement), count(distinct $measurement) FROM $facttable WHERE $measurement != ''";
537
	$this->log->info("generated query: ".$query);
538
	$res = $this->doQuery($query);
539
	$res=$res[0];
540
	return array($res[0],$res[1],$res[2]);
541
}
542

    
543
//return the minimun, maximum
544
function getRangeData($table, $field) {
545
	$query = 'SELECT min("'.$field.'"), max("'.$field.'") FROM "'.$table.'"';
546
	if($GLOBALS['type'] == "sqlite")
547
		$query .= ' WHERE "'.$field.'" != ""';
548
	$this->log->info("generated query: ".$query);
549
	$res = $this->doQuery($query);
550
	$res = $res[0];
551
	return array("min"=>$res[0],"max"=>$res[1]);
552
}
553

    
554
//return the distinct values
555
function getDistinctValues($table, $field) {
556
	$query = 'select distinct "'.$field.'" from "'.$table.'" order by "'.$field.'"';
557
	$this->log->info("generated query: ".$query);
558
	$res = $this->doQuery($query, PDO::FETCH_NUM);
559
	return $res;
560
}
561

    
562
function getFilterData($table,$field){
563
	$flag = false;
564
	$myDimTable = $this->findTable($table,'dimension');
565
	$myFactTable = $this->findTable($table,'fact');
566
	//is it a dim?
567
	if($myDimTable != false){
568
		//does it have the field?
569
		if(!isAssoc($myDimTable['attrib'])){
570
			foreach($myDimTable['attrib'] as $attrib){
571
				if($attrib['name'] == $field){
572
					$myField = $attrib;
573
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
574
				}
575
			}
576
		}
577
		else{
578
			if($myDimTable['attrib']['name'] == $field){
579
				$myField = $myDimTable['attrib'];
580
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
581
			}
582
		}
583
	}
584
	if($myFactTable != false){
585
		//look in the dims
586
		if(!isAssoc($myFactTable['dim'])){
587
			foreach($myFactTable['dim'] as $dim) {
588
				if($dim['name'] == $field){
589
					$myField = $dim;
590
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
591
				}
592
			}
593
		}
594
		else{
595
			if($myFactTable['dim']['name'] == $field){
596
				$myField = $myFactTable['dim'];
597
				//$flag = true;
598
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
599
			}
600
		}
601
		if(!isAssoc($myFactTable['meas'])){
602
			foreach($myFactTable['meas'] as $meas) {
603
				if($meas['name'] == $field){
604
					$myField = $meas;
605
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
606
				}
607
			}
608
		}
609
		else{
610
			if($myFactTable['meas']['name'] == $field){
611
				$myField = $myFactTable['meas'];
612
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
613
			}
614
		}
615
		$this->log->error('cannot find field '.$field.' in table '.$table);
616
		return "cannot find field ".$field;
617
	}
618

    
619
	$this->log->error("cannot find table ".$table);
620
	return "cannot find table ".$table;
621
}
622
	
623
	function getDefaultData($table) {
624
		$this->log->info("DefaultData -> table:".$table);
625
		if($table !=null && $table!='null') {
626
			$query = 'select * from "defaults" where tablename='."'".$table."'";
627
		}
628
		else{
629
			$query = 'select * from "defaults" where tableorder=(select min(tableorder) from "defaults")';
630
		}
631
		$this->log->info("DefaultData -> query created: ".$query);
632
		$res = $this->doQuery($query);
633
		if($res == null)
634
			return "empty";
635

    
636
		$selectedData = array();
637
		$selectedData['table'] = $res[0][0];
638
		$selectedData['fields'] = array();
639
		$selectedData['fields'][0] = array();
640
		$selectedData['fields'][0]['fld'] = $res[0][2];
641
		$selectedData['fields'][0]['agg'] = $res[0][3];
642
		$selectedData['fields'][0]['id'] = 0;
643
		$selectedData['fields'][0]['type'] = "";
644
		$selectedData['fields'][0]['yaxis'] = 1;
645
		$selectedData['xaxis']['name'] = $res[0][1];
646
		$selectedData['xaxis']['agg'] = 'avg';
647
		$selectedData['group'] = '';
648
		$selectedData['color'] = '';
649
		if($this->checkMeas($selectedData['table'], $selectedData['xaxis']['name'])){
650
			$type='scatter';
651
			$selectedData['type'] = 'scatter';
652
		}
653
		else{
654
			$selectedData['type'] = 'chart';
655
			$type = $res[0][5];
656
		}
657
		$selectedData['size'] = $GLOBALS['size'];
658
		return array('selectedData'=>$selectedData,'type'=>$type);
659
		//return array('selectedData'=>$selectedData, 'data'=>$this->getData($selectedData),'type'=>$type);
660
	}
661

    
662
/*
663
domi tou selectedData:
664
['table'] = fact table name
665
['fields'] = [{'fld':field name,'agg':aggregator for the field,'id': de mas noiazei}, ...]
666
['series'] = [dim field name with the list of the dim tables names that lead to it (eg: Product-Supplier-sup_name), ...]
667
['group'] = dim field name with the list of the dim tables names that lead to it (eg: Product-Supplier-sup_name) <---will have to group by it and have a series for each value of it 
668
['xaxis'] = {'name': to onoma tou dim h meas pou paei ston x axis, 'agg': o aggregator an einai meas}
669
['type'](optional)
670
stin apli periptwsi to series einai panta keno
671
sto telos exoume tosa series osa fields (to poly 3)
672

    
673
an sto xaxis exoume meas tote exoume scatter plot kai den bazoume to xaxis sto group by
674
an den exoume series tote den exoume group by kai agnooume ta aggs
675
*/
676
/*
677
domi tou query:
678
ok	select: to xaxis me patera to akribws proigoumeno sto onoma AND ola ta fields me ta aggs tous AND ola ta series me patera to akribws proigoumeno sto onoma
679
ok	from: to table AND ola osa emfanizontai sto series kai to xaxis
680
	where: 1 zeygari gia kathe syndyasmo diplanwn pinakwn pou emfanizetai sto series kai twn arxikwn me to table 
681
	(eg: gia to Product-Supplier tha exoume ena zeygari to Product,Supplier kai ena to Facttable,Product)
682
ok	group by: to xaxis kai ola ta series opws akribws kai sto select
683
ok	order by: to xaxis 
684
*/
685
	function makeQueryGroup($sel){//print_r($sel);
686
		$this->log->info("makeQueryGroup");
687
		/*
688
		select agg(field), xaxisfield, groupfield
689
		from facttable, xaxistables, grouptables
690
		where facttable = xaxistables and xaxistables and facttable = groupstables and groupstables
691
		group by groupfield, xaxisfield (ektos ki an einai meas)
692
		order by groupfield, xaxisfield
693
		*/
694
		$isMeas = false;
695
		$field = "";
696
		$xaxisfield = "";
697
		$groupfield = "";
698
		$tables = array();
699
		$tablesPairs = array();
700
		$tables[] = $sel['table'];
701
		/*yaxis*/ //<---- panta measurement
702
		$field = '"'.$sel['fields'][0]['fld'].'"';
703
		/*xaxis*/ 
704
		$xaxislist = explode("-",$sel['xaxis']['name']);
705
		if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1])){
706
			$isMeas = true;
707
		}
708
		if(!$isMeas){
709
			//an den einai measurement tote einai dimension kai mporei na exei tables
710
			if(count($xaxislist) == 1){ //einai dim alla den analyetai se pinaka
711
				$xaxisfield = '"'.$sel['table'].'"."'.$xaxislist[count($xaxislist)-1].'"';
712
			}
713
			else{
714
				$xaxisfield = '"'.$xaxislist[count($xaxislist)-2].'"."'.$xaxislist[count($xaxislist)-1].'"';
715

    
716
				//briskw tous pinakes enan enan kai tous bazw sta pairs alla kai sto xaxistables
717
				for($i=0;$i<count($xaxislist)-1;$i++){
718
					if(!in_array($xaxislist[$i],$tables)){
719
						$tables[] = $xaxislist[$i];
720
					}
721
					if($i == count($xaxislist)-2){
722
						if(!in_array_r(array($sel['table'],$xaxislist[$i]), $tablesPairs)){
723
							$tablesPairs[] = array($sel['table'],$xaxislist[$i]);
724
						}
725
					}
726
					else{
727
						if(!in_array_r(array($xaxislist[$i],$xaxislist[$i+1]),$tablesPairs))
728
							$tablesPairs[] = array($xaxislist[$i],$xaxislist[$i+1]);
729
					}
730
				}
731
			}
732
		}
733
		else {
734
			//einai meas, den kanw tipota
735
			$xaxisfield = '"'.$sel['table'].'"."'.$sel['xaxis']['name'].'"';
736
			$xaxistables = null;
737
		}
738
		/*group*/
739
		//briskw tous pinakes tou group field kai tous bazw enan enan sto table alla kai sta pairs
740
		$grouplist = explode("-",$sel['group']);
741
		if(count($grouplist) == 1){ //einai dim alla den analyetai se pinaka
742
			$groupfield = '"'.$sel['table'].'"."'.$grouplist[count($grouplist)-1].'"';
743
		}
744
		else{
745
			$groupfield = '"'.$grouplist[count($grouplist)-2].'"."'.$grouplist[count($grouplist)-1].'"';
746
			//briskw tous pinakes enan enan kai tous bazw sta pairs alla kai sto xaxistables
747
			for($i=0;$i<count($grouplist)-1;$i++){
748
				if(!in_array($grouplist[$i],$tables)){
749
					$tables[] = $grouplist[$i];
750
				}
751
				if($i == count($grouplist)-2){
752
					if(!in_array_r(array($sel['table'],$grouplist[$i]), $tablesPairs)){
753
						$tablesPairs[] = array($sel['table'],$grouplist[$i]);
754
					}
755
				}
756
				else{
757
					if(!in_array_r(array($grouplist[$i],$grouplist[$i+1]),$tablesPairs))
758
						$tablesPairs[] = array($grouplist[$i],$grouplist[$i+1]);
759
				}
760
			}
761
		}
762
		//steinw to query
763
		$query = "select ";
764
		/*xaxis*/
765
		if($isMeas && $sel['color'] != 'yes'){ // prepei na balw kai ton aggregator
766
			switch($sel['xaxis']['agg']){
767
				case 'none':
768
				case '':
769
				case 'avg':
770
					$query .= " avg(".$xaxisfield.") ";
771
					break;
772
				default:
773
					$query .= $sel['xaxis']['agg']."(".$xaxisfield.") ";
774
					break;
775
			}
776
		}
777
		else{
778
			$query .= " ".$xaxisfield;
779
		}
780
		/*yaxis*/
781
		if($sel['color'] != 'yes')
782
			switch($sel['fields'][0]['agg']){
783
				case 'none':
784
				case '':
785
				case 'avg':
786
					$query .= ", avg(".$field.") ";
787
					break;
788
				default:
789
					$query .= ", ".$sel['fields'][0]['agg']."(".$field.") ";
790
					break;
791
			}
792
		else
793
			$query .= ', '.$field;
794
				
795
		/*group*/
796
		$query .= ", ".$groupfield;
797
		
798
		$query .= " from ".implode(", ",$tables);
799
		$query .= " where ";
800
		for($i=0;$i<count($sel['fields']);$i++) {
801
			if($i!=0) $query .=" and ";
802
			$query .= '"'.$sel['fields'][$i]['fld'] .'" !=""';
803
		}
804

    
805
		if(count($tablesPairs) > 0){
806
			$query .= " and ";
807
			for($i=0;$i<count($tablesPairs);$i++){
808
				$query .= '"'.$tablesPairs[$i][0].'"."'.$tablesPairs[$i][1].'"="'.$tablesPairs[$i][1].'".id';
809
				if($i!=count($tablesPairs)-1) 	$query .= "and ";
810
				else $query .= " ";
811
			}
812
		}
813
		else $query .= ' ';
814
		if($sel['color'] != 'yes'){
815
			$query .= "group by ".$groupfield;
816
			if(!$isMeas){
817
				$query .=", ".$xaxisfield;
818
			}
819
		}
820
		$query .= " order by ".$groupfield.", ".$xaxisfield;
821
		$this->log->info("generated query: ".$query);
822
		$res = $this->doQuery($query, PDO::FETCH_NUM);
823
		if($isMeas) $returnType = 'scatter';
824
		else $returnType = 'chart';
825
		return array('type'=>$returnType,'data'=>$res,'accomDims'=>$dimsList['fields']);
826
	}
827

    
828
	function getData($sel){
829
		$this->log->info("getting data");
830
		$xaxislist = explode("-",$sel['xaxis']['name']);
831
		$groups = array();
832
		$brsels = array(); $queries = array();
833
		$breakflag = false;
834
		//check if we need to break the query to many (if there are filters that apply to only one field)
835
		if(count($sel['fields']) > 1){
836
			for($i=0;$i<count($sel['filters']);$i++)
837
				if(isset($sel['filters'][$i]['to']) && $sel['filters'][$i]['to'] != -1){
838
					if(!in_array($sel['filters'][$i]['to'],$groups))
839
						$groups[] = $sel['filters'][$i]['to'];
840
					$breakflag = true;
841
				}
842
			for($i=0;$i<count($sel['having']);$i++)
843
				if(isset($sel['having'][$i]['to']) && $sel['having'][$i]['to'] != -1){
844
					if(!in_array($sel['having'][$i]['to'],$groups))
845
						$groups[] = $sel['having'][$i]['to'];
846
					$breakflag = true;
847
				}
848
		}
849
		if($breakflag){
850
			$this->log->info("NEED TO BREAK!");
851
			//will break the query into as many as the different values in the filters and havings to attribute -> count($groups)
852
			$brsels[] = $this->clearselections($sel,$groups,-1,0);
853
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
854
				$queries[] = $this->scatterData($brsels[0],false);
855
			else
856
				$queries[] = $this->chartData($brsels[0],false);
857
			for($i=0;$i<count($groups);$i++){
858
				$brsels[] = $this->clearselections($sel,$groups,$groups[$i],$i+1);
859

    
860
				if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
861
					$queries[] = $this->scatterData($brsels[$i+1],false);
862
				else
863
					$queries[] = $this->chartData($brsels[$i+1],false);
864
			}
865

    
866
			$this->log->info("selections: ".print_r($brsels,true));
867
			$this->log->info("user selections updated: ".print_r($sel,true));
868
			$this->log->info("queries: ".print_r($queries,true));
869
			//get all the queries and combine them to one
870
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
871
				return $this->makeSuperQuery($queries,$sel,"scatter");
872
			else
873
				return $this->makeSuperQuery($queries,$sel,"chart");
874
		}
875
		else{
876
			$this->log->info("NO NEED TO BREAK!");
877
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
878
				return $this->scatterData($sel);
879
			else
880
				return $this->chartData($sel);
881
		}
882
	}
883

    
884
	private function makeSuperQuery($queries,$sel,$type){
885
		$superquerySelects = "SELECT ";
886
		$superquerySelecte = " ";
887
		$superqueryFrom = " FROM ";
888
		$superquerySort = "";
889
		//ta pedia tou xaxis kai tou group tha einai ayta tou outer join
890
		//sta select yparxei prwta to xaxis, meta i lista me ta fields onomatismena, kai meta an yparxei to group
891
		//sto megalo select tha yparxei gia kathe query to xaxis, meta ola ta fields twn queries me ti seira pou einai sto sel
892
		//kai meta gia kathe query to group field
893

    
894
		//prepei na kseroume kathe pedio tou select se poio query anikei, kai to pedio tou order by 
895
		for($q=0;$q<count($queries);$q++){//xaxis
896
			//if($q>0) $superquerySelects .= ", ";
897
			$superquerySelects .= "q".$q.".xfield, ";
898
			if($q>0) $superquerySort .= ", "; 
899
			$superquerySort .= "q".$q.".xfield "; 
900

    
901
			if($sel['group']!='' && $sel['group'] != 'no'){//dimfields
902
				/*if($q>0)*/ $superquerySelecte .= ", ";
903
				$superquerySelecte .= "q".$q.".dimfield ";
904
				$superquerySort .= ", q".$q.".dimfield ";
905
			}
906

    
907
			$superqueryFrom .= "(".$queries[$q].") as q".$q;
908

    
909
			if($q>0){
910
				$superqueryFrom .= " ON q".($q-1).".xfield = q".$q.".xfield ";
911
				if($sel['group']!='' && $sel['group'] != 'no')
912
					$superqueryFrom .= " AND q".($q-1).".dimfield = q".$q.".dimfield ";
913
			}
914

    
915
			if($q<count($queries)-1) {
916
				$superqueryFrom .= " FULL JOIN ";
917
			}
918

    
919
		}
920
		for($f=0;$f<count($sel['fields']);$f++){//fields
921
			$superquerySelects .= "q".$sel['fields'][$f]['q'].".field".$sel['fields'][$f]['i'];
922
			if($f<(count($sel['fields'])-1)) $superquerySelects .=", ";
923
		}
924
		if(isset($sel['sort']) && $sel['sort']!='xaxis'){
925
			$ex = explode(".", $sel['sortq']);
926
			$temp = "q".$ex[0].".field".$ex[1];
927

    
928
			if($sel['order'] && $sel['order'] == 'd')
929
				$temp.= " DESC, ";
930
			else
931
				$temp .= ", ";
932

    
933
			$superquerySort = $temp . $superquerySort;
934
		}
935

    
936
		$superquerySort = " ORDER BY ".$superquerySort;
937

    
938
		$superQuery = $superquerySelects.$superquerySelecte.$superqueryFrom.$superquerySort." LIMIT ".$sel['size'];
939
		$this->log->info("superquery: ".$superQuery);
940
		$res = $this->doQuery($superQuery, PDO::FETCH_NUM);
941
		return $this->combineData($res,count($queries),count($sel['fields']),$type);
942
	}
943

    
944
	private function combineData($data,$queries,$fields,$type){
945
		$newdata = array();
946
		if(count($data[0]) > $queries+$fields)
947
			$dstart = $queries + $fields;
948
		else
949
			$dstart = -1;
950
		$fstart = $queries;
951
		for($d=0;$d<count($data);$d++){
952
			$newdata[$d] = array();
953
			for($i=0;$i<$queries;$i++)
954
				if($data[$d][$i] != null){
955
					$newdata[$d][0] = $data[$d][$i];
956
					break;
957
				}
958
			for($i=$fstart;$i<$fields+$queries;$i++)
959
				$newdata[$d][$i-$fstart+1] = $data[$d][$i];
960
			if($dstart > 0)
961
				for($i=$dstart;$i<count($data[0]);$i++)
962
					if($data[$d][$i] != null){
963
						$newdata[$d][$fields+1] = $data[$d][$i];
964
						break;
965
					}
966
		}
967
		$this->log->info("superquerys result: ".print_r($newdata,true));
968
		return array('type'=>$type,'data'=>$newdata);
969
	}
970

    
971
	private function clearselections(&$sel,$seperate,$field,$index){
972
		$newsel = array();
973
		$fields = array();
974
		$newsel['table'] = $sel['table'];
975
		$newsel['xaxis'] = $sel['xaxis'];
976
		$newsel['group'] = $sel['group'];
977
		$newsel['color'] = $sel['color'];
978
		$newsel['size'] = $sel['size'];
979
		$newsel['fields'] = array();
980
		$newsel['filters'] = array();
981
		$newsel['having'] = array();
982
		if($field == -1 || $field == -2){ //things that apply to whole chart, will remove only the things that apply to one field and that field
983
			for($i=0;$i<count($sel['fields']);$i++){
984
				if(!in_array($i+1,$seperate)){
985
					$newsel['fields'][] = $sel['fields'][$i];
986
					$sel['fields'][$i]['q'] = $index;
987
					$sel['fields'][$i]['i'] = count($newsel['fields'])-1;
988
					$fields[] = $sel['fields'][$i]['agg'] + "-" + $sel['fields'][$i]['fld'];
989
				}
990
			}
991
			for($i=0;$i<count($sel['filters']);$i++){
992
				if(!isset($sel['filters'][$i]['to']) || $sel['filters'][$i]['to'] == -1){
993
					$newsel['filters'][] = $sel['filters'][$i];
994
				}
995
			}
996
			for($i=0;$i<count($sel['having']);$i++){
997
				if(!isset($sel['having'][$i]['to']) || $sel['having'][$i]['to'] == -1){
998
					$newsel['having'][] = $sel['having'][$i];
999
				}
1000
			}
1001
			if(in_array($sel['sort'],$fields)){
1002
				$sel['sortq'] = $index.".".(count($newsel['fields'])-1);
1003
				//$newsel['sort'] = $sel['sort'];
1004
			}
1005
			//else
1006
				//$newsel['sort'] = 'xaxis';
1007
		}
1008
		else{ //we keep only the field, and the filters and havings that apply to that and the whole chart
1009
			$newsel['fields'][] = $sel['fields'][$field-1];
1010
			$sel['fields'][$field-1]['q'] = $index;
1011
			$sel['fields'][$field-1]['i'] = count($newsel['fields'])-1;
1012
			for($i=0;$i<count($sel['filters']);$i++){
1013
				if(isset($sel['filters'][$i]['to']) && ($sel['filters'][$i]['to'] == $field || $sel['filters'][$i]['to'] == -1)){
1014
					$newsel['filters'][] = $sel['filters'][$i];
1015
				}
1016
			}
1017
			for($i=0;$i<count($sel['having']);$i++){
1018
				if(isset($sel['having'][$i]['to']) && $sel['having'][$i]['to'] == $field){
1019
					$newsel['having'][] = $sel['having'][$i];
1020
				}
1021
			}
1022
			if(in_array($sel['sort'],$fields)){
1023
				$newsel['sort'] = $sel['sort'];
1024
			}
1025
			else
1026
				$newsel['sort'] = 'xaxis';
1027
		}
1028
		return $newsel;
1029
	}
1030

    
1031
	function chartData($sel, $doquery=true){
1032
		if($sel['group']!='' && $sel['group'] != 'no'){	//group
1033
			return $this->chartDataGroup($sel, $doquery);
1034
		}
1035
		else{	
1036

    
1037
$this->log->info("sel: ".print_r($sel,true));
1038
			$tree = new QueryTree($sel['table']);
1039
			$tree->updateXAxis($sel['xaxis']['name']);
1040
			$tree->updateYAxis($sel['fields']);
1041
			$tree->updateFilters($sel['filters']);
1042
			if (isset($sel['sort'])) {
1043
				$tree->updateOrderBy($sel['sort']);
1044
				$tree->updateOrder($sel['order']);
1045
			}
1046
			$tree->updateLimit($sel['size']);
1047
			$tree->excludeNulls($sel['nulls']);
1048

    
1049
$this->log->info("tree: ".print_r($tree->tree, true));
1050

    
1051
			$query = $tree->getQuery();
1052

    
1053
			if(!$doquery){
1054
				$this->log->info('chartData generated query:'.$query);
1055
				$this->log->info('will not execute it');
1056
				return $query;
1057
			}
1058

    
1059
			$this->log->info('chartData generated tree: '.print_r($tree->getTree(), true));
1060
			$this->log->info('chartData generated query: '.$query);
1061
			$res = $this->doQuery($query, PDO::FETCH_NUM);
1062
			$this->log->info("result: ".print_r($res,true));
1063
			return array('type'=>'chart','data'=>$res);
1064
		}
1065
	
1066
	}
1067
	
1068
	function chartDataGroup($sel, $doquery=true){
1069
		//exoume dyo dims, ena tou xaxis kai ena tou group
1070
		//kanoume tin idia diadikasia kai gia ta dyo
1071
		$xfield = '';
1072
		$dimfield = '';
1073
		$tables = array();
1074
		$tablePairs = array();
1075
		$filters = array();
1076
		//order by it
1077
		//may need to join
1078
		//gia to xaxis
1079
		$dimlist = explode("-",$sel['xaxis']['name']);
1080
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1081
			$xfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1082
		}
1083
		else{
1084
			$xfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1085
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1086
			for($i=0;$i<count($dimlist)-1;$i++){
1087
				if(!in_array($dimlist[$i],$tables)){
1088
					$tables[] = $dimlist[$i];
1089
				}
1090
				if($i == 0){
1091
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1092
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1093
					}
1094
				}
1095
				else{
1096
					if(!in_array_r(array($dimlist[$i-1],$dimlist[$i]),$tablePairs))
1097
						$tablePairs[] = array($dimlist[$i-1],$dimlist[$i]);
1098
				}
1099
			}
1100
		}
1101
		//gia to group
1102
		$dimlist = explode("-",$sel['group']);
1103
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1104
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1105
		}
1106
		else{
1107
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1108
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1109
			for($i=0;$i<count($dimlist)-1;$i++){
1110
				if(!in_array($dimlist[$i],$tables)){
1111
					$tables[] = $dimlist[$i];
1112
				}
1113
				if($i == 0){
1114
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1115
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1116
					}
1117
				}
1118
				else{
1119
					if(!in_array_r(array($dimlist[$i-1],$dimlist[$i]),$tablePairs))
1120
						$tablePairs[] = array($dimlist[$i-1],$dimlist[$i]);
1121
				}
1122
			}
1123
		}
1124
		//filters
1125
		if(isset($sel['filters'])){
1126
			for($fc=0;$fc<count($sel['filters']);$fc++){
1127
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1128
				if(count($filterfields)>1){ //join needed
1129
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1130
					for($i=0;$i<count($filterfields)-1;$i++){
1131
						if(!in_array($filterfields[$i],$tables)){
1132
							$tables[] = $filterfields[$i];
1133
						}
1134
						if($i == 0){
1135
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1136
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1137
							}
1138
						}
1139
						else{
1140
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1141
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1142
							}
1143
						}
1144
					}
1145
				}
1146
				else
1147
                                	$sel['filters'][$fc]['name'] = $sel['table'].".".$sel['filters'][$fc]['name'];
1148
			}
1149
		}
1150
		//----------------------------------------------------------------//
1151
		//having
1152
		if(isset($sel['having'])){
1153
			for($fc=0;$fc<count($sel['having']);$fc++){
1154
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1155
				if(count($havingfields)>1){ //join needed
1156
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1157
					for($i=0;$i<count($havingfields)-1;$i++){
1158
						if(!in_array($havingfields[$i],$tables)){
1159
							$tables[] = $havingfields[$i];
1160
						}
1161
						if($i == 0){
1162
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1163
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1164
							}
1165
						}
1166
						else{
1167
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1168
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1169
							}
1170
						}
1171
					}
1172
				}
1173
			}
1174
		}
1175
		//----------------------------------------------------------------//
1176
		$query = 'SELECT '.$xfield.' as xfield';
1177
		for($i=0;$i<count($sel['fields']);$i++){
1178
			$query .= ', '.$sel['fields'][$i]['agg'].'("'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'") as field'.$i;
1179
		}
1180
		$query .= ', '.$dimfield.' as dimfield';
1181
		$query .= ' FROM "'.$sel['table'].'"';
1182
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1183
		/*$query .= ' WHERE "'.$sel['xaxis']['name'].'" !=""';
1184
		for($i=0;$i<count($sel['fields']);$i++){
1185
			$query .=" and ";
1186
			$query .= '"'.$sel['fields'][$i]['fld'] .'" !=""';
1187
		}*/
1188
		if(count($tablePairs) > 0 || (isset($sel['filters']) && count($sel['filters']) > 0) || $sel['nulls']){
1189
			$query .= " WHERE ";
1190
			for($i=0;$i<count($tablePairs);$i++){
1191
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1192
				if($i!=count($tablePairs)-1) 	$query .= " and ";
1193
				else $query .= " ";
1194
			}
1195
			//filters
1196
			if(isset($sel['filters']) && count($sel['filters'])>0){
1197
				if(count($tablePairs)>0)
1198
					$query .= " and ";
1199
				for($i=0;$i<count($sel['filters']);$i++){
1200
					if(isset($sel['filters'][$i]['max'])){
1201
						if(strstr($sel['filters'][$i]['name'],"year") !== false  && $sel['filters'][$i]['max']=='today')
1202
							$query .= "(".$sel['filters'][$i]['name']."<= extract(YEAR from now()) and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")";
1203
						else if(strstr($sel['filters'][$i]['name'],"year") !== false  && $sel['filters'][$i]['min']=='today')
1204
							$query .="(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">= extract(YEAR from now()))" ;
1205
						else
1206
							$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1207
					}
1208
					else if(isset($sel['filters'][$i]['values'])){
1209
						$query .= "(";
1210
						for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1211
							//$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1212
							$query .= $sel['filters'][$i]['name'].'=\''.$sel['filters'][$i]['values'][$j].'\'';
1213
							if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1214
						}
1215
						$query .= ")";
1216
					}
1217
					else if(isset($sel['filters'][$i]['exvalues'])){
1218
						$query .= "(";
1219
						for($j=0;$j<count($sel['filters'][$i]['exvalues']);$j++){
1220
							$query .= $sel['filters'][$i]['name'].'!=\''.$sel['filters'][$i]['exvalues'][$j].'\'';
1221
							if($j!=count($sel['filters'][$i]['exvalues'])-1) $query .= " and ";
1222
						}
1223
						$query .= ")";
1224
					}
1225
					//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1226
					if($i!=count($sel['filters'])-1) 	$query .= " and ";
1227
					else $query .= " ";
1228
				}
1229
			}
1230
			if($sel['nulls'] == true){//non null values from xaxis field and dimfield
1231
				if((isset($sel['filters']) && count($sel['filters'])>0) || count($tablePairs) > 0){
1232
					$query .= " and ";
1233
				}
1234
				$query .= $xfield . " IS NOT NULL AND ". $dimfield . " IS NOT NULL ";
1235
			}
1236
		}
1237
		//--------------------------------------------------------//
1238
		$query .= " GROUP BY ".$dimfield.', '.$xfield;
1239
		if(count($sel['having'])>0){
1240
			$query .= " HAVING "; 
1241
			for($i=0;$i<count($sel['having']);$i++){
1242
				if($i>0)
1243
					$query .= " and ";
1244
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1245
			}
1246
			
1247
		}
1248
		
1249
		if(!$doquery){
1250
			$this->log->info('chartDataGroup generated query:'.$query);
1251
			$this->log->info('will not execute it');
1252
			return $query;
1253
		}
1254
		
1255
		//need to find the field to order the result set by
1256
		$query.= " ORDER BY ";
1257
		if(isset($sel['sort']) && $sel['sort']!='xaxis'){
1258
			$ex = explode("-", $sel['sort']);
1259
			$query .= $ex[0]."(".$sel['table'].".".$ex[1].")";
1260
			if($sel['order'] && $sel['order'] == 'd')
1261
				$query.= " DESC";
1262
			$query .= ", ".$xfield;
1263
		}
1264
		else{
1265
			$query.= $xfield;
1266
			if($sel['order'] && $sel['order'] == 'd')
1267
				$query.= " DESC";
1268
		}
1269
		$query.=', '.$dimfield;
1270
		$query.= " LIMIT ".$sel['size'];
1271
		//echo $query;
1272
		$this->log->info('chartDataGroup generated query:'.$query);
1273
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1274
		$this->log->info("result: ".print_r($res,true));
1275
		return array('type'=>'chart','data'=>$res);
1276
	
1277
	}
1278
	
1279
	function scatterData($sel, $doquery=true){
1280
		//group, color, or nothing
1281
		//many fields or one
1282
		if($sel['group']!='' && $sel['group'] != 'no'){			//group
1283
			$this->log->info('scatterDataGroup called');
1284
			return $this->scatterDataGroup($sel, $doquery);
1285
		}
1286
		else if($sel['color']!='' && $sel['color'] != 'no'){	//color
1287
			$this->log->info('scatterDataColor called');
1288
			return $this->scatterDataColor($sel, $doquery);
1289
		}
1290
		else{													//nothing
1291
			$this->log->info('scatterData called');
1292
			//code here
1293
			//no dim to bother us, just the measurements
1294
			//TODO: get all other dims to show in tooltip
1295
			$tables = array();
1296
			$tablePairs = array();
1297
			$filters = array();
1298
			//filters
1299
			if(isset($sel['filters'])){
1300
				for($fc=0;$fc<count($sel['filters']);$fc++){
1301
					$filterfields = explode("-",$sel['filters'][$fc]['name']);
1302
					if(count($filterfields)==1){ //no join needed
1303
						;//$filters[] = $sel['filters'][$fc];
1304
                                                $sel['filters'][$fc]['name'] = $sel['table'].".".$sel['filters'][$fc]['name'];
1305
					}
1306
					else{
1307
						$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1308
						for($i=0;$i<count($filterfields)-1;$i++){
1309
							if(!in_array($filterfields[$i],$tables)){
1310
								$tables[] = $filterfields[$i];
1311
							}
1312
							if($i == 0){
1313
								if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1314
									$tablePairs[] = array($sel['table'],$filterfields[$i]);
1315
								}
1316
							}
1317
							else{
1318
								if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1319
									$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1320
								}
1321
							}
1322
						}
1323
					}
1324
				}
1325
			}
1326
			//----------------------------------------------------------------//
1327
			//having
1328
			if(isset($sel['having'])){
1329
				for($fc=0;$fc<count($sel['having']);$fc++){
1330
					$havingfields = explode("-",$sel['having'][$fc]['name']);
1331
					if(count($havingfields)>1){ //join needed
1332
						$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1333
						for($i=0;$i<count($havingfields)-1;$i++){
1334
							if(!in_array($havingfields[$i],$tables)){
1335
								$tables[] = $havingfields[$i];
1336
							}
1337
							if($i == 0){
1338
								if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1339
									$tablePairs[] = array($sel['table'],$havingfields[$i]);
1340
								}
1341
							}
1342
							else{
1343
								if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1344
									$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1345
								}
1346
							}
1347
						}
1348
					}
1349
				}
1350
			}
1351
			//----------------------------------------------------------------//
1352
			$query = 'SELECT "'.$sel['table'].'"."'.$sel['xaxis']['name'].' " as xfield';
1353
			for($i=0;$i<count($sel['fields']);$i++){
1354
				$query .= ', "'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'" as field'.$i;
1355
			}
1356
			$query .= ' FROM "'.$sel['table'].'"';
1357
			if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1358
			
1359
			$query .= ' WHERE ';
1360
			for($i=0;$i<count($sel['fields']);$i++){
1361
				if($i>0) $query .=" AND ";
1362
				$query .= "field".$i.'" IS NOT NULL';
1363
			}
1364
			//joins + filters
1365
			if(count($tablePairs) > 0 || (isset($sel['filters']) && count($sel['filters']) > 0) || $sel['nulls']){
1366
				$query .= " AND ";
1367
				for($i=0;$i<count($tablePairs);$i++){
1368
					$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1369
					if($i!=count($tablePairs)-1) 	$query .= " and ";
1370
					else $query .= " ";
1371
				}
1372
				if(isset($sel['filters']) && count($sel['filters'])>0){
1373
					if(count($tablePairs)>0) $query .= " and ";
1374
					for($i=0;$i<count($sel['filters']);$i++){
1375
						if(isset($sel['filters'][$i]['max'])){
1376
							$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1377
						}
1378
						else{
1379
							$query .= "(";
1380
							for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1381
								$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1382
								if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1383
							}
1384
							$query .= ")";
1385
						}
1386
						//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1387
						if($i!=count($sel['filters'])-1) 	$query .= " and ";
1388
						else $query .= " ";
1389
					}
1390
				}
1391
				if($sel['nulls'] == true){//non null values from xaxis field and dimfield
1392
					if((isset($sel['filters']) && count($sel['filters'])>0) || count($tablePairs) > 0){
1393
						$query .= " and ";
1394
					}
1395
					$query .= $xfield . " IS NOT NULL ";
1396
				}
1397
			}
1398
			if(count($sel['having'])>0){
1399
				$query .= " HAVING "; 
1400
				for($i=0;$i<count($sel['having']);$i++){
1401
					if($i>0)
1402
						$query .= " and ";
1403
					$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1404
				}
1405
			
1406
			}
1407
			//--------------------------------------------------------//
1408
			
1409
			if(!$doquery){
1410
				$this->log->info('scatterData generated query:'.$query);
1411
				$this->log->info('will not execute it');
1412
				return $query;
1413
			}
1414
			$this->log->info('scatterData generated query:'.$query);
1415
			//echo "scatterplot, simple case:"; echo $query;
1416
			$res = $this->doQuery($query, PDO::FETCH_NUM);
1417
			
1418
			$this->log->info("result: ".print_r($res,true));
1419
			return array('type'=>'scatter','data'=>$res);
1420
		}
1421
	}
1422
	
1423
	function scatterDataColor($sel, $doquery=true){
1424
		//one dim, the one for the color
1425
		//TODO: get all other dims to show in tooltip
1426
		$dimfield = '';
1427
		$tables = array();
1428
		$tablePairs = array();
1429
		//order by it
1430
		//may need to join
1431
		$dimlist = explode("-",$sel['color']);
1432
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1433
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1434
		}
1435
		else{
1436
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1437
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1438
			for($i=0;$i<count($dimlist)-1;$i++){
1439
				if(!in_array($dimlist[$i],$tables)){
1440
					$tables[] = $dimlist[$i];
1441
				}
1442
				if($i == count($dimlist)-2){
1443
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1444
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1445
					}
1446
				}
1447
				else{
1448
					if(!in_array_r(array($dimlist[$i],$dimlist[$i+1]),$tablePairs))
1449
						$tablePairs[] = array($dimlist[$i],$dimlist[$i+1]);
1450
				}
1451
			}
1452
		}
1453
		//filters
1454
		if(isset($sel['filters'])){
1455
			for($fc=0;$fc<count($sel['filters']);$fc++){
1456
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1457
				if(count($filterfields)==1){ //no join needed
1458
					;//$filters[] = $sel['filters'][$fc];
1459
				}
1460
				else{
1461
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1462
					for($i=0;$i<count($filterfields)-1;$i++){
1463
						if(!in_array($filterfields[$i],$tables)){
1464
							$tables[] = $filterfields[$i];
1465
						}
1466
						if($i == 0){
1467
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1468
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1469
							}
1470
						}
1471
						else{
1472
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1473
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1474
							}
1475
						}
1476
					}
1477
				}
1478
			}
1479
		}
1480
		//----------------------------------------------------------------//
1481
		//having
1482
		if(isset($sel['having'])){
1483
			for($fc=0;$fc<count($sel['having']);$fc++){
1484
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1485
				if(count($havingfields)>1){ //join needed
1486
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1487
					for($i=0;$i<count($havingfields)-1;$i++){
1488
						if(!in_array($havingfields[$i],$tables)){
1489
							$tables[] = $havingfields[$i];
1490
						}
1491
						if($i == 0){
1492
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1493
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1494
							}
1495
						}
1496
						else{
1497
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1498
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1499
							}
1500
						}
1501
					}
1502
				}
1503
			}
1504
		}
1505
		//----------------------------------------------------------------//
1506
		$query = 'SELECT "'.$sel['table'].'"."'.$sel['xaxis']['name'].'" as xfield';
1507
		for($i=0;$i<count($sel['fields']);$i++){
1508
			$query .= ', "'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'" as field'.$i;
1509
		}
1510
		$query .= ', '.$dimfield.' as dimfield';
1511
		$query .= ' FROM "'.$sel['table'].'"';
1512
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1513
		
1514
		$query .= " WHERE ";
1515
		for($i=0;$i<count($sel['fields']);$i++){
1516
			if($i>0) $query .=" AND ";
1517
			$query .= "field".$i.'" IS NOT NULL';
1518
		}
1519
		if(count($tablePairs) > 0){
1520
			$query .= " AND ";
1521
			for($i=0;$i<count($tablePairs);$i++){
1522
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1523
				if($i!=count($tablePairs)-1) 	$query .= "AND ";
1524
				else $query .= " ";
1525
			}
1526
		}
1527
		//filters
1528
		if(isset($sel['filters']) && count($sel['filters'])>0){
1529
			if(count($tablePairs)>0) $query .= " AND ";
1530
			for($i=0;$i<count($sel['filters']);$i++){
1531
				if(isset($sel['filters'][$i]['max'])){
1532
					$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." AND ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1533
				}
1534
				else{
1535
					$query .= "(";
1536
					for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1537
						$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1538
						if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1539
					}
1540
					$query .= ")";
1541
				}
1542
				//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1543
				if($i!=count($sel['filters'])-1) 	$query .= " AND ";
1544
				else $query .= " ";
1545
			}
1546
		}
1547
		if(count($sel['having'])>0){
1548
			$query .= " HAVING "; 
1549
			for($i=0;$i<count($sel['having']);$i++){
1550
				if($i>0)
1551
					$query .= " and ";
1552
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1553
			}
1554
			
1555
		}
1556
		
1557
		if(!$doquery){
1558
			$this->log->info('chartDataColor generated query:'.$query);
1559
			$this->log->info('will not execute it');
1560
			return $query;
1561
		}
1562
		
1563
		//--------------------------------------------------------//
1564
		$query .= " ORDER BY ".$dimfield;
1565
		//echo "scatterplot, case color:"; echo $query;
1566
		$this->log->info('scatterDataColor generated query:'.$query);
1567
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1568
		
1569
		$this->log->info("result: ".print_r($res,true));
1570
		return array('type'=>'scatter','data'=>$res);
1571
	}
1572
	
1573
	function scatterDataGroup($sel, $doquery=true){
1574
		//one dim, the one for the group
1575
		//aggrs for all fields
1576
		//TODO: get all other dims to show in tooltip
1577
		$dimfield = '';
1578
		$tables = array();
1579
		$tablePairs = array();
1580
		//order by it
1581
		//may need to join
1582
		$dimlist = explode("-",$sel['group']);
1583
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1584
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1585
		}
1586
		else{
1587
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1588
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1589
			for($i=0;$i<count($dimlist)-1;$i++){
1590
				if(!in_array($dimlist[$i],$tables)){
1591
					$tables[] = $dimlist[$i];
1592
				}
1593
				if($i == count($dimlist)-2){
1594
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1595
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1596
					}
1597
				}
1598
				else{
1599
					if(!in_array_r(array($dimlist[$i],$dimlist[$i+1]),$tablePairs))
1600
						$tablePairs[] = array($dimlist[$i],$dimlist[$i+1]);
1601
				}
1602
			}
1603
		}
1604
		//filters
1605
		if(isset($sel['filters'])){
1606
			for($fc=0;$fc<count($sel['filters']);$fc++){
1607
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1608
				if(count($filterfields)>1){ //join needed
1609
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1610
					for($i=0;$i<count($filterfields)-1;$i++){
1611
						if(!in_array($filterfields[$i],$tables)){
1612
							$tables[] = $filterfields[$i];
1613
						}
1614
						if($i == 0){
1615
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1616
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1617
							}
1618
						}
1619
						else{
1620
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1621
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1622
							}
1623
						}
1624
					}
1625
				}
1626
			}
1627
		}
1628
		//----------------------------------------------------------------//
1629
		//having
1630
		if(isset($sel['having'])){
1631
			for($fc=0;$fc<count($sel['having']);$fc++){
1632
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1633
				if(count($havingfields)>1){ //join needed
1634
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1635
					for($i=0;$i<count($havingfields)-1;$i++){
1636
						if(!in_array($havingfields[$i],$tables)){
1637
							$tables[] = $havingfields[$i];
1638
						}
1639
						if($i == 0){
1640
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1641
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1642
							}
1643
						}
1644
						else{
1645
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1646
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1647
							}
1648
						}
1649
					}
1650
				}
1651
			}
1652
		}
1653
		//----------------------------------------------------------------//
1654
		$query = 'SELECT '.$sel['xaxis']['agg'].'("'.$sel['table'].'"."'.$sel['xaxis']['name'].'") as xfield';
1655
		for($i=0;$i<count($sel['fields']);$i++){
1656
			$query .= ', '.$sel['fields'][$i]['agg'].'("'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'")';
1657
		}
1658
		$query .= ' ,'.$dimfield.' as dimfield';
1659
		$query .= ' FROM "'.$sel['table'].'"';
1660
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1661
		
1662
		$query .= ' WHERE ';
1663
		for($i=0;$i<count($sel['fields']);$i++){
1664
			if($i>0) $query .=" AND ";
1665
			$query .= 'field'.$i." IS NOT NULL";
1666
		}
1667

    
1668
		if(count($tablePairs) > 0){
1669
			$query .= " AND ";
1670
			for($i=0;$i<count($tablePairs);$i++){
1671
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1672
				if($i!=count($tablePairs)-1) 	$query .= "AND ";
1673
				else $query .= " ";
1674
			}
1675
		}
1676
		//filters
1677
		if(isset($sel['filters']) && count($sel['filters'])>0){
1678
			$query .= " AND ";
1679
			for($i=0;$i<count($sel['filters']);$i++){
1680
				if(isset($sel['filters'][$i]['max'])){
1681
					$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." AND ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1682
				}
1683
				else{
1684
					$query .= "(";
1685
					for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1686
						$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1687
						if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1688
					}
1689
					$query .= ")";
1690
				}
1691
				//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1692
				if($i!=count($sel['filters'])-1) 	$query .= " AND ";
1693
				else $query .= " ";
1694
			}
1695
		}
1696
		//--------------------------------------------------------//
1697
		$query .= " GROUP BY ".$dimfield;
1698
		if(count($sel['having'])>0){
1699
			$query .= " HAVING "; 
1700
			for($i=0;$i<count($sel['having']);$i++){
1701
				if($i>0)
1702
					$query .= " and ";
1703
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1704
			}
1705
			
1706
		}
1707
		
1708
		if(!$doquery){
1709
			$this->log->info('chartDataGroup generated query:'.$query);
1710
			$this->log->info('will not execute it');
1711
			return $query;
1712
		}
1713
		//echo "scatterplot, case group:"; echo $query;
1714
		$this->log->info('scatterDataGroup generated query:'.$query);
1715
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1716
		
1717
		$this->log->info("result: ".print_r($res,true));
1718
		return array('type'=>'scatter','data'=>$res);
1719
	}
1720
	
1721
	function performQuery($query){
1722
		$this->log->info("perfoming query");		
1723
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1724
		
1725
		$this->log->info("result: ".print_r($res,true));
1726
		return $res;
1727
	}
1728
	
1729
	function makeQuery($selectedData){
1730
		$this->log->info("makeQuery");
1731
		$isMeas = false;
1732
		$hasGroups = true;
1733
		$selectList = array();
1734
		$groupbyList = array();
1735
		$whereList = array();
1736
		$groupby = "";
1737
		$orderby = ""; 
1738
		$lastSelect = array();
1739
		
1740
		$tablesList = array();
1741
		$tablesPairs = array();
1742
		$xaxistables = array();
1743
		$dimsList = array();
1744
		$dimsList = $this->queryAllDims($selectedData['table']);
1745
		//create the tables list and the tables pairs list
1746
		$tablesList[] = $selectedData['table'];
1747
		foreach($selectedData['series'] as $series) {
1748
			$seriesexploded = explode("-",$series);
1749
			if(count($seriesexploded) == 1) {
1750
				$groupbyList[] = '"'.$selectedData['table'].'"."'.$seriesexploded[0].'"';
1751
				$lastSelect[] = $seriesexploded[0];
1752
			}
1753
			else{
1754
				$i=0;
1755
				if(!in_array($seriesexploded[$i],$tablesList))
1756
					$tablesList[] = $seriesexploded[$i];
1757
				
1758
				if(!in_array_r(array($selectedData['table'],$seriesexploded[0]),$tablesPairs))
1759
					$tablesPairs[] = array($selectedData['table'],$seriesexploded[0]);
1760
					
1761
				for($j=1;$j<count($seriesexploded)-1;$j++) {
1762
					if(!in_array($seriesexploded[$j],$tablesList))
1763
						$tablesList[] = $seriesexploded[$j];
1764
					if(!in_array_r(array($seriesexploded[$i],$seriesexploded[$j]),$tablesPairs))
1765
						$tablesPairs[] = array($seriesexploded[$i],$seriesexploded[$j]);
1766
					$i++;
1767
				}
1768
				$groupbyList[] = '"'.$seriesexploded[count($seriesexploded)-2].'"."'.$seriesexploded[count($seriesexploded)-1].'"';
1769
				$lastSelect[] = $seriesexploded[count($seriesexploded)-1];
1770
			}
1771
		}
1772
		$xaxistables = explode("-",$selectedData['xaxis']['name']);
1773
		if($this->checkMeas($selectedData['table'], $xaxistables[count($xaxistables)-1])){
1774
			$isMeas = true;
1775
			$hasGroups = false;
1776
		}
1777
		if(count($xaxistables) == 1){
1778
			if($isMeas && $selectedData['group'] && $selectedData['group'] != ''){
1779
				if($selectedData['xaxis']['agg'] == 'none')
1780
					$selectList[] = "avg('".$selectedData['table'].'"."'.$xaxistables[0].'")';
1781
				else
1782
					$selectList[] = $selectedData['xaxis']['agg']+'("'.$selectedData['table'].'"."'.$xaxistables[0].'")';
1783
			}
1784
			else{
1785
				$selectList[] = '"'.$selectedData['table'].'"."'.$xaxistables[0].'"';
1786
			}
1787
			if(!$isMeas){
1788
				$groupbyList[] = '"'.$selectedData['table'].'"."'.$xaxistables[0].'"';
1789
			}
1790
		}
1791
		else {
1792
			$selectList[] = '"'.$xaxistables[count($xaxistables)-2].'"."'.$xaxistables[count($xaxistables)-1].'"';
1793
			if(!$isMeas){
1794
				$groupbyList[] = '"'.$xaxistables[count($xaxistables)-2].'"."'.$xaxistables[count($xaxistables)-1].'"';
1795
			}
1796
			if(!in_array($xaxistables[count($xaxistables)-2],$tablesList))
1797
				$tablesList[] = $xaxistables[count($xaxistables)-2];
1798
			
1799
			if(!in_array_r(array($selectedData['table'],$xaxistables[0]),$tablesPairs))
1800
					$tablesPairs[] = array($selectedData['table'],$xaxistables[0]);
1801
			for($i=0;$i<count($xaxistables)-2;$i++) {
1802
				if(!in_array($xaxistables[$i],$tablesList))
1803
					$tablesList[] = $xaxistables[$i];
1804
			
1805
				if(!in_array_r(array($xaxistables[$i],$xaxistables[$i+1]),$tablesPairs))
1806
					$tablesPairs[] = array($xaxistables[$i],$xaxistables[$i+1]);
1807
			}
1808
		}
1809
		$orderby = implode(", ",$groupbyList);
1810
		$groupby = implode(", ",$groupbyList);
1811

    
1812
		foreach($tablesPairs as $pair) {
1813
			$whereList[] = '"'.$pair[0].'"."'.$pair[1].'" = "'.$pair[1].'".id';
1814
		}
1815
		
1816
		foreach($selectedData['fields'] as $field) {
1817
			if($hasGroups){
1818
				if($field['agg'] == 'none')
1819
					$selectList[] ='avg("'.$selectedData['table'].'"."'.$field['fld'].'")';
1820
				else
1821
					$selectList[] = $field['agg'].'("'.$selectedData['table'].'"."'.$field['fld'].'")';
1822
			}
1823
			else
1824
				$selectList[] = '"'.$selectedData['table'].'"."'.$field['fld'].'"';
1825
		}
1826
		$query = "select ".implode(", ",$selectList);
1827
		if(count($lastSelect)!=0)
1828
			$query .= ", ".implode(" || '-' || ",$lastSelect)." as seriesName ";
1829
		$query .= " from '".implode("', '",$tablesList)."'";
1830
		$query .= " where ";
1831
		for($i=0;$i<count($selectedData['fields']);$i++) {
1832
			if($i!=0) $query .=" and ";
1833
			$query .= '"'.$selectedData['fields'][$i]['fld'] .'" !=""';
1834
		}
1835
		if(count($whereList) !=0)
1836
			$query .= " and ".implode(" and ",$whereList);
1837
		if($groupby!='' && $selectedData['color']!= 'yes')
1838
			$query .= " group by ".$groupby;
1839
		if($orderby!='')
1840
			$query .= " order by ".$orderby;
1841
		//echo "NOT GROUP"; echo $query;
1842
		$this->log->info("generated query: ".$query);
1843
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1844
		//print_r($res);
1845
		//$this->log->info('result set:'.json_encode($res));
1846
		if($isMeas) $returnType = 'scatter';
1847
		else $returnType = 'chart';
1848
		return array('type'=>$returnType,'data'=>$res,'accomDims'=>$dimsList['fields']);
1849
	}
1850

    
1851
	function queryAllDims($tablename) {
1852
		//get all the dims of the fact table and make a list with all their keys
1853
		$fields = array();
1854
		$joins = array();
1855
		//find the factable
1856
		$table = $this->findTable($tablename,'fact');
1857
		if($table == false) {
1858
			return false;
1859
		}
1860
		foreach($table['dim'] as $dim) {
1861
			if(isset($dim['dimtable']) && $dim['dimtable'] == 'no') {//will need no join
1862
				$fields[] = $dim['name'];
1863
			}
1864
			else{
1865
				//find the key(s) put them in the fields list 
1866
				$key = $this->getDimsKeys($dim['name']);
1867
				if(is_array($key)){
1868
					foreach($key as $k)
1869
						$k = "'".$k."'";
1870
					$fields[] = implode(" || ",$key);
1871
				}
1872
				else
1873
					$fields[] = $key;
1874
				//and put it in the join list
1875
				$joins[] = $dim['name'];
1876
			}
1877
		}
1878
		return array('fields'=>$fields,'joins'=>$joins);
1879
	}
1880
}
1881

    
1882
class QueryTree {
1883
	public $tree = Array();
1884
	
1885
	public function __construct($table) {
1886
		$this->tree['table'] = $table;
1887
		$this->tree['chains'] = Array();
1888
		$this->tree['order'] = 'ASC';
1889
	}
1890
	
1891
	public function updateFilters($filters) {
1892
		for ($i = 0; $i < count($filters); $i++) {
1893
			$filterFields = explode("-", $filters[$i]['name']);
1894
			$rootField = $filterFields[0];
1895

    
1896
			$field = $filterFields[count($filterFields) - 1];
1897
			$filter = Array();
1898
			
1899
			$filter["column"] = $field;
1900
			if (isset($filters[$i]['values']))
1901
				$filter['values'] = $filters[$i]['values'];
1902
			if (isset($filters[$i]['max']))
1903
				$filter['max'] = $filters[$i]['max'];
1904
			if (isset($filters[$i]['min']))
1905
				$filter['min'] = $filters[$i]['min'];
1906
			if (isset($filters[$i]['exvalues']))
1907
				$filter['exvalues'] = $filters[$i]['exvalues'];
1908
			
1909
			if (count($filterFields) > 1) {
1910
				$this->buildChain($filters[$i]['name']);
1911
				$this->tree['chains'][$rootField]['tables'][count($filterFields) - 2]['filters'][] = $filter;
1912
			} else {
1913
				$this->tree['filters'][] = $filter;
1914
			}
1915
		}
1916
	}
1917
	
1918
	public function updateYAxis($yAxisFields) {
1919
		foreach ($yAxisFields as $field)
1920
			$this->tree['yAxis'][] = $field['agg'] . '("' . $this->tree['table'] . '"."' . $field['fld'] . '")';
1921
	}
1922
	
1923
	public function updateXAxis($xAxisField) {
1924
		$fields = explode("-", $xAxisField);
1925
		
1926
		if (count($fields) == 1) {
1927
			$this->tree['xAxis'] = '"'. $this->tree['table'] .'"."' . $fields[0] . '"';
1928
		} else {
1929
			if (!isset($this->tree['chains'][$fields[0]])) {
1930
				$this->buildChain($xAxisField);
1931
			}
1932
			
1933
			$this->tree['xAxis'] = '"' . $fields[0] . '"."' . $fields[count($fields) - 1] . '"';
1934
			$this->tree['chains'][$fields[0]]['return'] = '"'.$fields[count($fields) - 2] . '"."' . $fields[count($fields) - 1] . '"';
1935
		}
1936
	}
1937
	
1938
	public function excludeNulls($exclude = true) {
1939
		$this->tree['excludeNulls'] = $exclude;
1940
	}
1941
	
1942
	public function updateOrderBy($orderBy) {
1943
		if ($orderBy == 'xaxis') {
1944
			$this->tree['orderBy'] = $this->tree['xAxis'];
1945
		} else {
1946
			$fields = explode('-', $orderBy);
1947
			
1948
			$this->tree['orderBy'] = $fields[0] . '("' . $this->tree['table'] . '"."' . $fields[1] . '")';
1949
		}
1950
	}
1951
	
1952
	public function updateOrder($order) {
1953
		if ($order == 'd') {
1954
			$this->tree['order'] = 'DESC';
1955
		}
1956
	}
1957
	
1958
	public function updateLimit($limit) {
1959
		$this->tree['limit'] = $limit;
1960
	}
1961
	
1962
	public function getQuery() {
1963
		$query = 'SELECT ' . $this->tree['xAxis'] . ' as xfield';
1964
		
1965
		if (isset($this->tree['yAxis'])) {
1966
			for ($i = 0; $i < count($this->tree['yAxis']); $i++) {
1967
				
1968
				$query .= ', ';
1969
				
1970
				if ($i < count($this->tree['yAxis']) - 1) {
1971
					$query .= ' , ';
1972
				}
1973
				
1974
				$query .= $this->tree['yAxis'][$i] . ' as field' . $i;
1975
			}
1976
		}
1977
		
1978
		$query .= ' FROM ' . $this->tree['table'];
1979
		
1980
		foreach ($this->tree['chains'] as $chainName => $chain) {
1981
			$query .= ' JOIN (' . $this->buildSubQuery($chain) . ') as ' .$chainName . ' ON "' . $this->tree['table'] . '"."' . $chainName . '" = "' . $chainName . '"."id"' ;
1982
		}
1983
		
1984
		if (isset($this->tree['excludeNulls']) || isset($this->tree['filters'])) {
1985
			$query .= ' WHERE ';
1986
		}
1987
		
1988
		if (isset($this->tree['excludeNulls'])) {
1989
		 	$query .= $this->tree['xAxis'] . ' IS NOT NULL';
1990
		}
1991
		
1992
		if (isset($this->tree['filters'])) {
1993
			if (substr_compare($query, ' WHERE ', -strlen(' WHERE '), strlen(' WHERE ')) !== 0)
1994
				$query .= ' AND ';
1995
				
1996
			for ($i = 0; $i < count($this->tree['filters']); $i++) {
1997
				$query .= '(' . $this->buildSubQueryFilter($this->tree['table'], $this->tree['filters'][$i]) .')';
1998
				
1999
				if ($i < count($this->tree['filters']) - 1)
2000
					$query .= ' AND ';
2001
			}
2002
		}
2003
		
2004
		$query .= ' GROUP BY ' . $this->tree['xAxis'];
2005
		
2006
		if (isset($this->tree['orderBy'])) {
2007
			$query .= ' ORDER BY ' . $this->tree['orderBy'] . ' ' . $this->tree['order'];
2008
		}
2009
		
2010
		if (isset($this->tree['limit'])) {
2011
			$query .= ' LIMIT ' . $this->tree['limit'];
2012
		}
2013
		
2014
		return $query;
2015
	}
2016
	
2017
	public function getTree() {
2018
		return $this->tree;
2019
	}
2020
	
2021
	/*	Helper functions  */
2022
	
2023
	private function buildChain($fieldsString) {
2024
		$fields = explode("-", $fieldsString);
2025
		$rootField = $fields[0];
2026

    
2027
		if (!isset($this->tree['chains'][$rootField])) {
2028
			$this->tree['chains'][$rootField] = Array();
2029
			$this->tree['chains'][$rootField]['name'] = $rootField;
2030
		}
2031
					
2032
		for ($fc = 0; $fc < count($fields) - 1; $fc++) {
2033
			$field = $fields[$fc];
2034

    
2035
			if (!isset($this->tree['chains'][$rootField]['tables'][$fc]) ) {
2036
				$this->tree['chains'][$rootField]['tables'][] = Array("table" => $field);
2037
			}					
2038

    
2039
		}
2040
	}
2041
	
2042
	private function buildSubQuery($chain) {
2043
		$subQuery = 'select distinct "' . $chain['tables'][0]['table'] . '"."id"';
2044
		
2045
		if (isset($chain['return']))
2046
			$subQuery .= ', ' . $chain['return'];
2047

    
2048
		$subQuery .= ' from "' . $chain['tables'][0]['table'] . '"';
2049
		
2050
		for ($i = 1; $i < count($chain['tables']); $i++) {
2051
			$subQuery .= ' join "' . $chain['tables'][$i]['table'] .'" on "' . $chain['tables'][$i]['table'] . '"."id"="'.$chain['tables'][$i-1]['table'].'"."'.$chain['tables'][$i]['table'].'"';
2052
			
2053
			if (isset($chain['tables'][$i]['filters'])) {
2054
				foreach ($chain['tables'][$i]['filters'] as $filter) {
2055
					$subQuery .= ' and (' . $this->buildSubQueryFilter($chain['tables'][$i]['table'], $filter) . ') ';
2056
				}
2057
			}
2058
		}
2059
		
2060
		return $subQuery;
2061
	}
2062
	
2063
	private function buildSubQueryFilter($tableName, $filter) {
2064
		$column = $filter['column'];
2065
		$filterText = "";
2066
		
2067
		if (isset($filter['values'])) {
2068
			for ($fc = 0; $fc < count($filter['values']); $fc++) {
2069
				$value = $filter['values'][$fc];
2070
				
2071
				if ($fc > 0)
2072
					$filterText .= ' or ';
2073
				$filterText .= '"' . $tableName . '"."'.$column.'" = \'' . $value . '\'';
2074
			}
2075
		} else if (	isset($filter['exvalues'])) {
2076
			for ($fc = 0; $fc < count($filter['exvalues']); $fc++) {
2077
				$value = $filter['exvalues'][$fc];
2078

    
2079
				if ($fc > 0)
2080
					$filterText .= ' and ';
2081
				$filterText .= '"' . $tableName . '"."'.$column.'" != \'' . $value . '\'';
2082
			}
2083
		} else if (isset($filter['max'])) {
2084
			if (strstr($column, 'year') && $filter['max'] == 'today') {
2085
				$filterText = $column . ' <= extract(YEAR from now()) and ' . $column . ' >= ' . $filter['min'];
2086
			} else 	if (strstr($column, 'year') && $filter['min'] == 'today') {
2087
				$filterText = $column . ' >= extract(YEAR from now()) and ' . $column . ' <= ' . $filter['max'];
2088
			} else {
2089
				$filterText = $column . ' >= ' . $filter['min'] . ' and ' . $column . ' <= ' . $filter['max'];
2090
			}
2091
		}
2092
		
2093
		return $filterText;
2094
	}
2095
}
2096

    
2097
?>
(1-1/19)