Project

General

Profile

1 37810 eri.katsar
<?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
//todo changed this from 0 to -1 to disable timeouts
48
					"read_write_timeout" => -1));
49
50
        		$this->cache->connect();
51
52
				$this->log->info("redis host: ".$redis_host);
53
				$this->log->info("redis port: ".$redis_port);
54
55
			} catch(Exception $e) {
56
				$this->log->error("Error connecting to Redis server: ".$e->getMessage());
57
				$this->cache = null;
58
			}
59
60
		} else {
61
			$this->log->info("Class Predis does not exist\n");
62
		}
63
	}
64
65
	// initialises the arrays containing the warehouse schema, via an xml that describes them
66
	//TODO: insert checks on whether the data in the xml are correct (get schema from db)
67
	function loadSchema($file = null) {
68
		if(file_exists($file)) {
69
			$json = file_get_contents($file);
70
			//$this->log->info('schema of database: '.json_encode((array) simplexml_load_string($json)));
71
			$this->schema = json_decode(json_encode((array) simplexml_load_string($json)),1);
72
		}
73
		else {
74
			echo "loadSchema: could not find the xml";
75
			$this->log->error('loadSchema: could not find the xml');
76
			return -1;
77
		}
78
		foreach ($this->schema['table'] as $table) {
79
			switch ($table['type']) {
80
				case 'fact': array_push($this->facts,$table);
81
					break;
82
				//case 'm': array_push($this->metadata,$table);
83
				//	break;
84
				default: array_push($this->dimensions,$table);
85
					break;
86
			}
87
		}
88
		$this->log->info("loaded schema");
89
	}
90
91
92
	function doConnect($file) {
93
		try {
94
			switch($GLOBALS['type']){
95
				case 'postgres':
96
					$this->db = new PDO('pgsql:host='.$GLOBALS['host'].';port=5432;dbname='.$GLOBALS['db_name'].';user='.$GLOBALS['username'].';password='.$GLOBALS['password']);
97
					break;
98
				case 'sqlite':
99
					$this->db = new PDO('sqlite:'.$GLOBALS['head'].$GLOBALS['db_name']);
100
					break;
101
				default:
102
					echo "not known database type\n";
103
					break;
104
			}
105
		} catch(Exception $e){
106
			echo "oops..".$e->getMessage()."\n";
107
			$this->log->fatal($e->getMessage());
108
			return false;
109
		}
110
		$this->schema_file = $file;
111
		$this->loadSchema($file);
112
	}
113
114
	function doDisconnect($save = false) {
115
		if($save) {
116
			$fp = fopen($this->schema_file,"w");
117
			$data = "<schema>\n".toxml($this->schema,"schema",1)."\n</schema>\n";
118
			fwrite($fp,$data);
119
			fclose($fp);
120
		}
121
		$this->db = null;
122
	}
123
124
	function beginTrans() {
125
		$this->db->beginTransaction();
126
	}
127
128
	function doCommit() {
129
		$this->db->commit();
130
	}
131
132
//TODO here predis cache is checked and the query is submitted to the DB
133
134
	function doQuery($query, $fetchMode=PDO::FETCH_BOTH,$persistent){
135
136
		if($this->cache != null){
137
		      //TODO md5($query) -> REDIS hash set keys
138
			$myKey = md5($query);
139
			$this->log->debug("Searching for key: ".$myKey);
140
141
			if($this->cache->exists($myKey)) {
142
143
				$results = $this->cache->hget($myKey, "results");
144
				return json_decode($results, true);
145
146
			} else {
147
148
				$this->log->debug("not found in cache");
149
				$results = $this->doQueryNoCache($query, $fetchMode);
150
				$this->log->info("adding in cache. key: ".$myKey);
151
152
				if($persistent==null||$persistent=='1')
153
  			          {$persistent = "true";}
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
{
158
  					$this->cache->save();
159
  				}
160
  				return $results;
161
			}
162
		} else {
163
			return $this->doQueryNoCache($query, $fetchMode);
164
		}
165
	}
166
167
	function doQueryNoCache($query, $fetchMode=PDO::FETCH_BOTH) {
168
169
		$stmt = $this->db->query($query);
170
		if(!$stmt){
171
			$arr = $this->db->errorInfo();
172
			$this->log->error($arr[2]);
173
			return null;
174
		}
175
		return $stmt->fetchAll($fetchMode);
176
	}
177
178
	function doPrepare($query){
179
		$stmt = $this->db->prepare($query);
180
		if(!$stmt){
181
			$arr = $this->db->errorInfo();
182
			$this->log->error($arr[0]." ".$arr[1]." ".$arr[2]);
183
			return false;
184
		}
185
		return $stmt;
186
	}
187
188
	function doExecute($stmt){
189
		if(!$stmt->execute()){
190
			$arr = $stmt->errorInfo();
191
			$this->log->error($arr[2]);
192
			return false;
193
		}
194
		return $stmt;
195
	}
196
197
//-------------------------------------------------------------------------------------\\
198
//-------------------------------------------------------------------------------------\\
199
//------------------------------CHECKS, GETTERS, SETTERS-------------------------------\\
200
//-------------------------------------------------------------------------------------\\
201
//-------------------------------------------------------------------------------------\\
202
203
	public function printSchema() {
204
		print_r($this->schema);
205
	}
206
207
	public function getSchema() {
208
		if(isset($this->schema))
209
			return $this->schema;
210
		return null;
211
	}
212
213
	public function getFacts() {
214
		$list = $this->doQuery("select tableName from defaults order by tableorder","false");
215
		if($list != null){
216
			$sorted = array();
217
			if(isset($this->facts)) {
218
				for($i=0;$i<count($list);$i++) {
219
					foreach($this->facts as $fact){
220
						if($fact['name'] == $list[$i][0]){
221
							$sorted[] = $fact;
222
							break;
223
						}
224
					}
225
				}
226
				return $sorted;
227
			}
228
		}
229
		else
230
			return $this->facts;
231
	}
232
233
	public function getDimensions() {
234
		if(isset($this->dimensions)) {
235
			return $this->dimensions;
236
		}
237
		return null;
238
	}
239
240
	public function getFactsNames() {
241
		$names = array();
242
		if(isset($this->facts)) {
243
			foreach($this->facts as $fact) {
244
				array_push($names,$fact['name']);
245
			}
246
			return $names;
247
		}
248
		return null;
249
	}
250
251
	function getType($oldType) {
252
		switch ($oldType) {
253
			case 'int':
254
			case 'double':
255
				return 'number';
256
				break;
257
			case 'varchar':
258
			case 'datetime':
259
				return 'string';
260
				break;
261
			case 'bool':
262
				return 'boolean';
263
				break;
264
			default:
265
				return false;
266
		}
267
	}
268
269
	/*returns an array with the triplet (name,type,view) for each of the keys of the dimension table
270
	or false on failure
271
	type is either number, string or boolean //? need to add more ?*/
272
	function findKeys($table) {
273
		$myarray = array();
274
		if($table == false) {
275
			$this->log->error('findKeys: no table indicated');
276
			return false;
277
		}
278
		if(is_array($table['key'])) {
279
			foreach($table['key'] as $key) {
280
				$keyInfo = $this->findOneField($table,$key,'attrib');
281
				array_push($myarray,$keyInfo);
282
			}
283
		}
284
		else {
285
			$keyInfo = $this->findOneField($table,$table['key'],'attrib');
286
			array_push($myarray,$keyInfo);
287
		}
288
		return $myarray;
289
	}
290
291
	//returns an array with the tetraplet (name,type,view,data) for each of the meas of the fact table or false on failure
292
	//type is either number, string or boolean //? need to add more ?
293
	function findMeas($table) {
294
		$myarray = array();
295
		if($table == false) {
296
			$this->log->error('findMeas: no table indicated');
297
			return false;
298
		}
299
		if(isset($table['meas'][0])) {
300
			foreach($table['meas'] as $meas) {
301
				if(isset($meas['view'])) {
302
					$view = $meas['view'];
303
				}
304
				else
305
					$view = $meas['name'];
306
				array_push($myarray,array($meas['name'],$view,$meas['type'],$meas['data']));
307
			}
308
		}
309
		else {
310
			if(isset($table['meas']['view'])) {
311
				$view = $meas['view'];
312
			}
313
			else
314
				$view = $meas['name'];
315
			array_push($myarray,array($meas['name'],$view,$meas['type'],$meas['data']));
316
		}
317
		return $myarray;
318
	}
319
320
	function getDims() {
321
		return $this->dimensions;
322
	}
323
324
	function findOneField($table,$name,$ftype) {
325
		$field = search($table[$ftype],'name',$name);
326
		if(count($field)!=1) {
327
			$this->log->error('error in xml');
328
			return false;
329
		}
330
331
		$type = $this->getType($field[0]['type']);
332
333
		if(isset($field[0]['view'])) {
334
			$view = $field[0]['view'];
335
		}
336
		else
337
			$view = $field[0]['name'];
338
339
		return array($field[0]['name'],$type,$view,$field[0]['data']);
340
341
	}
342
343
	function getField($table,$name,$ftype) {
344
		$field = search($table[$ftype],'name',$name);
345
		if(count($field)!=1) {
346
			$this->log->error('error in xml');
347
			return false;
348
		}
349
350
		return $field[0];
351
	}
352
353
	function findTable($name,$type) {
354
		if($type == 'dimension') {
355
			$all_matching_files = search($this->dimensions,'name',$name);
356
		}
357
		elseif($type == 'fact') {
358
			$all_matching_files = search($this->facts,'name',$name);
359
		}
360
		else {
361
			$this->log->error('findTable: could not recognise type '.$type);
362
			return false;
363
   		}
364
		if(count($all_matching_files)==0) {
365
			$this->log->error('xml file error: table: '.$name.' not found');
366
			return false;
367
		}
368
		$matching_files = search($all_matching_files,'type',$type);
369
		if(count($matching_files)!=1) {
370
			$this->log->error('multiple '.$type.'s with name: '.$name);
371
			return false;
372
		}
373
		return $matching_files[0];
374
375
	}
376
377
	//checks if a fact table with exactly the given dimensions exist
378
	function searchWarehousebyDims($dims) {
379
		$flag = false;
380
381
		foreach($this->facts as $warehouse) {
382
383
			//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
384
			if(count($warehouse['dim']) != count($dims)){
385
				continue;
386
			}
387
			foreach($dims as $dim) {
388
				$res = search($warehouse['dim'], 'name', $dim);
389
				if(count($res) != 0) {
390
					$flag = true;
391
				}
392
				else {
393
					$flag = false;
394
					break;
395
				}
396
			}
397
			if($flag == true)
398
				return $warehouse['name'];
399
		}
400
		//not found
401
		return false;
402
	}
403
404
	/*check if a name is already in use for a fact table
405
	if yes, return false, otherwise, return true*/
406
	function checkName($name) {
407
		if(findTable($name,"fact") != false) {
408
			return true;
409
		}
410
		return false;
411
	}
412
413
	/*check if a name is already in use for a dimension table
414
	 if yes, return true, otherwise, return false*/
415
	function checkDim($name) {
416
		if(findTable($name,"dimension") != false) {
417
			return true;
418
		}
419
		return false;
420
	}
421
422
	function findTableType($name) {
423
		if($this->findTable($name,"dimension") != false) {
424
			return "dimension";
425
		}
426
		if($this->findTable($name,"fact") != false) {
427
			return "fact";
428
		}
429
		return false;
430
	}
431
432
	/*check if a list of dims all exist in the schema
433
		returns a list with all dims that don't exist or true
434
	*/
435
	function checkListofDims($dims) {
436
		$non_existent = array();
437
		$flag = true;
438
		foreach($dims as $dim) {
439
			if(checkDim($dim) == true){
440
				array_push($non_existent,$dim);
441
				$flag = false;
442
			}
443
		}
444
		if($flag == true)
445
			return true;
446
		else
447
			return $non_existent;
448
	}
449
450
	function checkMeas($fact, $meas_name) {
451
		//find the fact table
452
		//if there is a meas with the same name
453
		foreach($this->facts as $table)
454
			if($table['name'] == $fact)
455
				foreach($table['meas'] as $meas) {
456
					if($meas['name'] == $meas_name){
457
						return true;
458
					}
459
				}
460
			return false;
461
	}
462
463
	function getAllDims() {
464
		$dimnames = array();
465
		foreach($this->dimensions as $dim) {
466
			array_push($dimnames,$dim['name']);
467
		}
468
		return $dimnames;
469
	}
470
471
	function getDimsFieldsList($tableName) {
472
		$fields = array();
473
		//find the table
474
		$table = $this->findTable($tableName,'dimension');
475
		if($table == false) {
476
			return false;
477
		}
478
		foreach($table['attrib'] as $field) {
479
			if($field['name'] == 'id')
480
				continue;
481
			if(isset($field['analysed'])) {
482
				$fields = array_merge($fields,$this->getDimsFieldsList($field['analysed']));
483
			}
484
			else {
485
				if(isset($field['view']))
486
					$view = $field['view'];
487
				else
488
					$view = $field['name'];
489
				array_push($fields,array($tableName.".".$field['name'],$tableName.".".$view,$field['type'],$field['data']));
490
			}
491
		}
492
		return $fields;
493
	}
494
495
	function getDimsList($tablename) {
496
		$fields = array();
497
		//find the factable
498
		$table = $this->findTable($tablename,'fact');
499
		if($table == false) {
500
			return false;
501
		}
502
		foreach($table['dim'] as $dim) {
503
			$temp = $this->getDimsFieldsList($dim['name']);
504
			$fields = array_merge($fields, $temp);
505
		}
506
		return $fields;
507
	}
508
509
	function getDimsKeys($dimName) {
510
		$table = $this->findTable($dimName,'dimension');
511
		if($table == false) {
512
			return false;
513
		}
514
		return $table['key'];
515
	}
516
517
//-------------------------------------------------------------------------------------\\
518
//-------------------------------------------------------------------------------------\\
519
//----------------------------------DATA READING---------------------------------------\\
520
//-------------------------------------------------------------------------------------\\
521
//-------------------------------------------------------------------------------------\\
522
523
function getMeasMetadata($table) {
524
	$query = 'select name, source, sourceUrl, definition, unit from Metadata where inTable="'.$table.'"';
525
	$this->log->info("getMeasMetadata -> generated query: ".$query);
526
	$res = $this->doQuery($query);
527
	if($res == null)
528
		return "false";
529
530
	return $res;
531
}
532
533
/*
534
gets the name of a fact table and the name of a measurement and returns the minimun, maximum and count distinct values for it
535
*/
536
function measRangeData($facttable, $measurement) {
537
	$query = "SELECT min($measurement), max($measurement), count(distinct $measurement) FROM $facttable WHERE $measurement != ''";
538
	$this->log->info("generated query: ".$query);
539
	$res = $this->doQuery($query);
540
	$res=$res[0];
541
	return array($res[0],$res[1],$res[2]);
542
}
543
544
//return the minimun, maximum
545
function getRangeData($table, $field) {
546
	$query = 'SELECT min("'.$field.'"), max("'.$field.'") FROM "'.$table.'"';
547
	if($GLOBALS['type'] == "sqlite")
548
		$query .= ' WHERE "'.$field.'" != ""';
549
	$this->log->info("generated query: ".$query);
550
	$res = $this->doQuery($query);
551
	$res = $res[0];
552
	return array("min"=>$res[0],"max"=>$res[1]);
553
}
554
555
//return the distinct values
556
function getDistinctValues($table, $field) {
557
	$query = 'select distinct "'.$field.'" from "'.$table.'" order by "'.$field.'"';
558
	$this->log->info("generated query: ".$query);
559
	$res = $this->doQuery($query, PDO::FETCH_NUM);
560
	return $res;
561
}
562
563
function getFilterData($table,$field){
564
	$flag = false;
565
	$myDimTable = $this->findTable($table,'dimension');
566
	$myFactTable = $this->findTable($table,'fact');
567
	//is it a dim?
568
	if($myDimTable != false){
569
		//does it have the field?
570
		if(!isAssoc($myDimTable['attrib'])){
571
			foreach($myDimTable['attrib'] as $attrib){
572
				if($attrib['name'] == $field){
573
					$myField = $attrib;
574
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
575
				}
576
			}
577
		}
578
		else{
579
			if($myDimTable['attrib']['name'] == $field){
580
				$myField = $myDimTable['attrib'];
581
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
582
			}
583
		}
584
	}
585
	if($myFactTable != false){
586
		//look in the dims
587
		if(!isAssoc($myFactTable['dim'])){
588
			foreach($myFactTable['dim'] as $dim) {
589
				if($dim['name'] == $field){
590
					$myField = $dim;
591
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
592
				}
593
			}
594
		}
595
		else{
596
			if($myFactTable['dim']['name'] == $field){
597
				$myField = $myFactTable['dim'];
598
				//$flag = true;
599
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
600
			}
601
		}
602
		if(!isAssoc($myFactTable['meas'])){
603
			foreach($myFactTable['meas'] as $meas) {
604
				if($meas['name'] == $field){
605
					$myField = $meas;
606
					return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
607
				}
608
			}
609
		}
610
		else{
611
			if($myFactTable['meas']['name'] == $field){
612
				$myField = $myFactTable['meas'];
613
				return array_merge(array('type'=>$myField['data'],'data'=>$this->getDistinctValues($table, $field)),$this->getRangeData($table, $field));
614
			}
615
		}
616
		$this->log->error('cannot find field '.$field.' in table '.$table);
617
		return "cannot find field ".$field;
618
	}
619
620
	$this->log->error("cannot find table ".$table);
621
	return "cannot find table ".$table;
622
}
623
624
	function getDefaultData($table) {
625
		$this->log->info("DefaultData -> table:".$table);
626
		if($table !=null && $table!='null') {
627
			$query = 'select * from "defaults" where tablename='."'".$table."'";
628
		}
629
		else{
630
			$query = 'select * from "defaults" where tableorder=(select min(tableorder) from "defaults")';
631
		}
632
		$this->log->info("DefaultData -> query created: ".$query);
633
		$res = $this->doQuery($query,"false");
634
		if($res == null)
635
			return "empty";
636
637
		$selectedData = array();
638
		$selectedData['table'] = $res[0][0];
639
		$selectedData['fields'] = array();
640
		$selectedData['fields'][0] = array();
641
		$selectedData['fields'][0]['fld'] = $res[0][2];
642
		$selectedData['fields'][0]['agg'] = $res[0][3];
643
		$selectedData['fields'][0]['id'] = 0;
644
		$selectedData['fields'][0]['type'] = "";
645
		$selectedData['fields'][0]['yaxis'] = 1;
646
		$selectedData['xaxis']['name'] = $res[0][1];
647
		$selectedData['xaxis']['agg'] = 'avg';
648
		$selectedData['group'] = '';
649
		$selectedData['color'] = '';
650
		if($this->checkMeas($selectedData['table'], $selectedData['xaxis']['name'])){
651
			$type='scatter';
652
			$selectedData['type'] = 'scatter';
653
		}
654
		else{
655
			$selectedData['type'] = 'chart';
656
			$type = $res[0][5];
657
		}
658
		$selectedData['size'] = $GLOBALS['size'];
659
		return array('selectedData'=>$selectedData,'type'=>$type);
660
		//return array('selectedData'=>$selectedData, 'data'=>$this->getData($selectedData),'type'=>$type);
661
	}
662
663
/*
664
domi tou selectedData:
665
['table'] = fact table name
666
['fields'] = [{'fld':field name,'agg':aggregator for the field,'id': de mas noiazei}, ...]
667
['series'] = [dim field name with the list of the dim tables names that lead to it (eg: Product-Supplier-sup_name), ...]
668
['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
669
['xaxis'] = {'name': to onoma tou dim h meas pou paei ston x axis, 'agg': o aggregator an einai meas}
670
['type'](optional)
671
stin apli periptwsi to series einai panta keno
672
sto telos exoume tosa series osa fields (to poly 3)
673
674
an sto xaxis exoume meas tote exoume scatter plot kai den bazoume to xaxis sto group by
675
an den exoume series tote den exoume group by kai agnooume ta aggs
676
*/
677
/*
678
domi tou query:
679
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
680
ok	from: to table AND ola osa emfanizontai sto series kai to xaxis
681
	where: 1 zeygari gia kathe syndyasmo diplanwn pinakwn pou emfanizetai sto series kai twn arxikwn me to table
682
	(eg: gia to Product-Supplier tha exoume ena zeygari to Product,Supplier kai ena to Facttable,Product)
683
ok	group by: to xaxis kai ola ta series opws akribws kai sto select
684
ok	order by: to xaxis
685
*/
686
	function makeQueryGroup($sel,$persistent){//print_r($sel);
687
		$this->log->info("makeQueryGroup");
688
		/*
689
		select agg(field), xaxisfield, groupfield
690
		from facttable, xaxistables, grouptables
691
		where facttable = xaxistables and xaxistables and facttable = groupstables and groupstables
692
		group by groupfield, xaxisfield (ektos ki an einai meas)
693
		order by groupfield, xaxisfield
694
		*/
695
		$isMeas = false;
696
		$field = "";
697
		$xaxisfield = "";
698
		$groupfield = "";
699
		$tables = array();
700
		$tablesPairs = array();
701
		$tables[] = $sel['table'];
702
		/*yaxis*/ //<---- panta measurement
703
		$field = '"'.$sel['fields'][0]['fld'].'"';
704
		/*xaxis*/
705
		$xaxislist = explode("-",$sel['xaxis']['name']);
706
		if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1])){
707
			$isMeas = true;
708
		}
709
		if(!$isMeas){
710
			//an den einai measurement tote einai dimension kai mporei na exei tables
711
			if(count($xaxislist) == 1){ //einai dim alla den analyetai se pinaka
712
				$xaxisfield = '"'.$sel['table'].'"."'.$xaxislist[count($xaxislist)-1].'"';
713
			}
714
			else{
715
				$xaxisfield = '"'.$xaxislist[count($xaxislist)-2].'"."'.$xaxislist[count($xaxislist)-1].'"';
716
717
				//briskw tous pinakes enan enan kai tous bazw sta pairs alla kai sto xaxistables
718
				for($i=0;$i<count($xaxislist)-1;$i++){
719
					if(!in_array($xaxislist[$i],$tables)){
720
						$tables[] = $xaxislist[$i];
721
					}
722
					if($i == count($xaxislist)-2){
723
						if(!in_array_r(array($sel['table'],$xaxislist[$i]), $tablesPairs)){
724
							$tablesPairs[] = array($sel['table'],$xaxislist[$i]);
725
						}
726
					}
727
					else{
728
						if(!in_array_r(array($xaxislist[$i],$xaxislist[$i+1]),$tablesPairs))
729
							$tablesPairs[] = array($xaxislist[$i],$xaxislist[$i+1]);
730
					}
731
				}
732
			}
733
		}
734
		else {
735
			//einai meas, den kanw tipota
736
			$xaxisfield = '"'.$sel['table'].'"."'.$sel['xaxis']['name'].'"';
737
			$xaxistables = null;
738
		}
739
		/*group*/
740
		//briskw tous pinakes tou group field kai tous bazw enan enan sto table alla kai sta pairs
741
		$grouplist = explode("-",$sel['group']);
742
		if(count($grouplist) == 1){ //einai dim alla den analyetai se pinaka
743
			$groupfield = '"'.$sel['table'].'"."'.$grouplist[count($grouplist)-1].'"';
744
		}
745
		else{
746
			$groupfield = '"'.$grouplist[count($grouplist)-2].'"."'.$grouplist[count($grouplist)-1].'"';
747
			//briskw tous pinakes enan enan kai tous bazw sta pairs alla kai sto xaxistables
748
			for($i=0;$i<count($grouplist)-1;$i++){
749
				if(!in_array($grouplist[$i],$tables)){
750
					$tables[] = $grouplist[$i];
751
				}
752
				if($i == count($grouplist)-2){
753
					if(!in_array_r(array($sel['table'],$grouplist[$i]), $tablesPairs)){
754
						$tablesPairs[] = array($sel['table'],$grouplist[$i]);
755
					}
756
				}
757
				else{
758
					if(!in_array_r(array($grouplist[$i],$grouplist[$i+1]),$tablesPairs))
759
						$tablesPairs[] = array($grouplist[$i],$grouplist[$i+1]);
760
				}
761
			}
762
		}
763
		//steinw to query
764
		$query = "select ";
765
		/*xaxis*/
766
		if($isMeas && $sel['color'] != 'yes'){ // prepei na balw kai ton aggregator
767
			switch($sel['xaxis']['agg']){
768
				case 'none':
769
				case '':
770
				case 'avg':
771
					$query .= " avg(".$xaxisfield.") ";
772
					break;
773
				default:
774
					$query .= $sel['xaxis']['agg']."(".$xaxisfield.") ";
775
					break;
776
			}
777
		}
778
		else{
779
			$query .= " ".$xaxisfield;
780
		}
781
		/*yaxis*/
782
		if($sel['color'] != 'yes')
783
			switch($sel['fields'][0]['agg']){
784
				case 'none':
785
				case '':
786
				case 'avg':
787
					$query .= ", avg(".$field.") ";
788
					break;
789
				default:
790
					$query .= ", ".$sel['fields'][0]['agg']."(".$field.") ";
791
					break;
792
			}
793
		else
794
			$query .= ', '.$field;
795
796
		/*group*/
797
		$query .= ", ".$groupfield;
798
799
		$query .= " from ".implode(", ",$tables);
800
		$query .= " where ";
801
		for($i=0;$i<count($sel['fields']);$i++) {
802
			if($i!=0) $query .=" and ";
803
			$query .= '"'.$sel['fields'][$i]['fld'] .'" !=""';
804
		}
805
806
		if(count($tablesPairs) > 0){
807
			$query .= " and ";
808
			for($i=0;$i<count($tablesPairs);$i++){
809
				$query .= '"'.$tablesPairs[$i][0].'"."'.$tablesPairs[$i][1].'"="'.$tablesPairs[$i][1].'".id';
810
				if($i!=count($tablesPairs)-1) 	$query .= "and ";
811
				else $query .= " ";
812
			}
813
		}
814
		else $query .= ' ';
815
		if($sel['color'] != 'yes'){
816
			$query .= "group by ".$groupfield;
817
			if(!$isMeas){
818
				$query .=", ".$xaxisfield;
819
			}
820
		}
821
		$query .= " order by ".$groupfield.", ".$xaxisfield;
822
		$this->log->info("generated query: ".$query);
823
		$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
824
		if($isMeas) $returnType = 'scatter';
825
		else $returnType = 'chart';
826
		return array('type'=>$returnType,'data'=>$res,'accomDims'=>$dimsList['fields']);
827
	}
828
829
	function getData($sel,$persistent){
830
		$this->log->info("getting data");
831
		$xaxislist = explode("-",$sel['xaxis']['name']);
832
		$groups = array();
833
		$brsels = array(); $queries = array();
834
		$breakflag = false;
835
836
837
838
                     //check if we need to break the query to many (if there are filters that apply to only one field)
839
		if(count($sel['fields']) > 1){
840
			for($i=0;$i<count($sel['filters']);$i++)
841
				if(isset($sel['filters'][$i]['to']) && $sel['filters'][$i]['to'] != -1){
842
					if(!in_array($sel['filters'][$i]['to'],$groups))
843
						$groups[] = $sel['filters'][$i]['to'];
844
					$breakflag = true;
845
				}
846
			for($i=0;$i<count($sel['having']);$i++)
847
				if(isset($sel['having'][$i]['to']) && $sel['having'][$i]['to'] != -1){
848
					if(!in_array($sel['having'][$i]['to'],$groups))
849
						$groups[] = $sel['having'][$i]['to'];
850
					$breakflag = true;
851
				}
852
		}
853
		if($breakflag){
854
			$this->log->info("NEED TO BREAK!");
855
			//will break the query into as many as the different values in the filters and havings to attribute -> count($groups)
856
			$brsels[] = $this->clearselections($sel,$groups,-1,0);
857
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
858
				$queries[] = $this->scatterData($brsels[0],false);
859
			else
860
				$queries[] = $this->chartData($brsels[0],false);
861
			for($i=0;$i<count($groups);$i++){
862
				$brsels[] = $this->clearselections($sel,$groups,$groups[$i],$i+1);
863
864
				if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
865
					$queries[] = $this->scatterData($brsels[$i+1],false);
866
				else
867
					$queries[] = $this->chartData($brsels[$i+1],false);
868
			}
869
870
			$this->log->info("selections: ".print_r($brsels,true));
871
			$this->log->info("user selections updated: ".print_r($sel,true));
872
			$this->log->info("queries: ".print_r($queries,true));
873
			//get all the queries and combine them to one
874
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
875
				return $this->makeSuperQuery($queries,$sel,"scatter",$persistent);
876
			else
877
				return $this->makeSuperQuery($queries,$sel,"chart",$persistent);
878
		}
879
		else{
880
			$this->log->info("NO NEED TO BREAK!");
881
			if($this->checkMeas($sel['table'], $xaxislist[count($xaxislist)-1]))
882
				return $this->scatterData($sel,$persistent);
883
			else
884
				return $this->chartData($sel,true,$persistent);
885
		}
886
	}
887
888
	private function makeSuperQuery($queries,$sel,$type,$persistent){
889
		$superquerySelects = "SELECT ";
890
		$superquerySelecte = " ";
891
		$superqueryFrom = " FROM ";
892
		$superquerySort = "";
893
		//ta pedia tou xaxis kai tou group tha einai ayta tou outer join
894
		//sta select yparxei prwta to xaxis, meta i lista me ta fields onomatismena, kai meta an yparxei to group
895
		//sto megalo select tha yparxei gia kathe query to xaxis, meta ola ta fields twn queries me ti seira pou einai sto sel
896
		//kai meta gia kathe query to group field
897
898
		//prepei na kseroume kathe pedio tou select se poio query anikei, kai to pedio tou order by
899
		for($q=0;$q<count($queries);$q++){//xaxis
900
			//if($q>0) $superquerySelects .= ", ";
901
			$superquerySelects .= "q".$q.".xfield, ";
902
			if($q>0) $superquerySort .= ", ";
903
			$superquerySort .= "q".$q.".xfield ";
904
905
			if($sel['group']!='' && $sel['group'] != 'no'){//dimfields
906
				/*if($q>0)*/ $superquerySelecte .= ", ";
907
				$superquerySelecte .= "q".$q.".dimfield ";
908
				$superquerySort .= ", q".$q.".dimfield ";
909
			}
910
911
			$superqueryFrom .= "(".$queries[$q].") as q".$q;
912
913
			if($q>0){
914
				$superqueryFrom .= " ON q".($q-1).".xfield = q".$q.".xfield ";
915
				if($sel['group']!='' && $sel['group'] != 'no')
916
					$superqueryFrom .= " AND q".($q-1).".dimfield = q".$q.".dimfield ";
917
			}
918
919
			if($q<count($queries)-1) {
920
				$superqueryFrom .= " FULL JOIN ";
921
			}
922
923
		}
924
		for($f=0;$f<count($sel['fields']);$f++){//fields
925
			$superquerySelects .= "q".$sel['fields'][$f]['q'].".field".$sel['fields'][$f]['i'];
926
			if($f<(count($sel['fields'])-1)) $superquerySelects .=", ";
927
		}
928
		if(isset($sel['sort']) && $sel['sort']!='xaxis'){
929
			$ex = explode(".", $sel['sortq']);
930
			$temp = "q".$ex[0].".field".$ex[1];
931
932
			if($sel['order'] && $sel['order'] == 'd')
933
				$temp.= " DESC, ";
934
			else
935
				$temp .= ", ";
936
937
			$superquerySort = $temp . $superquerySort;
938
		}
939
940
		$superquerySort = " ORDER BY ".$superquerySort;
941
942
		$superQuery = $superquerySelects.$superquerySelecte.$superqueryFrom.$superquerySort." LIMIT ".$sel['size'];
943
		$this->log->info("superquery: ".$superQuery);
944
		$res = $this->doQuery($superQuery, PDO::FETCH_NUM,$persistent);
945
		return $this->combineData($res,count($queries),count($sel['fields']),$type);
946
	}
947
948
	private function combineData($data,$queries,$fields,$type){
949
		$newdata = array();
950
		if(count($data[0]) > $queries+$fields)
951
			$dstart = $queries + $fields;
952
		else
953
			$dstart = -1;
954
		$fstart = $queries;
955
		for($d=0;$d<count($data);$d++){
956
			$newdata[$d] = array();
957
			for($i=0;$i<$queries;$i++)
958
				if($data[$d][$i] != null){
959
					$newdata[$d][0] = $data[$d][$i];
960
					break;
961
				}
962
			for($i=$fstart;$i<$fields+$queries;$i++)
963
				$newdata[$d][$i-$fstart+1] = $data[$d][$i];
964
			if($dstart > 0)
965
				for($i=$dstart;$i<count($data[0]);$i++)
966
					if($data[$d][$i] != null){
967
						$newdata[$d][$fields+1] = $data[$d][$i];
968
						break;
969
					}
970
		}
971
		$this->log->info("superquerys result: ".print_r($newdata,true));
972
		return array('type'=>$type,'data'=>$newdata);
973
	}
974
975
	private function clearselections(&$sel,$seperate,$field,$index){
976
		$newsel = array();
977
		$fields = array();
978
		$newsel['table'] = $sel['table'];
979
		$newsel['xaxis'] = $sel['xaxis'];
980
		$newsel['group'] = $sel['group'];
981
		$newsel['color'] = $sel['color'];
982
		$newsel['size'] = $sel['size'];
983
		$newsel['fields'] = array();
984
		$newsel['filters'] = array();
985
		$newsel['having'] = array();
986
		if($field == -1 || $field == -2){ //things that apply to whole chart, will remove only the things that apply to one field and that field
987
			for($i=0;$i<count($sel['fields']);$i++){
988
				if(!in_array($i+1,$seperate)){
989
					$newsel['fields'][] = $sel['fields'][$i];
990
					$sel['fields'][$i]['q'] = $index;
991
					$sel['fields'][$i]['i'] = count($newsel['fields'])-1;
992
					$fields[] = $sel['fields'][$i]['agg'] + "-" + $sel['fields'][$i]['fld'];
993
				}
994
			}
995
			for($i=0;$i<count($sel['filters']);$i++){
996
				if(!isset($sel['filters'][$i]['to']) || $sel['filters'][$i]['to'] == -1){
997
					$newsel['filters'][] = $sel['filters'][$i];
998
				}
999
			}
1000
			for($i=0;$i<count($sel['having']);$i++){
1001
				if(!isset($sel['having'][$i]['to']) || $sel['having'][$i]['to'] == -1){
1002
					$newsel['having'][] = $sel['having'][$i];
1003
				}
1004
			}
1005
			if(in_array($sel['sort'],$fields)){
1006
				$sel['sortq'] = $index.".".(count($newsel['fields'])-1);
1007
				//$newsel['sort'] = $sel['sort'];
1008
			}
1009
			//else
1010
				//$newsel['sort'] = 'xaxis';
1011
		}
1012
		else{ //we keep only the field, and the filters and havings that apply to that and the whole chart
1013
			$newsel['fields'][] = $sel['fields'][$field-1];
1014
			$sel['fields'][$field-1]['q'] = $index;
1015
			$sel['fields'][$field-1]['i'] = count($newsel['fields'])-1;
1016
			for($i=0;$i<count($sel['filters']);$i++){
1017
				if(isset($sel['filters'][$i]['to']) && ($sel['filters'][$i]['to'] == $field || $sel['filters'][$i]['to'] == -1)){
1018
					$newsel['filters'][] = $sel['filters'][$i];
1019
				}
1020
			}
1021
			for($i=0;$i<count($sel['having']);$i++){
1022
				if(isset($sel['having'][$i]['to']) && $sel['having'][$i]['to'] == $field){
1023
					$newsel['having'][] = $sel['having'][$i];
1024
				}
1025
			}
1026
			if(in_array($sel['sort'],$fields)){
1027
				$newsel['sort'] = $sel['sort'];
1028
			}
1029
			else
1030
				$newsel['sort'] = 'xaxis';
1031
		}
1032
		return $newsel;
1033
	}
1034
1035
	function chartData($sel, $doquery=true,$persistent){
1036
		if($sel['group']!='' && $sel['group'] != 'no'){	//group
1037
			return $this->chartDataGroup($sel, $doquery);
1038
		}
1039
		else{
1040
1041
$this->log->info("sel: ".print_r($sel,true));
1042
			$tree = new QueryTree($sel['table']);
1043
			$tree->updateXAxis($sel['xaxis']['name']);
1044
			$tree->updateYAxis($sel['fields']);
1045
			$tree->updateFilters($sel['filters']);
1046
			if (isset($sel['sort'])) {$tree->updateOrderBy($sel['sort']);}
1047
if(isset($sel['order'])){$tree->updateOrder($sel['order']);}
1048
if(isset($sel['size'])){$tree->updateLimit($sel['size']);}
1049
if(isset($sel['nulls'])){$tree->excludeNulls($sel['nulls']);}
1050
1051
$this->log->info("tree: ".print_r($tree->tree, true));
1052
1053
			$query = $tree->getQuery();
1054
1055
			if(!$doquery){
1056
				$this->log->info('chartData generated query:'.$query);
1057
				$this->log->info('will not execute it');
1058
				return $query;
1059
			}
1060
1061
			$this->log->info('chartData generated tree: '.print_r($tree->getTree(), true));
1062
			$this->log->info('chartData generated query: '.$query);
1063
			$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1064
			$this->log->info("result: ".print_r($res,true));
1065
			return array('type'=>'chart','data'=>$res);
1066
		}
1067
1068
	}
1069
1070
	function chartDataGroup($sel, $doquery=true,$persistent){
1071
		//exoume dyo dims, ena tou xaxis kai ena tou group
1072
		//kanoume tin idia diadikasia kai gia ta dyo
1073
		$xfield = '';
1074
		$dimfield = '';
1075
		$tables = array();
1076
		$tablePairs = array();
1077
		$filters = array();
1078
		//order by it
1079
		//may need to join
1080
		//gia to xaxis
1081
		$dimlist = explode("-",$sel['xaxis']['name']);
1082
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1083
			$xfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1084
		}
1085
		else{
1086
			$xfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1087
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1088
			for($i=0;$i<count($dimlist)-1;$i++){
1089
				if(!in_array($dimlist[$i],$tables)){
1090
					$tables[] = $dimlist[$i];
1091
				}
1092
				if($i == 0){
1093
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1094
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1095
					}
1096
				}
1097
				else{
1098
					if(!in_array_r(array($dimlist[$i-1],$dimlist[$i]),$tablePairs))
1099
						$tablePairs[] = array($dimlist[$i-1],$dimlist[$i]);
1100
				}
1101
			}
1102
		}
1103
		//gia to group
1104
		$dimlist = explode("-",$sel['group']);
1105
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1106
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1107
		}
1108
		else{
1109
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1110
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1111
			for($i=0;$i<count($dimlist)-1;$i++){
1112
				if(!in_array($dimlist[$i],$tables)){
1113
					$tables[] = $dimlist[$i];
1114
				}
1115
				if($i == 0){
1116
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1117
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1118
					}
1119
				}
1120
				else{
1121
					if(!in_array_r(array($dimlist[$i-1],$dimlist[$i]),$tablePairs))
1122
						$tablePairs[] = array($dimlist[$i-1],$dimlist[$i]);
1123
				}
1124
			}
1125
		}
1126
		//filters
1127
		if(isset($sel['filters'])){
1128
			for($fc=0;$fc<count($sel['filters']);$fc++){
1129
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1130
				if(count($filterfields)>1){ //join needed
1131
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1132
					for($i=0;$i<count($filterfields)-1;$i++){
1133
						if(!in_array($filterfields[$i],$tables)){
1134
							$tables[] = $filterfields[$i];
1135
						}
1136
						if($i == 0){
1137
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1138
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1139
							}
1140
						}
1141
						else{
1142
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1143
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1144
							}
1145
						}
1146
					}
1147
				}
1148
				else
1149
                                	$sel['filters'][$fc]['name'] = $sel['table'].".".$sel['filters'][$fc]['name'];
1150
			}
1151
		}
1152
		//----------------------------------------------------------------//
1153
		//having
1154
		if(isset($sel['having'])){
1155
			for($fc=0;$fc<count($sel['having']);$fc++){
1156
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1157
				if(count($havingfields)>1){ //join needed
1158
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1159
					for($i=0;$i<count($havingfields)-1;$i++){
1160
						if(!in_array($havingfields[$i],$tables)){
1161
							$tables[] = $havingfields[$i];
1162
						}
1163
						if($i == 0){
1164
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1165
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1166
							}
1167
						}
1168
						else{
1169
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1170
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1171
							}
1172
						}
1173
					}
1174
				}
1175
			}
1176
		}
1177
		//----------------------------------------------------------------//
1178
		$query = 'SELECT '.$xfield.' as xfield';
1179
		for($i=0;$i<count($sel['fields']);$i++){
1180
			$query .= ', '.$sel['fields'][$i]['agg'].'("'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'") as field'.$i;
1181
		}
1182
		$query .= ', '.$dimfield.' as dimfield';
1183
		$query .= ' FROM "'.$sel['table'].'"';
1184
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1185
		/*$query .= ' WHERE "'.$sel['xaxis']['name'].'" !=""';
1186
		for($i=0;$i<count($sel['fields']);$i++){
1187
			$query .=" and ";
1188
			$query .= '"'.$sel['fields'][$i]['fld'] .'" !=""';
1189
		}*/
1190
		if(count($tablePairs) > 0 || (isset($sel['filters']) && count($sel['filters']) > 0) || $sel['nulls']){
1191
			$query .= " WHERE ";
1192
			for($i=0;$i<count($tablePairs);$i++){
1193
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1194
				if($i!=count($tablePairs)-1) 	$query .= " and ";
1195
				else $query .= " ";
1196
			}
1197
			//filters
1198
			if(isset($sel['filters']) && count($sel['filters'])>0){
1199
				if(count($tablePairs)>0)
1200
					$query .= " and ";
1201
				for($i=0;$i<count($sel['filters']);$i++){
1202
					if(isset($sel['filters'][$i]['max'])){
1203
						if(strstr($sel['filters'][$i]['name'],"year") !== false  && $sel['filters'][$i]['max']=='today')
1204
							$query .= "(".$sel['filters'][$i]['name']."<= extract(YEAR from now()) and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")";
1205
						else if(strstr($sel['filters'][$i]['name'],"year") !== false  && $sel['filters'][$i]['min']=='today')
1206
							$query .="(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">= extract(YEAR from now()))" ;
1207
						else
1208
							$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1209
					}
1210
					else if(isset($sel['filters'][$i]['values'])){
1211
						$query .= "(";
1212
						for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1213
							//$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1214
							$query .= $sel['filters'][$i]['name'].'=\''.$sel['filters'][$i]['values'][$j].'\'';
1215
							if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1216
						}
1217
						$query .= ")";
1218
					}
1219
					else if(isset($sel['filters'][$i]['exvalues'])){
1220
						$query .= "(";
1221
						for($j=0;$j<count($sel['filters'][$i]['exvalues']);$j++){
1222
							$query .= $sel['filters'][$i]['name'].'!=\''.$sel['filters'][$i]['exvalues'][$j].'\'';
1223
							if($j!=count($sel['filters'][$i]['exvalues'])-1) $query .= " and ";
1224
						}
1225
						$query .= ")";
1226
					}
1227
					//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1228
					if($i!=count($sel['filters'])-1) 	$query .= " and ";
1229
					else $query .= " ";
1230
				}
1231
			}
1232
			if($sel['nulls'] == true){//non null values from xaxis field and dimfield
1233
				if((isset($sel['filters']) && count($sel['filters'])>0) || count($tablePairs) > 0){
1234
					$query .= " and ";
1235
				}
1236
				$query .= $xfield . " IS NOT NULL AND ". $dimfield . " IS NOT NULL ";
1237
			}
1238
		}
1239
		//--------------------------------------------------------//
1240
		$query .= " GROUP BY ".$dimfield.', '.$xfield;
1241
		if(count($sel['having'])>0){
1242
			$query .= " HAVING ";
1243
			for($i=0;$i<count($sel['having']);$i++){
1244
				if($i>0)
1245
					$query .= " and ";
1246
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1247
			}
1248
1249
		}
1250
1251
		if(!$doquery){
1252
			$this->log->info('chartDataGroup generated query:'.$query);
1253
			$this->log->info('will not execute it');
1254
			return $query;
1255
		}
1256
1257
		//need to find the field to order the result set by
1258
		$query.= " ORDER BY ";
1259
		if(isset($sel['sort']) && $sel['sort']!='xaxis'){
1260
			$ex = explode("-", $sel['sort']);
1261
			$query .= $ex[0]."(".$sel['table'].".".$ex[1].")";
1262
			if($sel['order'] && $sel['order'] == 'd')
1263
				$query.= " DESC";
1264
			$query .= ", ".$xfield;
1265
		}
1266
		else{
1267
			$query.= $xfield;
1268
			if($sel['order'] && $sel['order'] == 'd')
1269
				$query.= " DESC";
1270
		}
1271
		$query.=', '.$dimfield;
1272
		$query.= " LIMIT ".$sel['size'];
1273
		//echo $query;
1274
		$this->log->info('chartDataGroup generated query:'.$query);
1275
		$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1276
		$this->log->info("result: ".print_r($res,true));
1277
		return array('type'=>'chart','data'=>$res);
1278
1279
	}
1280
1281
	function scatterData($sel, $doquery=true,$persistent){
1282
		//group, color, or nothing
1283
		//many fields or one
1284
		if($sel['group']!='' && $sel['group'] != 'no'){			//group
1285
			$this->log->info('scatterDataGroup called');
1286
			return $this->scatterDataGroup($sel, $doquery);
1287
		}
1288
		else if($sel['color']!='' && $sel['color'] != 'no'){	//color
1289
			$this->log->info('scatterDataColor called');
1290
			return $this->scatterDataColor($sel, $doquery);
1291
		}
1292
		else{													//nothing
1293
			$this->log->info('scatterData called');
1294
			//code here
1295
			//no dim to bother us, just the measurements
1296
			//TODO: get all other dims to show in tooltip
1297
			$tables = array();
1298
			$tablePairs = array();
1299
			$filters = array();
1300
			//filters
1301
			if(isset($sel['filters'])){
1302
				for($fc=0;$fc<count($sel['filters']);$fc++){
1303
					$filterfields = explode("-",$sel['filters'][$fc]['name']);
1304
					if(count($filterfields)==1){ //no join needed
1305
						;//$filters[] = $sel['filters'][$fc];
1306
                                                $sel['filters'][$fc]['name'] = $sel['table'].".".$sel['filters'][$fc]['name'];
1307
					}
1308
					else{
1309
						$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1310
						for($i=0;$i<count($filterfields)-1;$i++){
1311
							if(!in_array($filterfields[$i],$tables)){
1312
								$tables[] = $filterfields[$i];
1313
							}
1314
							if($i == 0){
1315
								if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1316
									$tablePairs[] = array($sel['table'],$filterfields[$i]);
1317
								}
1318
							}
1319
							else{
1320
								if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1321
									$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1322
								}
1323
							}
1324
						}
1325
					}
1326
				}
1327
			}
1328
			//----------------------------------------------------------------//
1329
			//having
1330
			if(isset($sel['having'])){
1331
				for($fc=0;$fc<count($sel['having']);$fc++){
1332
					$havingfields = explode("-",$sel['having'][$fc]['name']);
1333
					if(count($havingfields)>1){ //join needed
1334
						$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1335
						for($i=0;$i<count($havingfields)-1;$i++){
1336
							if(!in_array($havingfields[$i],$tables)){
1337
								$tables[] = $havingfields[$i];
1338
							}
1339
							if($i == 0){
1340
								if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1341
									$tablePairs[] = array($sel['table'],$havingfields[$i]);
1342
								}
1343
							}
1344
							else{
1345
								if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1346
									$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1347
								}
1348
							}
1349
						}
1350
					}
1351
				}
1352
			}
1353
			//----------------------------------------------------------------//
1354
			$query = 'SELECT "'.$sel['table'].'"."'.$sel['xaxis']['name'].' " as xfield';
1355
			for($i=0;$i<count($sel['fields']);$i++){
1356
				$query .= ', "'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'" as field'.$i;
1357
			}
1358
			$query .= ' FROM "'.$sel['table'].'"';
1359
			if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1360
1361
			$query .= ' WHERE ';
1362
			for($i=0;$i<count($sel['fields']);$i++){
1363
				if($i>0) $query .=" AND ";
1364
				$query .= "field".$i.'" IS NOT NULL';
1365
			}
1366
			//joins + filters
1367
			if(count($tablePairs) > 0 || (isset($sel['filters']) && count($sel['filters']) > 0) || $sel['nulls']){
1368
				$query .= " AND ";
1369
				for($i=0;$i<count($tablePairs);$i++){
1370
					$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1371
					if($i!=count($tablePairs)-1) 	$query .= " and ";
1372
					else $query .= " ";
1373
				}
1374
				if(isset($sel['filters']) && count($sel['filters'])>0){
1375
					if(count($tablePairs)>0) $query .= " and ";
1376
					for($i=0;$i<count($sel['filters']);$i++){
1377
						if(isset($sel['filters'][$i]['max'])){
1378
							$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." and ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1379
						}
1380
						else{
1381
							$query .= "(";
1382
							for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1383
								$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1384
								if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1385
							}
1386
							$query .= ")";
1387
						}
1388
						//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1389
						if($i!=count($sel['filters'])-1) 	$query .= " and ";
1390
						else $query .= " ";
1391
					}
1392
				}
1393
				if($sel['nulls'] == true){//non null values from xaxis field and dimfield
1394
					if((isset($sel['filters']) && count($sel['filters'])>0) || count($tablePairs) > 0){
1395
						$query .= " and ";
1396
					}
1397
					$query .= $xfield . " IS NOT NULL ";
1398
				}
1399
			}
1400
			if(count($sel['having'])>0){
1401
				$query .= " HAVING ";
1402
				for($i=0;$i<count($sel['having']);$i++){
1403
					if($i>0)
1404
						$query .= " and ";
1405
					$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1406
				}
1407
1408
			}
1409
			//--------------------------------------------------------//
1410
1411
			if(!$doquery){
1412
				$this->log->info('scatterData generated query:'.$query);
1413
				$this->log->info('will not execute it');
1414
				return $query;
1415
			}
1416
			$this->log->info('scatterData generated query:'.$query);
1417
			//echo "scatterplot, simple case:"; echo $query;
1418
			$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1419
1420
			$this->log->info("result: ".print_r($res,true));
1421
			return array('type'=>'scatter','data'=>$res);
1422
		}
1423
	}
1424
1425
	function scatterDataColor($sel, $doquery=true,$persistent){
1426
		//one dim, the one for the color
1427
		//TODO: get all other dims to show in tooltip
1428
		$dimfield = '';
1429
		$tables = array();
1430
		$tablePairs = array();
1431
		//order by it
1432
		//may need to join
1433
		$dimlist = explode("-",$sel['color']);
1434
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1435
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1436
		}
1437
		else{
1438
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1439
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1440
			for($i=0;$i<count($dimlist)-1;$i++){
1441
				if(!in_array($dimlist[$i],$tables)){
1442
					$tables[] = $dimlist[$i];
1443
				}
1444
				if($i == count($dimlist)-2){
1445
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1446
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1447
					}
1448
				}
1449
				else{
1450
					if(!in_array_r(array($dimlist[$i],$dimlist[$i+1]),$tablePairs))
1451
						$tablePairs[] = array($dimlist[$i],$dimlist[$i+1]);
1452
				}
1453
			}
1454
		}
1455
		//filters
1456
		if(isset($sel['filters'])){
1457
			for($fc=0;$fc<count($sel['filters']);$fc++){
1458
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1459
				if(count($filterfields)==1){ //no join needed
1460
					;//$filters[] = $sel['filters'][$fc];
1461
				}
1462
				else{
1463
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1464
					for($i=0;$i<count($filterfields)-1;$i++){
1465
						if(!in_array($filterfields[$i],$tables)){
1466
							$tables[] = $filterfields[$i];
1467
						}
1468
						if($i == 0){
1469
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1470
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1471
							}
1472
						}
1473
						else{
1474
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1475
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1476
							}
1477
						}
1478
					}
1479
				}
1480
			}
1481
		}
1482
		//----------------------------------------------------------------//
1483
		//having
1484
		if(isset($sel['having'])){
1485
			for($fc=0;$fc<count($sel['having']);$fc++){
1486
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1487
				if(count($havingfields)>1){ //join needed
1488
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1489
					for($i=0;$i<count($havingfields)-1;$i++){
1490
						if(!in_array($havingfields[$i],$tables)){
1491
							$tables[] = $havingfields[$i];
1492
						}
1493
						if($i == 0){
1494
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1495
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1496
							}
1497
						}
1498
						else{
1499
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1500
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1501
							}
1502
						}
1503
					}
1504
				}
1505
			}
1506
		}
1507
		//----------------------------------------------------------------//
1508
		$query = 'SELECT "'.$sel['table'].'"."'.$sel['xaxis']['name'].'" as xfield';
1509
		for($i=0;$i<count($sel['fields']);$i++){
1510
			$query .= ', "'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'" as field'.$i;
1511
		}
1512
		$query .= ', '.$dimfield.' as dimfield';
1513
		$query .= ' FROM "'.$sel['table'].'"';
1514
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1515
1516
		$query .= " WHERE ";
1517
		for($i=0;$i<count($sel['fields']);$i++){
1518
			if($i>0) $query .=" AND ";
1519
			$query .= "field".$i.'" IS NOT NULL';
1520
		}
1521
		if(count($tablePairs) > 0){
1522
			$query .= " AND ";
1523
			for($i=0;$i<count($tablePairs);$i++){
1524
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1525
				if($i!=count($tablePairs)-1) 	$query .= "AND ";
1526
				else $query .= " ";
1527
			}
1528
		}
1529
		//filters
1530
		if(isset($sel['filters']) && count($sel['filters'])>0){
1531
			if(count($tablePairs)>0) $query .= " AND ";
1532
			for($i=0;$i<count($sel['filters']);$i++){
1533
				if(isset($sel['filters'][$i]['max'])){
1534
					$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." AND ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1535
				}
1536
				else{
1537
					$query .= "(";
1538
					for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1539
						$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1540
						if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1541
					}
1542
					$query .= ")";
1543
				}
1544
				//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1545
				if($i!=count($sel['filters'])-1) 	$query .= " AND ";
1546
				else $query .= " ";
1547
			}
1548
		}
1549
		if(count($sel['having'])>0){
1550
			$query .= " HAVING ";
1551
			for($i=0;$i<count($sel['having']);$i++){
1552
				if($i>0)
1553
					$query .= " and ";
1554
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1555
			}
1556
1557
		}
1558
1559
		if(!$doquery){
1560
			$this->log->info('chartDataColor generated query:'.$query);
1561
			$this->log->info('will not execute it');
1562
			return $query;
1563
		}
1564
1565
		//--------------------------------------------------------//
1566
		$query .= " ORDER BY ".$dimfield;
1567
		//echo "scatterplot, case color:"; echo $query;
1568
		$this->log->info('scatterDataColor generated query:'.$query);
1569
		$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1570
1571
		$this->log->info("result: ".print_r($res,true));
1572
		return array('type'=>'scatter','data'=>$res);
1573
	}
1574
1575
	function scatterDataGroup($sel, $doquery=true,$persistent){
1576
		//one dim, the one for the group
1577
		//aggrs for all fields
1578
		//TODO: get all other dims to show in tooltip
1579
		$dimfield = '';
1580
		$tables = array();
1581
		$tablePairs = array();
1582
		//order by it
1583
		//may need to join
1584
		$dimlist = explode("-",$sel['group']);
1585
		if(count($dimlist) == 1){ //einai dim alla den analyetai se pinaka
1586
			$dimfield = '"'.$sel['table'].'"."'.$dimlist[count($dimlist)-1].'"';
1587
		}
1588
		else{
1589
			$dimfield = '"'.$dimlist[count($dimlist)-2].'"."'.$dimlist[count($dimlist)-1].'"';
1590
			//briskw tous pinakes enan enan kai tous bazw sta pairs
1591
			for($i=0;$i<count($dimlist)-1;$i++){
1592
				if(!in_array($dimlist[$i],$tables)){
1593
					$tables[] = $dimlist[$i];
1594
				}
1595
				if($i == count($dimlist)-2){
1596
					if(!in_array_r(array($sel['table'],$dimlist[$i]), $tablePairs)){
1597
						$tablePairs[] = array($sel['table'],$dimlist[$i]);
1598
					}
1599
				}
1600
				else{
1601
					if(!in_array_r(array($dimlist[$i],$dimlist[$i+1]),$tablePairs))
1602
						$tablePairs[] = array($dimlist[$i],$dimlist[$i+1]);
1603
				}
1604
			}
1605
		}
1606
		//filters
1607
		if(isset($sel['filters'])){
1608
			for($fc=0;$fc<count($sel['filters']);$fc++){
1609
				$filterfields = explode("-",$sel['filters'][$fc]['name']);
1610
				if(count($filterfields)>1){ //join needed
1611
					$sel['filters'][$fc]['name'] = '"'.$filterfields[count($filterfields)-2].'"."'.$filterfields[count($filterfields)-1].'"';
1612
					for($i=0;$i<count($filterfields)-1;$i++){
1613
						if(!in_array($filterfields[$i],$tables)){
1614
							$tables[] = $filterfields[$i];
1615
						}
1616
						if($i == 0){
1617
							if(!in_array_r(array($sel['table'],$filterfields[$i]), $tablePairs)){
1618
								$tablePairs[] = array($sel['table'],$filterfields[$i]);
1619
							}
1620
						}
1621
						else{
1622
							if(!in_array_r(array($filterfields[$i-1],$filterfields[$i]),$tablePairs)){
1623
								$tablePairs[] = array($filterfields[$i-1],$filterfields[$i]);
1624
							}
1625
						}
1626
					}
1627
				}
1628
			}
1629
		}
1630
		//----------------------------------------------------------------//
1631
		//having
1632
		if(isset($sel['having'])){
1633
			for($fc=0;$fc<count($sel['having']);$fc++){
1634
				$havingfields = explode("-",$sel['having'][$fc]['name']);
1635
				if(count($havingfields)>1){ //join needed
1636
					$sel['having'][$fc]['name'] = '"'.$havingfields[count($havingfields)-2].'"."'.$havingfields[count($havingfields)-1].'"';
1637
					for($i=0;$i<count($havingfields)-1;$i++){
1638
						if(!in_array($havingfields[$i],$tables)){
1639
							$tables[] = $havingfields[$i];
1640
						}
1641
						if($i == 0){
1642
							if(!in_array_r(array($sel['table'],$havingfields[$i]), $tablePairs)){
1643
								$tablePairs[] = array($sel['table'],$havingfields[$i]);
1644
							}
1645
						}
1646
						else{
1647
							if(!in_array_r(array($havingfields[$i-1],$havingfields[$i]),$tablePairs)){
1648
								$tablePairs[] = array($havingfields[$i-1],$havingfields[$i]);
1649
							}
1650
						}
1651
					}
1652
				}
1653
			}
1654
		}
1655
		//----------------------------------------------------------------//
1656
		$query = 'SELECT '.$sel['xaxis']['agg'].'("'.$sel['table'].'"."'.$sel['xaxis']['name'].'") as xfield';
1657
		for($i=0;$i<count($sel['fields']);$i++){
1658
			$query .= ', '.$sel['fields'][$i]['agg'].'("'.$sel['table'].'"."'.$sel['fields'][$i]['fld'].'")';
1659
		}
1660
		$query .= ' ,'.$dimfield.' as dimfield';
1661
		$query .= ' FROM "'.$sel['table'].'"';
1662
		if(count($tables)>0) $query .= ', "'.implode("\", \"",$tables).'" ';
1663
1664
		$query .= ' WHERE ';
1665
		for($i=0;$i<count($sel['fields']);$i++){
1666
			if($i>0) $query .=" AND ";
1667
			$query .= 'field'.$i." IS NOT NULL";
1668
		}
1669
1670
		if(count($tablePairs) > 0){
1671
			$query .= " AND ";
1672
			for($i=0;$i<count($tablePairs);$i++){
1673
				$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1674
				if($i!=count($tablePairs)-1) 	$query .= "AND ";
1675
				else $query .= " ";
1676
			}
1677
		}
1678
		//filters
1679
		if(isset($sel['filters']) && count($sel['filters'])>0){
1680
			$query .= " AND ";
1681
			for($i=0;$i<count($sel['filters']);$i++){
1682
				if(isset($sel['filters'][$i]['max'])){
1683
					$query .= "(".$sel['filters'][$i]['name']."<=".$sel['filters'][$i]['max']." AND ".$sel['filters'][$i]['name'].">=".$sel['filters'][$i]['min'].")" ;
1684
				}
1685
				else{
1686
					$query .= "(";
1687
					for($j=0;$j<count($sel['filters'][$i]['values']);$j++){
1688
						$query .= $sel['filters'][$i]['name'].'="'.$sel['filters'][$i]['values'][$j].'"';
1689
						if($j!=count($sel['filters'][$i]['values'])-1) $query .= " or ";
1690
					}
1691
					$query .= ")";
1692
				}
1693
				//$query .= '"'.$tablePairs[$i][0].'"."'.$tablePairs[$i][1].'"="'.$tablePairs[$i][1].'".id';
1694
				if($i!=count($sel['filters'])-1) 	$query .= " AND ";
1695
				else $query .= " ";
1696
			}
1697
		}
1698
		//--------------------------------------------------------//
1699
		$query .= " GROUP BY ".$dimfield;
1700
		if(count($sel['having'])>0){
1701
			$query .= " HAVING ";
1702
			for($i=0;$i<count($sel['having']);$i++){
1703
				if($i>0)
1704
					$query .= " and ";
1705
				$query .= $sel['having'][$i]['agg']."(".$sel['having'][$i]['name'].")".$sel['having'][$i]['fnc'].$sel['having'][$i]['value'];
1706
			}
1707
1708
		}
1709
1710
		if(!$doquery){
1711
			$this->log->info('chartDataGroup generated query:'.$query);
1712
			$this->log->info('will not execute it');
1713
			return $query;
1714
		}
1715
		//echo "scatterplot, case group:"; echo $query;
1716
		$this->log->info('scatterDataGroup generated query:'.$query);
1717
		$res = $this->doQuery($query, PDO::FETCH_NUM);
1718
1719
		$this->log->info("result: ".print_r($res,true));
1720
		return array('type'=>'scatter','data'=>$res);
1721
	}
1722
1723
	function performQuery($query,$persistent){
1724
		$this->log->info("perfoming query");
1725
		$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1726
1727
		$this->log->info("result: ".print_r($res,true));
1728
		return $res;
1729
	}
1730
1731
	function makeQuery($selectedData){
1732
		$this->log->info("makeQuery");
1733
		$isMeas = false;
1734
		$hasGroups = true;
1735
		$selectList = array();
1736
		$groupbyList = array();
1737
		$whereList = array();
1738
		$groupby = "";
1739
		$orderby = "";
1740
		$lastSelect = array();
1741
1742
		$tablesList = array();
1743
		$tablesPairs = array();
1744
		$xaxistables = array();
1745
		$dimsList = array();
1746
		$dimsList = $this->queryAllDims($selectedData['table']);
1747
		//create the tables list and the tables pairs list
1748
		$tablesList[] = $selectedData['table'];
1749
		foreach($selectedData['series'] as $series) {
1750
			$seriesexploded = explode("-",$series);
1751
			if(count($seriesexploded) == 1) {
1752
				$groupbyList[] = '"'.$selectedData['table'].'"."'.$seriesexploded[0].'"';
1753
				$lastSelect[] = $seriesexploded[0];
1754
			}
1755
			else{
1756
				$i=0;
1757
				if(!in_array($seriesexploded[$i],$tablesList))
1758
					$tablesList[] = $seriesexploded[$i];
1759
1760
				if(!in_array_r(array($selectedData['table'],$seriesexploded[0]),$tablesPairs))
1761
					$tablesPairs[] = array($selectedData['table'],$seriesexploded[0]);
1762
1763
				for($j=1;$j<count($seriesexploded)-1;$j++) {
1764
					if(!in_array($seriesexploded[$j],$tablesList))
1765
						$tablesList[] = $seriesexploded[$j];
1766
					if(!in_array_r(array($seriesexploded[$i],$seriesexploded[$j]),$tablesPairs))
1767
						$tablesPairs[] = array($seriesexploded[$i],$seriesexploded[$j]);
1768
					$i++;
1769
				}
1770
				$groupbyList[] = '"'.$seriesexploded[count($seriesexploded)-2].'"."'.$seriesexploded[count($seriesexploded)-1].'"';
1771
				$lastSelect[] = $seriesexploded[count($seriesexploded)-1];
1772
			}
1773
		}
1774
		$xaxistables = explode("-",$selectedData['xaxis']['name']);
1775
		if($this->checkMeas($selectedData['table'], $xaxistables[count($xaxistables)-1])){
1776
			$isMeas = true;
1777
			$hasGroups = false;
1778
		}
1779
		if(count($xaxistables) == 1){
1780
			if($isMeas && $selectedData['group'] && $selectedData['group'] != ''){
1781
				if($selectedData['xaxis']['agg'] == 'none')
1782
					$selectList[] = "avg('".$selectedData['table'].'"."'.$xaxistables[0].'")';
1783
				else
1784
					$selectList[] = $selectedData['xaxis']['agg']+'("'.$selectedData['table'].'"."'.$xaxistables[0].'")';
1785
			}
1786
			else{
1787
				$selectList[] = '"'.$selectedData['table'].'"."'.$xaxistables[0].'"';
1788
			}
1789
			if(!$isMeas){
1790
				$groupbyList[] = '"'.$selectedData['table'].'"."'.$xaxistables[0].'"';
1791
			}
1792
		}
1793
		else {
1794
			$selectList[] = '"'.$xaxistables[count($xaxistables)-2].'"."'.$xaxistables[count($xaxistables)-1].'"';
1795
			if(!$isMeas){
1796
				$groupbyList[] = '"'.$xaxistables[count($xaxistables)-2].'"."'.$xaxistables[count($xaxistables)-1].'"';
1797
			}
1798
			if(!in_array($xaxistables[count($xaxistables)-2],$tablesList))
1799
				$tablesList[] = $xaxistables[count($xaxistables)-2];
1800
1801
			if(!in_array_r(array($selectedData['table'],$xaxistables[0]),$tablesPairs))
1802
					$tablesPairs[] = array($selectedData['table'],$xaxistables[0]);
1803
			for($i=0;$i<count($xaxistables)-2;$i++) {
1804
				if(!in_array($xaxistables[$i],$tablesList))
1805
					$tablesList[] = $xaxistables[$i];
1806
1807
				if(!in_array_r(array($xaxistables[$i],$xaxistables[$i+1]),$tablesPairs))
1808
					$tablesPairs[] = array($xaxistables[$i],$xaxistables[$i+1]);
1809
			}
1810
		}
1811
		$orderby = implode(", ",$groupbyList);
1812
		$groupby = implode(", ",$groupbyList);
1813
1814
		foreach($tablesPairs as $pair) {
1815
			$whereList[] = '"'.$pair[0].'"."'.$pair[1].'" = "'.$pair[1].'".id';
1816
		}
1817
1818
		foreach($selectedData['fields'] as $field) {
1819
			if($hasGroups){
1820
				if($field['agg'] == 'none')
1821
					$selectList[] ='avg("'.$selectedData['table'].'"."'.$field['fld'].'")';
1822
				else
1823
					$selectList[] = $field['agg'].'("'.$selectedData['table'].'"."'.$field['fld'].'")';
1824
			}
1825
			else
1826
				$selectList[] = '"'.$selectedData['table'].'"."'.$field['fld'].'"';
1827
		}
1828
		$query = "select ".implode(", ",$selectList);
1829
		if(count($lastSelect)!=0)
1830
			$query .= ", ".implode(" || '-' || ",$lastSelect)." as seriesName ";
1831
		$query .= " from '".implode("', '",$tablesList)."'";
1832
		$query .= " where ";
1833
		for($i=0;$i<count($selectedData['fields']);$i++) {
1834
			if($i!=0) $query .=" and ";
1835
			$query .= '"'.$selectedData['fields'][$i]['fld'] .'" !=""';
1836
		}
1837
		if(count($whereList) !=0)
1838
			$query .= " and ".implode(" and ",$whereList);
1839
		if($groupby!='' && $selectedData['color']!= 'yes')
1840
			$query .= " group by ".$groupby;
1841
		if($orderby!='')
1842
			$query .= " order by ".$orderby;
1843
		//echo "NOT GROUP"; echo $query;
1844
		$this->log->info("generated query: ".$query);
1845
		$res = $this->doQuery($query, PDO::FETCH_NUM,$persistent);
1846
		//print_r($res);
1847
		//$this->log->info('result set:'.json_encode($res));
1848
		if($isMeas) $returnType = 'scatter';
1849
		else $returnType = 'chart';
1850
		return array('type'=>$returnType,'data'=>$res,'accomDims'=>$dimsList['fields']);
1851
	}
1852
1853
	function queryAllDims($tablename) {
1854
		//get all the dims of the fact table and make a list with all their keys
1855
		$fields = array();
1856
		$joins = array();
1857
		//find the factable
1858
		$table = $this->findTable($tablename,'fact');
1859
		if($table == false) {
1860
			return false;
1861
		}
1862
		foreach($table['dim'] as $dim) {
1863
			if(isset($dim['dimtable']) && $dim['dimtable'] == 'no') {//will need no join
1864
				$fields[] = $dim['name'];
1865
			}
1866
			else{
1867
				//find the key(s) put them in the fields list
1868
				$key = $this->getDimsKeys($dim['name']);
1869
				if(is_array($key)){
1870
					foreach($key as $k)
1871
						$k = "'".$k."'";
1872
					$fields[] = implode(" || ",$key);
1873
				}
1874
				else
1875
					$fields[] = $key;
1876
				//and put it in the join list
1877
				$joins[] = $dim['name'];
1878
			}
1879
		}
1880
		return array('fields'=>$fields,'joins'=>$joins);
1881
	}
1882
}
1883
1884
class QueryTree {
1885
	public $tree = Array();
1886
1887
	public function __construct($table) {
1888
		$this->tree['table'] = $table;
1889
		$this->tree['chains'] = Array();
1890
		$this->tree['order'] = 'ASC';
1891
	}
1892
1893
	public function updateFilters($filters) {
1894
		for ($i = 0; $i < count($filters); $i++) {
1895
			$filterFields = explode("-", $filters[$i]['name']);
1896
			$rootField = $filterFields[0];
1897
1898
			$field = $filterFields[count($filterFields) - 1];
1899
			$filter = Array();
1900
1901
			$filter["column"] = $field;
1902
			if (isset($filters[$i]['values']))
1903
				$filter['values'] = $filters[$i]['values'];
1904
			if (isset($filters[$i]['max']))
1905
				$filter['max'] = $filters[$i]['max'];
1906
			if (isset($filters[$i]['min']))
1907
				$filter['min'] = $filters[$i]['min'];
1908
			if (isset($filters[$i]['exvalues']))
1909
				$filter['exvalues'] = $filters[$i]['exvalues'];
1910
1911
			if (count($filterFields) > 1) {
1912
				$this->buildChain($filters[$i]['name']);
1913
				$this->tree['chains'][$rootField]['tables'][count($filterFields) - 2]['filters'][] = $filter;
1914
			} else {
1915
				$this->tree['filters'][] = $filter;
1916
			}
1917
		}
1918
	}
1919
1920
	public function updateYAxis($yAxisFields) {
1921
		foreach ($yAxisFields as $field)
1922
			$this->tree['yAxis'][] = $field['agg'] . '("' . $this->tree['table'] . '"."' . $field['fld'] . '")';
1923
	}
1924
1925
	public function updateXAxis($xAxisField) {
1926
		$fields = explode("-", $xAxisField);
1927
1928
		if (count($fields) == 1) {
1929
			$this->tree['xAxis'] = '"'. $this->tree['table'] .'"."' . $fields[0] . '"';
1930
		} else {
1931
			if (!isset($this->tree['chains'][$fields[0]])) {
1932
				$this->buildChain($xAxisField);
1933
			}
1934
1935
			$this->tree['xAxis'] = '"' . $fields[0] . '"."' . $fields[count($fields) - 1] . '"';
1936
			$this->tree['chains'][$fields[0]]['return'] = '"'.$fields[count($fields) - 2] . '"."' . $fields[count($fields) - 1] . '"';
1937
		}
1938
	}
1939
1940
	public function excludeNulls($exclude = true) {
1941
		$this->tree['excludeNulls'] = $exclude;
1942
	}
1943
1944
	public function updateOrderBy($orderBy) {
1945
		if ($orderBy == 'xaxis') {
1946
			$this->tree['orderBy'] = $this->tree['xAxis'];
1947
		} else {
1948
			$fields = explode('-', $orderBy);
1949
1950
			$this->tree['orderBy'] = $fields[0] . '("' . $this->tree['table'] . '"."' . $fields[1] . '")';
1951
		}
1952
	}
1953
1954
	public function updateOrder($order) {
1955
		if ($order == 'd') {
1956
			$this->tree['order'] = 'DESC';
1957
		}
1958
	}
1959
1960
	public function updateLimit($limit) {
1961
		$this->tree['limit'] = $limit;
1962
	}
1963
1964
	public function getQuery() {
1965
		$query = 'SELECT ' . $this->tree['xAxis'] . ' as xfield';
1966
1967
		if (isset($this->tree['yAxis'])) {
1968
			for ($i = 0; $i < count($this->tree['yAxis']); $i++) {
1969
1970
				$query .= ', ';
1971
1972
				if ($i < count($this->tree['yAxis']) - 1) {
1973
					$query .= ' , ';
1974
				}
1975
1976
				$query .= $this->tree['yAxis'][$i] . ' as field' . $i;
1977
			}
1978
		}
1979
1980
		$query .= ' FROM ' . $this->tree['table'];
1981
1982
		foreach ($this->tree['chains'] as $chainName => $chain) {
1983
			$query .= ' JOIN (' . $this->buildSubQuery($chain) . ') as ' .$chainName . ' ON "' . $this->tree['table'] . '"."' . $chainName . '" = "' . $chainName . '"."id"' ;
1984
		}
1985
1986
		if (isset($this->tree['excludeNulls']) || isset($this->tree['filters'])) {
1987
			$query .= ' WHERE ';
1988
		}
1989
1990
		if (isset($this->tree['excludeNulls'])) {
1991
		 	$query .= $this->tree['xAxis'] . ' IS NOT NULL';
1992
		}
1993
1994
		if (isset($this->tree['filters'])) {
1995
			if (substr_compare($query, ' WHERE ', -strlen(' WHERE '), strlen(' WHERE ')) !== 0)
1996
				$query .= ' AND ';
1997
1998
			for ($i = 0; $i < count($this->tree['filters']); $i++) {
1999
				$query .= '(' . $this->buildSubQueryFilter($this->tree['table'], $this->tree['filters'][$i]) .')';
2000
2001
				if ($i < count($this->tree['filters']) - 1)
2002
					$query .= ' AND ';
2003
			}
2004
		}
2005
2006
		$query .= ' GROUP BY ' . $this->tree['xAxis'];
2007
2008
		if (isset($this->tree['orderBy'])) {
2009
			$query .= ' ORDER BY ' . $this->tree['orderBy'] . ' ' . $this->tree['order'];
2010
		}
2011
2012
		if (isset($this->tree['limit'])) {
2013
			$query .= ' LIMIT ' . $this->tree['limit'];
2014
		}
2015
2016
		return $query;
2017
	}
2018
2019
	public function getTree() {
2020
		return $this->tree;
2021
	}
2022
2023
	/*	Helper functions  */
2024
2025
	private function buildChain($fieldsString) {
2026
		$fields = explode("-", $fieldsString);
2027
		$rootField = $fields[0];
2028
2029
		if (!isset($this->tree['chains'][$rootField])) {
2030
			$this->tree['chains'][$rootField] = Array();
2031
			$this->tree['chains'][$rootField]['name'] = $rootField;
2032
		}
2033
2034
		for ($fc = 0; $fc < count($fields) - 1; $fc++) {
2035
			$field = $fields[$fc];
2036
2037
			if (!isset($this->tree['chains'][$rootField]['tables'][$fc]) ) {
2038
				$this->tree['chains'][$rootField]['tables'][] = Array("table" => $field);
2039
			}
2040
2041
		}
2042
	}
2043
2044
	private function buildSubQuery($chain) {
2045
		$subQuery = 'select distinct "' . $chain['tables'][0]['table'] . '"."id"';
2046
2047
		if (isset($chain['return']))
2048
			$subQuery .= ', ' . $chain['return'];
2049
2050
		$subQuery .= ' from "' . $chain['tables'][0]['table'] . '"';
2051
2052
		for ($i = 1; $i < count($chain['tables']); $i++) {
2053
			$subQuery .= ' join "' . $chain['tables'][$i]['table'] .'" on "' . $chain['tables'][$i]['table'] . '"."id"="'.$chain['tables'][$i-1]['table'].'"."'.$chain['tables'][$i]['table'].'"';
2054
2055
			if (isset($chain['tables'][$i]['filters'])) {
2056
				foreach ($chain['tables'][$i]['filters'] as $filter) {
2057
					$subQuery .= ' and (' . $this->buildSubQueryFilter($chain['tables'][$i]['table'], $filter) . ') ';
2058
				}
2059
			}
2060
		}
2061
2062
		return $subQuery;
2063
	}
2064
2065
	private function buildSubQueryFilter($tableName, $filter) {
2066
		$column = $filter['column'];
2067
		$filterText = "";
2068
2069
		if (isset($filter['values'])) {
2070
			for ($fc = 0; $fc < count($filter['values']); $fc++) {
2071
				$value = $filter['values'][$fc];
2072
2073
				if ($fc > 0)
2074
					$filterText .= ' or ';
2075
				$filterText .= '"' . $tableName . '"."'.$column.'" = \'' . $value . '\'';
2076
			}
2077
		} else if (	isset($filter['exvalues'])) {
2078
			for ($fc = 0; $fc < count($filter['exvalues']); $fc++) {
2079
				$value = $filter['exvalues'][$fc];
2080
2081
				if ($fc > 0)
2082
					$filterText .= ' and ';
2083
				$filterText .= '"' . $tableName . '"."'.$column.'" != \'' . $value . '\'';
2084
			}
2085
		} else if (isset($filter['max'])) {
2086
			if (strstr($column, 'year') && $filter['max'] == 'today') {
2087
				$filterText = $column . ' <= extract(YEAR from now()) and ' . $column . ' >= ' . $filter['min'];
2088
			} else 	if (strstr($column, 'year') && $filter['min'] == 'today') {
2089
				$filterText = $column . ' >= extract(YEAR from now()) and ' . $column . ' <= ' . $filter['max'];
2090
			} else {
2091
				$filterText = $column . ' >= ' . $filter['min'] . ' and ' . $column . ' <= ' . $filter['max'];
2092
			}
2093
		}
2094
2095
		return $filterText;
2096
	}
2097
}
2098
2099
?>