hoon's bLog

SQL ERROR | org.postgresql.util.PSQLException: ERROR: input of anonymous composite types is not implemented 본문

IT/Error

SQL ERROR | org.postgresql.util.PSQLException: ERROR: input of anonymous composite types is not implemented

개발한기발자 2024. 3. 18. 10:37
반응형

Error 발생 경로

환경 : Spring Mybatis에서 PostgreSQL에서 쿼리문을 작성하는 도중,

아래와 같은 에러가 발생했다.

org.postgresql.util.PSQLException: ERROR: input of anonymous composite types is not implemented
  Position: 702
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2565)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2297)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:322)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:481)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:401)
	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:164)
	at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:153)
	at net.sf.log4jdbc.sql.jdbcapi.PreparedStatementSpy.execute(PreparedStatementSpy.java:443)
	at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44)
	at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
	at com.sun.proxy.$Proxy164.execute(Unknown Source)
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64)
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79)
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63)
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:83)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:76)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426)
	at com.sun.proxy.$Proxy82.selectOne(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:159)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:87)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:93)
	at com.sun.proxy.$Proxy147.retrieveMemberPointDetailTotalCount(Unknown Source)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    ... 중략 ...
	at java.lang.Thread.run(Thread.java:748)
input of anonymous composite types is not implemented

번역기를 돌려보니 익명 복합 유형의 입력이 구현되지 않았다?

Mybatis 관련 문법 문제인줄 알았으나, DB tool에서 역시 같은 에러가 발생하고 있었다.

Stack Overflow도 참조 해봤으나, 내가 발생시킨 에러와는 조금 유형이 달랐다.

에러가 발생한 SQL문은 다음과 같다.

WITH member_info AS (
    SELECT *
      FROM fn_get_member_info(CAST('59' AS BIGINT))
)
SELECT COUNT(*)      AS total_point_count
     , SUM(fd_point) AS total_point_sum
  FROM member_info                AS member
  LEFT OUTER JOIN tb_member_point AS point
    ON member.pk_member = point.fk_member
 WHERE TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') >= '2024-02-12'
   AND TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') <= '2024-03-12'
   AND point.fd_save_use_code IN (CASE WHEN '4401' = '4401' THEN '4501'
                                       ELSE ('4502', '4503') END);
  • member_info :  59라는 pk 값을 가지고 있는 회원의 정보를 가져온다.
  • tb_member_info : 회원의 포인트 정보를 가지고 있는 테이블
  • member_info를 기준으로 tb_member_info와 LEFT OUTER JOIN을 하여 해당 WHERE 조건을 따라 받은 포인트 개수(total_point_count)와 총 포인트 합계(total_point_sum)를 가져올 목적이었다.

해결

먼저 문제가 있을것 같은 AND 부분을 주석처리하여 SELECT를 했다.

WITH member_info AS (
    SELECT *
      FROM fn_get_member_info(CAST('59' AS BIGINT))
)
SELECT COUNT(*)      AS total_point_count
     , SUM(fd_point) AS total_point_sum
  FROM member_info                AS member
  LEFT OUTER JOIN tb_member_point AS point
    ON member.pk_member = point.fk_member
 WHERE TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') >= '2024-02-12'
   AND TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') <= '2024-03-12'
--   AND point.fd_save_use_code IN (CASE WHEN '4401' = '4401' THEN '4501'
--                                       ELSE ('4502', '4503') END);

정상적으로 나온걸 보니 아무래도 CASE문 문법에서 뭔가 문제가 있는 듯하다.

아하!!!

CASE문은 주어진 조건에 따라 단일 값 또는 하나의 값만 줄 수 있기 때문에 ( '4502', '4503' ) 처럼,

여러 개의 값을 줄 수 없다.

따라서 내가 하고 싶은 point.fd_save_use_code IN (원하는 값1, 원하는 값2,...) 이 부분 자체를 CASE문의 결과 값으로 하자!!

WITH member_info AS (
    SELECT *
      FROM fn_get_member_info(CAST('59' AS BIGINT))
)
SELECT COUNT(*)      AS total_point_count
     , SUM(fd_point) AS total_point_sum
  FROM member_info                AS member
  LEFT OUTER JOIN tb_member_point AS point
    ON member.pk_member = point.fk_member
 WHERE TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') >= '2024-02-12'
   AND TO_CHAR(point.fd_regdate, 'YYYY-MM-DD') <= '2024-03-12'
   AND ( CASE WHEN '4401' = '4401' THEN point.fd_save_use_code = '4501'
              ELSE point.fd_save_use_code IN ('4502', '4503')
          END );

이렇게 처리하면 내가 point.fd_save_use_code에 값을 원하는 대로 할당할 수 있다.

결론

실무를 한지 언 5년이 다되어가는데도,

아직도 SQL 문법적으로 부족한 부분이 너무 많다.

계속해서 나의 치부와 부족함을 이렇게 기록하며,

다시는 같은 실수를 반복하지 않도록 더욱! 정진해야겠다!

 

언제나 새로운 정보 공유와 잘못된 정보

비판/지적/태클은 환영입니다!

도움이 되셨다면 공감♥️, 댓글 부탁드려요:)

끝.

728x90
반응형