TIP게시판

제목 sqlsrv_forge.php의 _alter_table 버그
글쓴이 오봉구 작성시각 2013/10/19 01:10:42
댓글 : 2 추천 : 0 스크랩 : 0 조회수 : 12032   RSS
 CI 2.1.4 를 사용중입니다

db drvier는 sqlsrv를 사용중이구요,

add_column() 함수를 사용했는데요,

사용자 가이드와 달리 에러를 뱉어내더라구요,


 core를 찾다보니 버그인것 같아 글을 남깁니다.


사용자 가이드에 보면

$fields = array(
                        'preferences' => array('type' => 'TEXT')
);
$this->dbforge->add_column('table_name', $fields);

와 같이 사용하는 함수입니다. 두번째 파라미터에서 배열의 형식으로 값을 넘겨줍니다.


실제로 system/database/DB_forge.php를 열어서 252번째 줄을 열어보면

function add_column($table = '', $field = array(), $after_field = '')

파라미터가 배열형식으로 넘어가는 것을 확인 할 수 있습니다.

add_column() 함수 내부에 

$this->_alter_table() 함수를 통해 각 db driver의 함수가 실행되게 되는데,


mysql driver의 경우에는 _protect_identifiers() 란 함수를 통해 파라미터로 넘겨준 배열을 스트링으로 만들어주는 과정을 거쳐

정상적으로 동작하게 되는데,

sqlsrv driver의 경우에는 

이러한 과정없이 array를 바로 쿼리문에 집어넣게 됩니다.

그래서 생성된 쿼리를 보면

~~~ 컬럼명 컬럼속성(컬럼길이) ~~~~ 와 같이 생성되어야 할 쿼리가

~~~ Array ~~~ 와 같이 생성되어서 에러가 나더라구요,


위 문제를 해결하려면 

system/database/drivers/sqlsrv_forge.php 의 191번째 줄에 있는 _alter_table() 함수를 수정하시면 됩니다.


원래 코드는 

function _alter_table($alter_type, $table, $column_name, $column_definiti $default_value = '', $null = '', $after_field = '')
{
$sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($column_name);
 
// DROP has everything it needs now.
if ($alter_type == 'DROP')
{
return $sql;
}
 
$sql .= " $column_definition";


제가 수정한 코드는 

function _alter_table($alter_type, $table, $column_name, $column_definiti $default_value = '', $null = '', $after_field = '')
{
$field_name = array_keys($column_name)[0];
$column_definition = $column_name[$field_name];
$sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ".$this->db->_protect_identifiers($field_name);
 
// DROP has everything it needs now.
if ($alter_type == 'DROP')
{
return $sql;
}
 
//$sql .= " $column_definition";
if (array_key_exists('type', $column_definition)) {
$sql .= " ".$column_definition['type'];
if (array_key_exists('constraint', $column_definition)) {
$sql .= "(".$column_definition["constraint"].")";
}
}
 다음글 layout을 사용할때 view안에 css넣기 (1)
 이전글 Controller를 통한 전역변수 사용 (3)

댓글

letsgolee / 2013/10/19 20:34:08 / 추천 0
 버그는 맞습니다. 소스를 살펴보니 문제가 있네요. 그런데 오봉구님의 방법도 문제가 있습니다. _alter_table함수에 오는 $column_name은 배열로 오는데 이게 꼭 한 column만 오지 않는데 오봉구님의 것은 오직 하나만 받는 방법이기 때문입니다.

소스를 더 살펴보니 mysql 의 경우 _process_fields란 함수를 이용해서 여러 column값을 스트링으로 전환을 합니다. 그런데 이 함수가 sqlsrv에서는 제공이 안되어 있습니다. 따라서 mysql에서처럼 배열로 주어진 여러개의 컬럼 정보들을 스트링으로 변환하는 _process_fields함수를 따로 만들어 사용해야 할 것 같네요. mysql의 함수를 조금 수정하면 될 것 같습니다. 마찬가지로 _alter_table함수도 mysql의 함수를 참조해 수정하면 될 것 같구요.

이 문제는 3.0버젼에서 해결될 것처럼 보입니다. 소스 구조가 전체적으로 바뀌어 관련 _process_column함수가 존재합니다. 오봉구님은 버그 캐처같습니다. 아래에서도 where_in버그도 찾으시더니...
한대승(불의회상) / 2013/10/21 08:53:56 / 추천 0
오봉구// 좋은 정보 감사 합니다.
주로 사용되는 DB가 mysql이다 보니 다른 DB에 대한 버그들은 잘 인지 하지 못하게 되는군요.
소중한 정보 다시 한번 감사 합니다.