Example #1
0
	function explain() {
		//ajaxリクエスト以外
		if( !$this->RequestHandler->isAjax() ) {
			$this->set("result" , array("result" => "not ajax"));
			return;
		}

		//パラメータ解析
		$u_userid=$this->params['form']['u'];
		$u_database=$this->params['form']['d'];
		$u_query=htmlspecialchars_decode($this->params['form']['q'], ENT_QUOTES);
		if ( $u_database == "" or $u_userid == "" or $u_query == "" ){
			$this->set("result" , array("result" => "parameter error"));
			return;
		}

		//事前処理
		list($res,$hive_database)=CommonComponent::HiveBefore($u_userid,$u_query);	
		if ( $res != 0 ){
			$this->set("result" , array("result" => "許可されていないクエリです"));
			return;
		}

		//リクエストID発行
		if ( CommonComponent::MakeDirectory($u_userid) != 0 ){
			$this->set("result" , array("result" => "create directory error"));
			return;
		}
		$u_id=sprintf("%s_%05d",date("YmdHis"),getmypid());
		$hql_file=DIR_REQUEST."/${u_userid}/${u_id}.hql";
		$chk_file=DIR_REQUEST."/${u_userid}/${u_id}.chk";
		$exp_file=DIR_RESULT."/${u_userid}/${u_id}.exp";

		//コメント行変換処理
		$arr=preg_split("/[\r\n]/",$u_query);
		$u_query2="";
		for ($i=0; $i<count($arr); $i++){
			if ( eregi('^--',$arr[$i]) ){
				$u_query2.="$arr[$i];\n";
			}else{
				$u_query2.="$arr[$i]\n";
			}
		}

		//リクエストファイル作成
		if ( !($fp=fopen($hql_file,"w")) ){
			$this->set("result" , array("result" => "file open error", "id" => "$u_id"));
			return;
		}
		fputs($fp,"use ${u_database};\n");
		$arr=preg_split("/;/",$u_query2);
		for ($i=0; $i<count($arr); $i++){
			$arr[$i]=str_replace(array("\r\n","\n","\r","\t"), ' ', $arr[$i]);
			$arr[$i]=ltrim($arr[$i]);
			if ( $arr[$i] == "" ){ continue; }
			$ret=fputs($fp,"$arr[$i];\n");
		}
		fclose($fp);

		//EXPLAINファイル作成
		if ( !($fp=fopen($chk_file,"w")) ){
			$this->set("result" , array("result" => "file open error", "id" => "$u_id"));
			return;
		}
		fputs($fp,"use ${u_database};\n");
		$arr=preg_split("/;/",$u_query2);
		for ($i=0; $i<count($arr); $i++){
			$arr[$i]=str_replace(array("\r\n","\n","\r","\t"), ' ', $arr[$i]);
			$arr[$i]=ltrim($arr[$i]);
			if ( $arr[$i] == "" ){ continue; }
			if ( eregi('^--',$arr[$i]) ){
				$ret=fputs($fp,"$arr[$i]\n");
				continue;
			}
			if ( eregi(SQL_EXPLAIN_EXCLUDE,$arr[$i]) ){
				$ret=fputs($fp,"$arr[$i];\n");
			}else{
				$ret=fputs($fp,"explain $arr[$i];\n");
			}
		}
		fclose($fp);

		// explainによるHiveQLチェック
		$cmd = CMD_HIVE . " -v -f $chk_file > $exp_file 2>&1";
		$this->log("CMD=$cmd",LOG_DEBUG);
		exec($cmd,$result,$retval);
		$this->log("CMD=$cmd => $retval",LOG_DEBUG);
		if ( !file_exists($exp_file) ){
			$this->set("result" , array("result" => "explain error", "id" => "$u_id"));
			return;
		}
		if ( $retval != 0 ){
			$this->set("result" , array("result" => "query error", "id" => "$u_id"));
			return;
		}

		// explain結果判定
		list($stage_cnt,$mapreduce_cnt,$line_cnt)=CommonComponent::CheckSQLexplain($u_userid,$u_id);
		if ( $stage_cnt < 0 ){
			$this->set("result" , array("result" => "unknown", "id" => "$u_id"));
			return;
		}

		// データベース実行権限チェック
		$u_databases=DATABASE_PERMISSION;
		$u_user=$this->Users->find('all', array( "conditions" => "username='******'", "limit"=>1));
		if(!empty($u_user[0]['Users']['hive_database'])){
			$u_databases=$u_user[0]['Users']['hive_database'];	
		}
		$chk_result=CommonComponent::CheckExplainDatabase($u_userid,$u_id,$u_databases);
		if ( $chk_result != 0 ){
			$this->set("result" , array("result" => "指定されたデータベースへのアクセスが許可されていません", "id" => "$u_id"));
			return;
		}

		//時間がかかりそうな場合は結果確認画面を出す
		if ( $stage_cnt > 3 or $mapreduce_cnt > 0 or $line_cnt > 35 ){
			$msg="処理数=$stage_cnt MapReduce数=$mapreduce_cnt コスト=$line_cnt";
			$this->set("result" , array("result" => "check", "id" => "$u_id", "msg"=>"$msg"));
		}else{
			$this->set("result" , array("result" => "ok", "id" => "$u_id"));
		}
	}