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"].")";
}
}
소스를 더 살펴보니 mysql 의 경우 _process_fields란 함수를 이용해서 여러 column값을 스트링으로 전환을 합니다. 그런데 이 함수가 sqlsrv에서는 제공이 안되어 있습니다. 따라서 mysql에서처럼 배열로 주어진 여러개의 컬럼 정보들을 스트링으로 변환하는 _process_fields함수를 따로 만들어 사용해야 할 것 같네요. mysql의 함수를 조금 수정하면 될 것 같습니다. 마찬가지로 _alter_table함수도 mysql의 함수를 참조해 수정하면 될 것 같구요.
이 문제는 3.0버젼에서 해결될 것처럼 보입니다. 소스 구조가 전체적으로 바뀌어 관련 _process_column함수가 존재합니다. 오봉구님은 버그 캐처같습니다. 아래에서도 where_in버그도 찾으시더니...