dboption = $db_option ?: $_config_db_option; if( !$db_option && $__dbconn__ ) { //기본 Connection을 이용 $this->dbconn = $__dbconn__; }else{ //전용 Connection을 이용 $this->dbConn($db_option); } } public function dbConn($db_option=""){ $_config_db_option = @parse_ini_file("db_config.php"); if( !$_config_db_option ){ $_config_db_option = @parse_ini_file(_ROOT_PATH_."/config/db_config.php"); } if( !$db_option ) $db_option = array(); /*위에 있어서 필요없는 코드*/ $db_option["database_type"] = $db_option["database_type"] ?: $_config_db_option["database_type"]; $db_option["database_host"] = $db_option["database_host"] ?: $_config_db_option["database_host"]; $db_option["database_port"] = $db_option["database_port"] ?: $_config_db_option["database_port"]; $db_option["database_name"] = $db_option["database_name"] ?: $_config_db_option["database_name"]; $db_option["database_user"] = $db_option["database_user"] ?: $_config_db_option["database_user"]; $db_option["database_pass"] = $db_option["database_pass"] ?: $_config_db_option["database_pass"]; $db_option["database_encode"] = $db_option["database_encode"] ?: $_config_db_option["database_encode"]; $db_option["database_charset"] = $db_option["database_charset"] ?: $_config_db_option["database_charset"]; $db_option["database_old"] = $db_option["database_old"] ?: $_config_db_option["database_old"]; if( !$this->dboption ){ $this->dboption = $db_option; } $addr = "{$db_option['database_host']},{$db_option['database_port']}"; $option = Array( "Database" => $db_option['database_name'], "Uid" => $db_option['database_user'], "PWD" => $db_option['database_pass'], "CharacterSet" => $db_option['database_encode'], "TrustServerCertificate" => "yes", "ConnectionPooling" => 0, ); $conn = sqlsrv_connect( $addr, $option); if( $conn ){ $this->dbconn = $conn; if( defined("TB_query_log") ){ $this->tableExists(TB_query_log); } return $conn; }else{ die('Could not connect: ' . print_r(sqlsrv_errors(), true)); } } public function qry($sql, $sqlrow="", $options="", $print=""){ return $this->cqry($sql, $sqlrow, $options, $print); } public function cqry($sql, $sqlrow="", $options="", $print="", $rev=1){ if( $rev === 1 ){ $anrow = $this->anqry($sqlrow); $params = $anrow['params']; }else{ $params = $sqlrow; } if( $print || $this->query_print ){ echo $this->mkstr($sql,$params?:Array()); } if( $print ){exit;} $stmt = @sqlsrv_query($this->dbconn, $sql, $params?:Array(), $options?:Array()); if( $stmt ){ $result = "SUCCESS"; $rst = $stmt; }else{ $bpage = debug_backtrace(); $fname = $bpage[count($bpage)-1]['file']; if( !$GLOBALS['NO_SQL_ERR'] ){ $result = print_r(sqlsrv_errors(), true); echo "
{$fname}".PHP_EOL.$sql.PHP_EOL.print_r($params?:Array(),1).PHP_EOL.PHP_EOL.print_r(sqlsrv_errors(), true)."";
}else{
$result = "NO_SQL_ERROR";
}
$rst = false;
}
if( $this->query_record ){
$this->putQueryLog( $sql, $params, $result );
}
return $rst;
}
public function query($sql, $params="", $options="", $print=""){
$stmt = $this->qry($sql, $params?:Array(), $options?:Array(), $print);
if( !$stmt ) return false;
$rows = Array();
while( $row = $this->fetch_array($stmt) ){
$rows[] = $row;
}
return $rows;
}
public function call( $procedure, $params=array() ){
$anrow = $this->anqry($params);
$sql = "{CALL {$procedure} (".implode(",",$anrow['val']).")}";
return $this->qry($sql, $params);
}
public function call_output( $procedure, $params=array() ){
$anrow = $this->anqry($params);
$sql = "{CALL {$procedure} ".implode(",",$anrow['val']).")}";
return $this->cqry($sql, $params,"","",2);
}
public function call_next( $stmt ){
return @sqlsrv_next_result($stmt);
}
public function call_all( $procedure, $params=array() ){
$rst = $this->call( $procedure, $params );
if( $rst ){
$rows = Array();
while( $row = $this->fetch_array($rst) ){
$rows[] = $row;
}
return $rows;
}
return $rst;
}
public function exec( $procedure, $params=array() ){
$anrow = $this->anqry($params);
$sql = "EXEC {$procedure} ".implode(",",$anrow['val'])."";
return $this->qry($sql, $params);
}
public function exec_output( $procedure, $params=array() ){ //$params => 숫자키 배열
$anrow = $this->anqry($params);
$sql = "EXEC {$procedure} ".implode(",",$anrow['val'])."";
return $this->cqry($sql, $params,"","",2);
}
public function exec_output_merge( $procedure, $params=array() ){ //$params => 문자 키 배열. output요소가 array(array("값",SQLSRV_PARAM_OUT)) 가 되어야 한다.
$oparams = Array();
foreach( $params as $val ){
$oparams[] = $val;
}
$anrow = $this->anqry($oparams);
$sql = "EXEC {$procedure} ".implode(",",$anrow['val'])."";
return $this->cqry($sql, $oparams,"","",2);
}
public function exec_next( $stmt ){
return @sqlsrv_next_result($stmt);
}
public function exec_all( $procedure, $params=array() ){
$rst = $this->exec( $procedure, $params );
if( $rst ){
$rows = Array();
while( $row = $this->fetch_array($rst) ){
$rows[] = $row;
}
return $rows;
}
return $rst;
}
public function queryFirstField($sql, $params="", $options="", $print=""){
$stmt = $this->qry($sql, $params?:Array(), $options?:Array(), $print);
if( !$stmt ) return false;
return $this->result($stmt,0,0);
}
public function queryFirstRow($sql, $params="", $options="", $print=""){
$stmt = $this->qry($sql, $params?:Array(), $options?:Array(), $print);
if( !$stmt ) return false;
return $this->fetch_array($stmt);
}
public function pqry($sql, $params="", $options=""){
return $this->qry($sql, $params?:Array(), $options?:Array(), 1);
}
public function pquery($sql, $params="", $options=""){
return $this->query($sql, $params?:Array(), $options?:Array(), 1);
}
public function fetch_row($stmt){
if( $stmt ){
return @sqlsrv_fetch_array($stmt, 1);
}
return "sqlsrv_fetch_array Error #1";
}
public function fetch_array($stmt){
if( $stmt ){
return @sqlsrv_fetch_array($stmt, 2);
}
echo "sqlsrv_fetch_array Error #2";
}
public function fetch_object($stmt){
if( $stmt ){
return @sqlsrv_fetch_object($stmt, 2);
}
echo "sqlsrv_fetch_object Error #2";
}
public function num_rows($stmt){
if( $stmt ){
return @sqlsrv_num_rows($stmt);
}
echo "sqlsrv_num_rows Error";
}
public function select_count($tb, $where="", $whererow="", $print=""){
$where = $where?:"1=1";
$sql = "select count(*) from {$tb} where {$where}";
return $this->queryFirstField($sql, $whererow?:array(), $print);
}
public function insert($tb, $row, $print=""){
$anrow = $this->anqry($row);
$sql = "insert into {$tb} (".implode(",",$anrow['fld']).") values (".implode(",",$anrow['val']).")";
$rst = $this->qry($sql, $anrow['params'], "", $print);
return (bool)$rst;
}
public function update($tb, $row, $where="", $whererow="", $print=""){
$where = $where?:"1=1";
$anrow = $this->anqry($row);
$sql = "update {$tb} set ";
$setrow = array();
foreach( (array)$anrow['fld'] as $k => $v ){
$setrow[] = " {$v} = {$anrow['val'][$k]} ";
}
$sql.= implode(",",$setrow)." where {$where}";
foreach( (array)$whererow as $k => $v ){
$anrow['params'][] = $v;
}
$rst = $this->qry($sql, $anrow['params'], "", $print);
return (bool)$rst;
}
public function insertupdate($tb, $ins_row, $upt_row, $where="", $whererow="", $print=""){
$where = $where?:"1=1";
$ins_anrow = $this->anqry($ins_row);
$upt_anrow = $this->anqry($upt_row);
$setrow = array();
foreach( (array)$upt_anrow['fld'] as $k => $v ){
$setrow[] = " {$v} = {$upt_anrow['val'][$k]} ";
}
$sql = "merge into {$tb} as A using (select 1 as dual) as B on ({$where}) ";
$sql.= "when matched then ";
$sql.= "update set ".implode(",",$setrow)." ";
$sql.= "when not matched then ";
$sql.= "insert (".implode(",",$ins_anrow['fld']).") values (".implode(",",$ins_anrow['val']).");";
$params = array_merge($whererow, $upt_anrow['params'], $ins_anrow['params']);
$rst = $this->qry($sql, $params?:Array(), "", $print);
return (bool)$rst;
}
public function delete($tb, $where, $whererow="", $print=""){
$where = $where?:"1=1";
$sql = "delete from {$tb} where {$where}";
$rst = $this->qry($sql, $whererow?:Array(), "", $print);
return (bool)$rst;
}
public function insertId($tb){
if( $tb ){
$sql = "select ident_current(?)";
return $this->queryFirstField($sql,array($tb));
}else{
$sql = "select @@identity";
return $this->queryFirstField($sql);
}
//@@IDENTITY 현재 세션의 테이블에서 생성된 마지막 ID 값을 반환합니다. --// 현재 세션내 모든 테이블에서 발생하는 ID값중 마지막
//SCOPE_IDENTITY() 현재 세션의 테이블에서 생성된 마지막 ID 값을 반환합니다. --// 현재 세션내 특
//IDENT_CURRENT() 임의 세션 및 범위에 있는 특정 테이블에 생성된 값을 반환합니다.
}
public function anqry($row){ // 필드와 값 분리 + assign value
$fld = array();
$val = array();
$params = array();
foreach( (array)$row as $k => $v ){
$fld[] = $k;
if( $this->chkeval($v) ){
$val[] = $this->valeval($v);
}else{
$val[] = "?";
$params[] = $v;
}
}
return Array( "fld"=>$fld, "val"=>$val, "params"=>$params );
}
public function result($stmt, $rows=0, $cols=0){
$rows = intval($rows);
for( $a=0 ; $a<=$rows ; $a++ ){
if( is_int($cols) ){
$arr = $this->fetch_row($stmt);
}else{
$arr = $this->fetch_array($stmt);
}
}
return is_array($arr)?$arr[$cols]:$arr;
}
public function mkstr( $sql, $params="" ){ //쿼리 출력
$params = $params?:Array();
$str = $sql;
for( $a=0 ; $a < substr_count($sql, "?") ; $a++ ){
$str = $this->str_freplace("?","'{$params[$a]}'",$str);
}
return $str;
}
public function str_freplace( $needle, $replace, $str ){
$pos = strpos($str, $needle);
if( $pos !== false ){
$nstr = substr_replace($str, $replace, $pos, strlen($needle));
}
return $nstr;
}
public function limit($start, $length){
if( $length > 0 ){
return " offset {$start} rows fetch next {$length} rows only ";
}
return '';
}
public function addLimit($sql, $ordby, $start, $length){
$ordby = $ordby?:1;
$start = $start?:0;
$length = $length?:999999999998;
if( $this->dboption["database_version"] && $this->dboption["database_version"] <= "2008" ){
$start = $start+1;
$length = $start+$length-1;
$sql = "select * from ( select *, row_number() over(order by {$ordby}) as ROWNUM from ({$sql}) as tblsub ) as tblmain where ROWNUM between {$start} and {$length}";
}else {
$sql = "{$sql} order by {$ordby} offset {$start} rows fetch next {$length} rows only ";
}
return $sql;
}
public function sqleval($str){
return chr(27).$str;
}
public function chkeval($str){
if( !is_array($str) && preg_match("/^".chr(27)."/ims",$str) ){
return true;
}
return false;
}
public function valeval($str,$val=""){
return preg_replace("/^".chr(27)."/ims",$val,$str);
}
public function tableExists( $table ){
if( !$table ) return false;
$tbl = explode(".",$table);
if( !$tbl[1] ){
$database = "dbo";
$table = $tbl[0];
}else{
$database = $tbl[0];
$table = $tbl[1];
}
$cnt = $this->queryFirstField("select 1 from Information_schema.tables where TABLE_TYPE = ? and TABLE_NAME = ?", array(
"BASE TABLE",
$table
));
if( $cnt ){
return true;
}else{
if( !( $fs = fopen( TB_schema_file, "r") ) ) return false;
while( $rw = fgets($fs, 255) ){
$tbname = defined("TB_HEAD")?preg_replace("/^".TB_HEAD."/","",$table):$table;
if( chop($rw) == "[{$tbname}]" ) break;
}
$query = "create table {$database}.{$table} ";
while( $rw = fgets($fs, 255) ){
if( chop($rw) != "-end-" ){
$rw = preg_replace("/ comment[ \=].*\'.*\'/ims","",$rw);
$rw = preg_replace("/CONSTRAINT pk\_/ims","CONSTRAINT pk_".TB_HEAD,$rw);
$rw = preg_replace("/CONSTRAINT fk\_/ims","CONSTRAINT fk_".TB_HEAD,$rw);
$rw = preg_replace("/CONSTRAINT uk\_/ims","CONSTRAINT uk_".TB_HEAD,$rw);
$rw = preg_replace("/CONSTRAINT ik\_/ims","CONSTRAINT ik_".TB_HEAD,$rw);
$query .= $rw;
}else{
break;
}
}
fclose($fs);
$rst = $this->qry($query);
if( $rst ){
include TB_data_file;
if( isset($table_base_data[$tbname]) ){
foreach( $table_base_data[$tbname] as $val ){
$this->insert($table, $val);
}
}
}
return $rst;
}
}
public function putQueryLog( $save_sql, $save_params, $result ){
global $__dbconn__;
if( !defined("TB_query_log") ) return false;
if( preg_match("/Information_schema.tables/ims", $save_sql) ) return false;
$this->delQueryLog(1);
$qryrow = Array(
"query_date" => $this->sqleval("CURRENT_TIMESTAMP"),
"query_result" => $result,
"host_name" => $this->dboption["database_host"],
"db_name" => $this->dboption["database_name"],
"query_string" => $save_sql,
"query_params" => @print_r($save_params, true),
"visit_sess" => $_SESSION['visit_sess'],
"member_id" => $GLOBALS['_Umem']['member_id'],
);
$anrow = $this->anqry($qryrow);
$sql = "insert into ".TB_query_log." (".implode(",",$anrow['fld']).") values (".implode(",",$anrow['val']).")";
return @sqlsrv_query($__dbconn__, $sql, $anrow['params']);
}
public function delQueryLog( $month = 6 ){
global $__dbconn__;
if( rand(1,100) === 50 ){ // 1% 확률로 삭제
$month= -1*abs($month);
$sql = "delete from ".TB_query_log." where query_date < dateadd(month, {$month}, getdate()) ";
return @sqlsrv_query($__dbconn__, $sql);
}
return false;
}
public function callTransaction(){
return sqlsrv_begin_transaction( $this->dbconn );
}
public function callCommit(){
return sqlsrv_commit( $this->dbconn );
}
public function callRollBack(){
return sqlsrv_rollback( $this->dbconn );
}
public function setPrint(){
$this->query_print = true;
}
public function resetPrint(){
$this->query_print = false;
}
public function setRecord(){
$this->query_record = true;
}
public function resetRecord(){
$this->query_record = false;
}
}
class BaseDB {
public $DB;
public $lcrypt;
public function __construct($db_option=""){
$this->DB = new DB_Mssql($db_option);
$this->lcrypt = new lcrypt();
}
}