<?php 
	include_once('xml/XMLS.php'); 	
	

	
	//Anula la salida de errores y warnings
	$old = error_reporting();
	error_reporting(0);	


	//Genera la salida en XML (El resultado)
	$result = new XML();
	$result->AgregarNodo("Result");
		
	
	
	//Obtienen los parametros pasado desde FLEX
	$xmlstr = "".$_POST['parameters']."";	
	
	
	
	$xml =simplexml_load_string($xmlstr);	
	
	
	
	$hostname = $xml->hostname;
	$port = $xml->port;
	$database = $xml->database;
	$username = $xml->username;
	$password = $xml->password;
	if($xml->mododebug == "false"){
		$mododebug = false;
	}else{
		$mododebug = true;		
	}

	
	if($xml->contransaccion == "false"){
		$contransaccion = false;
	}else{
		$contransaccion = true;		
		if($mododebug){ salida("Transaccion True"); }
	}

	
	$sqlCount = $xml->SqlCount;
	$LinksCount  = $xml->LinksCount;
	 
	$ResultPendiente ="";
	
	if($mododebug){	salida($xmlstr);}
	
	if($mododebug){ salida($xml->Links->LinkCount); }
	if($mododebug){ salida($xml->Links); }
	
	
	$Error = false;		
	$ErrorDesc = "";		
	$LastErrorNro = 0;
	$LastErrorDesc = "";		
	$LastID = 0;
		

	//conecta a la base asi es en Postgres
	$conn_string = "host=" . $hostname  .  " port=" . $port .  " dbname=" . $database . " user=" . $username . " password=" . $password ;
	if($mododebug){salida("Cadena de conexion:" . $conn_string ) ; }
	
	$dbdatabase = pg_connect($conn_string);
	if($mododebug){salida("Resultado Conexion:" . $dbdatabase ) ; }

	if ( $dbdatabase == "") {			
		$Error = true;		
		$ErrorDesc = "No se pudo conectar a la base de datos";		
		//$LastErrorNro = pg_last_error();
		$LastErrorNro = "1";
		$LastErrorDesc = pg_errormessage();
		if($mododebug){salida("Error de conexion:"  ) ; }		
	}
	
	//Si no hubo error selecciona el esquema    (En postgres no es necesario, lo hace todo la primera instruccion)
	//if(!$Error){
	//	if (!pg_connect(" dbname=" + $dbdatabase)) {			
	//		$Error = true;		
	//		$ErrorDesc = "No se pudo seleccionar el esquema";		
	//		$LastErrorNro = pg_last_error();
	//		$LastErrorDesc = pg_errormessage();		
	//	}
	//		
	//}					
	
	
	//Si  hubo error devuelve las variables de estados
	if($Error){		
		$result->AgregarNodo("Control");
		$result->AgregarItem("Error",$Error);
		$result->AgregarItem("ErrorDesc",utf8_encode($ErrorDesc));
		$result->AgregarItem("ErrorMySql",utf8_encode($LastErrorDesc));
		$result->AgregarItem("ErrorNro",utf8_encode($LastErrorNro));	
		$result->AgregarItem("Conected","false");		
		$result->AgregarItem("SqlCount",$sqlCount);		
		$result->AgregarItem("Last_Id",$LastID);
		$result->CerrarNodo("Control");		
	
	}else{	
		
		// Agrega las instrucciones sql en el archivo para depurar (parametros.txt)
		if($mododebug){
			for ($NroSql=0; $NroSql<$sqlCount; $NroSql++){			
					salida(trim(decodificar($xml->Sql[$NroSql])))	;					
				}			
		}

		if($contransaccion)	{
			if($mododebug){ salida("Comienza transaccion");			}
			
			// Ver como es en Postgress (parece ser simplemente begin)
			pg_query("SET AUTOCOMMIT=0;");
			pg_query("START TRANSACTION;");
			 
		}
			
		//Recorrer todos los sqls que se recibieron
		for ($NroSql=0; $NroSql<$sqlCount; $NroSql++){			
			
			if($mododebug){	salida("Procesando:" .$xml->Sql[$NroSql]->Result); }
			
			//si era una una tabla abierta
			if($xml->Sql[$NroSql]->Open == "yes"){	
				
				if($mododebug){	salida("Armando estructura:");}

				$strSql = trim(decodificar($xml->Sql[$NroSql]));
				for ($NroLink=0; $NroLink<$LinksCount; $NroLink++){										
					$strSql = str_replace($xml->Links[$NroLink]->Comodin,$xml->Links[$NroLink]->Valor,$strSql);					
				}
				
				
				//Abre la consulta para luego poder tomar la definicion de los campos
				$rst = pg_query($dbdatabase,$strSql);
				if($mododebug){	salida("Resultado abrir consulta ($strSql):" . $rst); }												
				if (!$rst) {						
					$Error = true;		
					$ErrorDesc = "Error: consulta sql incorrecta:" . trim(decodificar($xml->Sql[$NroSql]));
					$LastErrorNro = pg_last_error();
					$LastErrorDesc = pg_errormessage();	
					$ResultPendiente = $xml->Sql[$NroSql]->Result; 
					if($mododebug){	salida("Error de consulta sql"); }				
					break;
				}	
				
				//Si hay una solisitud de Result o de tableDefs agrega el nodo "Result"
				if ($xml->Sql[$NroSql]->Result != "" ){				
					//Agregar la estructura de Result con el nombre indicado en el parametro Result
					$result->AgregarNodo($xml->Sql[$NroSql]->Result );
					if($mododebug){	salida("Agrego el nodo Result al xml"); }				
				} 				
				
				
				//Agregar la estructura TableDef (donde se encuentra los nombres de los campos del Result
				$cant =  pg_num_fields($rst);
				if($mododebug){	salida("Cantidad de campos " . $cant); }				
				
				$result->AgregarNodoConAtributos("TableDefs","FieldsCount='". $cant ."'");
				$i=0; 
				
				
				while ($i < $cant){
					$attr = pg_fetch_array($rst, $i);
					
					$result->AgregarNodo("Field");
					
					$result->AgregarItem("name", pg_field_name($rst,$i));
					$result->AgregarItem("type", pg_field_type($rst,$i));
					$result->AgregarItem("primary_key" , false );
					
					//$result->AgregarItem("primary_key" , $attr->primary_key );
					//$result->AgregarItem("unique_key" , $attr->unique_key );					
					//$result->AgregarItem("multiple_key" , $attr->multiple_key );										
					$result->AgregarItem("not_null" , 0);
					
					//$result->AgregarItem("blob" , $attr->blob );
					//$result->AgregarItem("numeric" , $attr->numeric );					
					
					
					//$banderas = pg_field_flags($rst, $i);
					//$posicion = strpos($banderas, "auto_increment");					
					//if ($posicion === false) {					
					//	$result->AgregarItem("auto_increment" , false );
					//}else{
					//	$result->AgregarItem("auto_increment", true );					
					//}
														
					$result->CerrarNodo("Field");
					
					
					$i++;
				}
				
				$result->CerrarNodo("TableDefs");									
							
			}
			
			
			if($xml->Sql[$NroSql]->Result != ""){  //Necesita un Result  (si no hay error previo)				
				
				if($mododebug){ salida("Armando datos"); }
				
				//Intenta reemplazar los campos comodines por los valores previamentes capturados
				$strSql = trim(decodificar($xml->Sql[$NroSql]));
				for ($NroLink=0; $NroLink<$LinksCount; $NroLink++){										
					$strSql = str_replace($xml->Links[$NroLink]->Comodin,$xml->Links[$NroLink]->Valor,$strSql);					
				}
				if($mododebug){salida($strSql);}
				
							
				
				$rst = pg_query($dbdatabase,$strSql);				
				if (!$rst) {						
					$Error = true;		
					$ErrorDesc = "Error: consulta sql incorrecta:";
					$LastErrorNro = pg_last_error();
					$LastErrorDesc = pg_errormessage();	
					$ResultPendiente = $xml->Sql[$NroSql]->Result; 
					if($contransaccion){
						 if($mododebug){salida("hizo rooback");}
						 //TODO: Falta ver como es el rollback en postgresql
						 pg_query("ROLLBACK;"); 
					}
					break;
				}	
			
				//Agrega el nodo RESULT	
				if($xml->Sql[$NroSql]->Open != "yes"){			
					$result->AgregarNodo($xml->Sql[$NroSql]->Result );
				}				
					
					
				//Agregar a cada uno de los registros que corresponden a la instruccion SQL actual
				$r=0;
				while ($row =  pg_fetch_assoc($rst)) {	
					//$result->AgregarItemConatributos("Record","","RecordNro='".$r ."'");
					$result->AgregarNodoConAtributos("Record","RecordNro='".$r ."'");
					$i=0;
					while ($i < pg_num_fields($rst)){
						
						//Intenta capturar los valores para los comodines
						
						for ($NroLink=0; $NroLink<$LinksCount; $NroLink++){
							//salida("tabla:" . $xml->Links[$NroLink]->Tabla . "    Result:" .$xml->Sql[$NroSql]->Result );
							if($xml->Links[$NroLink]->Tabla == $xml->Sql[$NroSql]->Result){
								if($xml->Links[$NroLink]->Campo == pg_field_name($rst,$i)){
									//$xml->Links[$NroLink]['Valor'] = $row[mysql_field_name($rst,$i)];

									$xml->Links[$NroLink]->Valor = $row[mysql_field_name($rst,$i)];				//Si falla provar con esto
									if($mododebug){ salida("Nro link" . $NroLink + " campo:" +$xml->Links[$NroLink]->Campo + "  valor:" . $xml->Links[$NroLink]->Valor); }
								}
							}
							
						}
						
						//agrega el campo y el valor en el xml
						$result->AgregarItem(pg_field_name($rst,$i), SacarMayoresYMenores(utf8_encode($row[pg_field_name($rst,$i)])));
						$i++;
					}
					$result->CerrarNodo("Record");									
					$r++;
				}		
				

				// Actualiza propiedades segun la cantidad de regitros existentes				
				if($r >0){
					$result->AgregarItem("NoMatch","false");
				}else{
				  	$result->AgregarItem("NoMatch","true");  
				}
				
				
			
			}else{		// No necesita Result  (es un execute)
				
				// esta es la rama de updates o insert 	
				$strSql = trim(decodificar($xml->Sql[$NroSql]));
				$strSql = str_replace("@LastId@",$LastID,$strSql);
												
				$rst = pg_query($strSql, $dbdatabase);
				if (!$rst) {					
					if($mododebug){ salida("Dio error" . mysql_error());}
					$Error = true;		
					$ErrorDesc = "Error: consulta sql incorrecta:" . $strSql ;
					$LastErrorNro = pg_last_error();					
					$LastErrorDesc = pg_error();	
					if($contransaccion){
						if($mododebug){ salida("hizo rooback"); }
						 pg_query("ROLLBACK;");
					}
					break;
				}
				//TODO:Falta saber como obtener el ultimo id insertado (autonumerico
				//if (pg_insert_id() > 0){
				//	$LastID  = mysql_insert_id();
				//}				
				
			
			}
			
			//Si hubo una solisitud de Result o de tableDefs cierra el nodo "Result" (nombre de la tabla)
			if($xml->Sql[$NroSql]->Open == "yes" or $xml->Sql[$NroSql]->Result != "" ){								
				$result->CerrarNodo($xml->Sql[$NroSql]->Result);				
			} 			
					
		} // next del for para recorrer cada una de las instrucciones sql
		
		$result->AgregarNodo("Control");
		$result->AgregarItem("Debuger","true");
		$result->AgregarItem("Error",$Error );
		$result->AgregarItem("ErrorDesc",utf8_encode($ErrorDesc));
		$result->AgregarItem("ErrorMySql",utf8_encode($LastErrorDesc));
		$result->AgregarItem("ErrorNro",utf8_encode($LastErrorNro));	
		$result->AgregarItem("Conected","true");		
		$result->AgregarItem("SqlCount",$sqlCount);		
		$result->AgregarItem("Last_Id",$LastID);								
		$result->CerrarNodo("Control");		
	}	

	$result->CerrarNodo("Result");		
	
	
	if(!$Error and $contransaccion){
		pg_query("COMMIT;");
		if($mododebug){ salida("hizo commit"); }
	}
		
		
	// devuelve el resultado en formato XML
	echo $result->GetXML();
	if($mododebug){
		salida("\n");
		salida($result->GetXML());	
	}
	

	
	
	function codificar($string)
	{
	    $hex='';
	    for ($i=0; $i < strlen($string); $i++)
	    {
	        $hex .= dechex(ord($string[$i])). " ";
	    }
	    return $hex;
	}
	
	function decodificar($hex)
	{
		$buffer = split(" ",$hex);
	    $string='';
	    
	    foreach ($buffer as $valor)    
	    {
	        $string .= chr(hexdec($valor));
	    }
	    return $string;
	}
	
	
	function AbrirSalida(){
		$man = fopen("dao_log.txt","w");
		fclose($man);	
	}
	
	
	function salida($texto){
		$man = fopen("dao_log.txt","a");
		fwrite($man,utf8_decode($texto) . chr(13) . chr(10)) ;
		fclose($man);		
	}
	
	function SacarMayoresYMenores($texto){
		
		// saca los <
		$res = str_replace("<","@ÊHH1Ê@",$texto);
		$res = str_replace(">","@ÊHH2Ê@",$res);
		return $res;
	}
	
?>
