programing

MariaDB prepareStatement가 where 절에 대한 characterSet을 변환하지 않습니다.

muds 2023. 8. 4. 23:20
반응형

MariaDB prepareStatement가 where 절에 대한 characterSet을 변환하지 않습니다.

MariaDB의 버그처럼 보이는 문제가 있습니다. 하지만 MariaDB 버그 데이터베이스에 게시하기 전에 여기에 게시하고 싶었습니다. 제가 뭔가 잘못하고 있는 것 같습니다.

이 문제는 다음 코드로 쉽게 재현할 수 있습니다.

public static void main(String[] args) throws ReplicationException, SQLException {
  byte[] cb3 = {-61, -92, 98, -29, -125, -70, -61, -87}; //equals to "äb?é", with “?” being a japanese character
  String corrupt = new String(cb3, Charsets.UTF_8);
  MariaDB db = new MariaDB();
  Connection conn = db.getConnection();

  //byte[] latinBytes =  corrupt.getBytes(Charset.forName("ISO-8859-1")); //workaround
  //corrupt = new String(latinBytes, Charset.forName("ISO-8859-1")); //workaround

  PreparedStatement sqlInsert = conn.prepareStatement("insert into prep values (?)");
  sqlInsert.setString(1, corrupt);
  sqlInsert.execute();
  conn.commit();
  System.out.println("insert ok");

  PreparedStatement sqlSelect = conn.prepareStatement("select * from prep where text=? ");
  sqlSelect.setString(1, corrupt);
  sqlSelect.execute();
}

내 MariaDB(문자 집합 latin1!)에는 "create table prep(text varchar(10))"라는 테이블 준비가 있습니다. 이 코드를 실행하면 삽입이 완벽하게 작동합니다. 일본어 문자는 예상대로 "?"로 변환됩니다.그러나 sqlSelect는 전혀 작동하지 않으며 "Inligal mix of colations(latin1_general_cs,INCLIVEL) 및 (utf8_general_ci, COERCIBLE)은 '=' 작업에 사용됩니다."

sql을 "prep에서 select *"로 변경하면 text=?colate latin1_general_cs", "COLLATION 'latin1_general_cs'가 CARRACHER SET 'utf8'에 대해 유효하지 않습니다."라는 오류 메시지가 표시됩니다.따라서 저는 제 바인딩 변수 "corrupt"가 where 절에 대해 latin1로 변환되지 않았다고 결론 내렸습니다.하지만 이 변환은 인서트와 함께 작동했기 때문에 예상했습니다.

해결 방법이 있습니다. "//해결 방법" 두 줄을 활성화하면 문자열이 데이터베이스에 제공되기 전에 Java로 변환됩니다.하지만, 저는 이것이 필요하지 않다고 생각합니다.

오라클 데이터베이스에서 동일한 코드를 실행해도 오류가 발생하지 않습니다.누가 이것을 mysql 데이터베이스에서 실행할 수 있습니까?

그래서, 이것이 여러분에게 벌레처럼 보이거나, 제가 뭔가를 놓치고 있는 것입니까?

추가 정보:
MariaDB 버전 10.0.14, Java용 MariaDB 클라이언트 라이브러리: 1.1.7
jdbc 연결 문자열은 다음과 같습니다.

"jdbc:mariadb://localhost:3306/myDb?rewriteBatchedStatements=true&useServerPrepStmts=false"  

데이터베이스를 시작하려면 기본 "my-large.ini"를 사용합니다.
다음 코드로 데이터베이스를 작성했습니다.

create database myDb
DEFAULT CHARACTER SET latin1 
COLLATE latin1_general_cs;

업데이트: mariaDB팀에 버그 보고서를 제출했습니다. https://mariadb.atlassian.net/browse/CONJ-117

MariaDB와 MySQL을 모두 사용하여 테스트 코드를 실험한 후에 저는 그들이 다르게 행동하는 것처럼 보인다는 것을 확인할 수 있습니다.하지만, 저는 마리아DB에서 그것을 꼭 "버그"라고 부르지는 않을 것입니다.

데이터베이스 서버 자체와의 응답 차이로 나타납니다.MariaDB Java Client 1.7과 MySQL Connector/J 5.1.27을 모두 사용하여 MariaDB 10.0.13 서버에 변경 사항을 적용해 보았더니 둘 다 동일한 결과를 얻었습니다. MariaDB는 UTF-8의 첫 번째, 두 번째, 네 번째 문자를 Latin1로 자동 번역할 수 있었습니다.그러나 Latin1에 해당하는 문자가 없기 때문에 세 번째(일본어) 문자 U+30FA(UTF-8의 경우 0xE30x830xBA)에서 질식했습니다.

일리 있는 말이야.에 따라 할 수 없는 모든 를 간단하게할 수 .'?'하지만 그것이 항상 바람직한 것은 아닙니다.에게 라틴 으로 강제하도록 하는 입니다.'?'마리아 DB에 전달합니다.당신은 그것이 필요하지 않다고 생각하지만, 저는 동의할 수 없습니다.

따라서 MariaDB의 "버그"인지 여부는 MariaDB가 "설계된 대로" 작동하는지 여부에 따라 결정됩니다.즉, MariaDB가 MySQL과 다르게 동작한다고 해서 반드시 MariaDB의 버그가 되는 것은 아닙니다.예를 들어 MariaDB 5.5.31에서는 CAST()의 동작을 변경하여 이진 문자열 리터럴 해석의 문제를 해결했습니다. 결과는 다음과 같습니다.

이로 인해 이전 버전의 MariaDB 및 모든 버전의 MySQL과 호환되지 않습니다.

즉, 언제든지 문제를 MariaDB 버그로 보고하고 대응 방식을 확인할 수 있습니다.

언급URL : https://stackoverflow.com/questions/26380888/mariadb-preparestatement-does-not-convert-characterset-for-where-clause

반응형