Org postgresql util psqlexception ошибка оператор не существует integer character varying

I think it is telling you exactly what is wrong. You cannot compare an integer with a varchar. PostgreSQL is strict and does not do any magic typecasting for you. I’m guessing SQLServer does typecasting automagically (which is a bad thing).

If you want to compare these two different beasts, you will have to cast one to the other using the casting syntax ::.

Something along these lines:

create view view1
as 
select table1.col1,table2.col1,table3.col3
from table1 
inner join
table2 
inner join 
table3
on 
table1.col4::varchar = table2.col5
/* Here col4 of table1 is of "integer" type and col5 of table2 is of type "varchar" */
/* ERROR: operator does not exist: integer = character varying */
....;

Notice the varchar typecasting on the table1.col4.

Also note that typecasting might possibly render your index on that column unusable and has a performance penalty, which is pretty bad. An even better solution would be to see if you can permanently change one of the two column types to match the other one. Literately change your database design.

Or you could create a index on the casted values by using a custom, immutable function which casts the values on the column. But this too may prove suboptimal (but better than live casting).

Google Chrome 59.0.3071.115
Ubuntu 17.04
PostgreSQL 9.6.3 on x86_64-pc-linux-gnu, compiled by gcc (Debian 4.9.2-10) 4.9.2, 64-bit

  • Metabase version: 0.25.1
  • Metabase hosting environment: Docker
  • Metabase internal database: H2

SELECT COUNT("order".order_id) AS sclr_0, TO_CHAR("order".created_at, 'YYYY-MM-DD') AS sclr_1 FROM "order" where {{created_at}} AND {{restaurant}} GROUP BY sclr_1;

restaurant variable -> Widget: id

ERROR: operator does not exist: integer = character varying Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts. Position: 331

Logs

Jul 28 16:27:32 WARN metabase.query-processor :: {:status :failed,
:class java.lang.Exception,
:error «ERROR: operator does not exist: integer = character varyingn Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.n Position: 275»,
:stacktrace
[«driver.generic_sql.query_processor$do_with_try_catch.invokeStatic(query_processor.clj:349)»
«driver.generic_sql.query_processor$do_with_try_catch.invoke(query_processor.clj:345)»
«driver.generic_sql.query_processor$execute_query.invokeStatic(query_processor.clj:396)»
«driver.generic_sql.query_processor$execute_query.invoke(query_processor.clj:392)»
«driver$fn__22473$G__22466__22480.invoke(driver.clj:45)»
«query_processor$execute_query.invokeStatic(query_processor.clj:49)»
«query_processor$execute_query.invoke(query_processor.clj:43)»
«query_processor.middleware.mbql_to_native$mbql__GT_native$fn__26496.invoke(mbql_to_native.clj:30)»
«query_processor.middleware.annotate_and_sort$annotate_and_sort$fn__25019.invoke(annotate_and_sort.clj:41)»
«query_processor.middleware.limit$limit$fn__26451.invoke(limit.clj:14)»
«query_processor.middleware.cumulative_aggregations$cumulative_aggregation$fn__26299.invoke(cumulative_aggregations.clj:46)»
«query_processor.middleware.cumulative_aggregations$cumulative_aggregation$fn__26299.invoke(cumulative_aggregations.clj:46)»
«query_processor.middleware.format_rows$format_rows$fn__26442.invoke(format_rows.clj:21)»
«query_processor.middleware.results_metadata$record_and_return_metadata_BANG_$fn__27720.invoke(results_metadata.clj:88)»
«query_processor.middleware.resolve$resolve_middleware$fn__24627.invoke(resolve.clj:329)»
«query_processor.middleware.expand$expand_middleware$fn__26193.invoke(expand.clj:536)»
«query_processor.middleware.add_row_count_and_status$add_row_count_and_status$fn__24711.invoke(add_row_count_and_status.clj:14)»
«query_processor.middleware.driver_specific$process_query_in_context$fn__26319.invoke(driver_specific.clj:12)»
«query_processor.middleware.resolve_driver$resolve_driver$fn__27730.invoke(resolve_driver.clj:14)»
«query_processor.middleware.cache$maybe_return_cached_results$fn__25099.invoke(cache.clj:146)»
«query_processor.middleware.catch_exceptions$catch_exceptions$fn__26241.invoke(catch_exceptions.clj:58)»
«query_processor$process_query.invokeStatic(query_processor.clj:124)»
«query_processor$process_query.invoke(query_processor.clj:120)»
«query_processor$run_and_save_query_BANG_.invokeStatic(query_processor.clj:232)»
«query_processor$run_and_save_query_BANG_.invoke(query_processor.clj:227)»
«query_processor$fn__27764$process_query_and_save_execution_BANG___27769$fn__27770.invoke(query_processor.clj:270)»
«query_processor$fn__27764$process_query_and_save_execution_BANG___27769.invoke(query_processor.clj:256)»
«api.card$run_query_for_card.invokeStatic(card.clj:491)»
«api.card$run_query_for_card.doInvoke(card.clj:477)»
«api.card$fn__29925$fn__29928$fn__29929.invoke(card.clj:498)»
«api.card$fn__29925$fn__29928.invoke(card.clj:497)»
«api.common.internal$do_with_caught_api_exceptions.invokeStatic(internal.clj:227)»
«api.common.internal$do_with_caught_api_exceptions.invoke(internal.clj:222)»
«api.card$fn__29925.invokeStatic(card.clj:493)»
«api.card$fn__29925.invoke(card.clj:493)»
«middleware$enforce_authentication$fn__28955.invoke(middleware.clj:122)»
«api.routes$fn__40133.invokeStatic(routes.clj:56)»
«api.routes$fn__40133.invoke(routes.clj:56)»
«routes$fn__40784$fn__40785.doInvoke(routes.clj:75)»
«routes$fn__40784.invokeStatic(routes.clj:71)»
«routes$fn__40784.invoke(routes.clj:71)»
«middleware$log_api_call$fn__29054$fn__29056.invoke(middleware.clj:331)»
«middleware$log_api_call$fn__29054.invoke(middleware.clj:330)»
«middleware$add_security_headers$fn__29004.invoke(middleware.clj:245)»
«middleware$bind_current_user$fn__28959.invoke(middleware.clj:142)»
«middleware$maybe_set_site_url$fn__29008.invoke(middleware.clj:268)»],
:query
{:type «native»,
:native
{:query «SELECT COUNT(«order».order_id) AS sclr_0, TO_CHAR(«order».created_at, ‘YYYY-MM-DD’) ASnsclr_1 FROM «order» where {{created_at}} [[AND {{restaurant}}]]nGROUP BY sclr_1;»,
:template_tags
{:created_at
{:id «431f6a38-455e-db5e-d862-59d6903b3242», :name «created_at», :display_name «Created at», :type «dimension», :required true, :dimension [«field-id» 166], :widget_type «date/range»},
:restaurant {:id «66ad5e09-0957-d8e2-d85f-30cab586024a», :name «restaurant», :display_name «Restaurant», :type «dimension», :dimension [«field-id» 181], :widget_type «id»}}},
:constraints {:max-results 10000, :max-results-bare-rows 2000},
:parameters [{:type «id», :target [«dimension» [«template-tag» «restaurant»]], :value «6»}],
:cache_ttl nil,
:info
{:executed-by 1,
:context :question,
:card-id 3,
:dashboard-id nil,
:query-hash [-49, -69, -67, 38, 55, -79, -44, 54, 54, -72, -75, -20, 71, -14, 52, -66, -89, -106, -38, 7, 42, 16, 27, 25, 122, 123, 24, -84, 42, 71, -116, -126],
:query-type «native»}},
:expanded-query nil}

Jul 28 16:27:32 WARN metabase.query-processor :: Query failure: ERROR: operator does not exist: integer = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Position: 275
[«query_processor$assert_query_status_successful.invokeStatic(query_processor.clj:201)»
«query_processor$assert_query_status_successful.invoke(query_processor.clj:194)»
«query_processor$run_and_save_query_BANG_.invokeStatic(query_processor.clj:233)»
«query_processor$run_and_save_query_BANG_.invoke(query_processor.clj:227)»
«query_processor$fn__27764$process_query_and_save_execution_BANG___27769$fn__27770.invoke(query_processor.clj:270)»
«query_processor$fn__27764$process_query_and_save_execution_BANG___27769.invoke(query_processor.clj:256)»
«api.card$run_query_for_card.invokeStatic(card.clj:491)»
«api.card$run_query_for_card.doInvoke(card.clj:477)»
«api.card$fn__29925$fn__29928$fn__29929.invoke(card.clj:498)»
«api.card$fn__29925$fn__29928.invoke(card.clj:497)»
«api.common.internal$do_with_caught_api_exceptions.invokeStatic(internal.clj:227)»
«api.common.internal$do_with_caught_api_exceptions.invoke(internal.clj:222)»
«api.card$fn__29925.invokeStatic(card.clj:493)»
«api.card$fn__29925.invoke(card.clj:493)»
«middleware$enforce_authentication$fn__28955.invoke(middleware.clj:122)»
«api.routes$fn__40133.invokeStatic(routes.clj:56)»
«api.routes$fn__40133.invoke(routes.clj:56)»
«routes$fn__40784$fn__40785.doInvoke(routes.clj:75)»
«routes$fn__40784.invokeStatic(routes.clj:71)»
«routes$fn__40784.invoke(routes.clj:71)»
«middleware$log_api_call$fn__29054$fn__29056.invoke(middleware.clj:331)»
«middleware$log_api_call$fn__29054.invoke(middleware.clj:330)»
«middleware$add_security_headers$fn__29004.invoke(middleware.clj:245)»
«middleware$bind_current_user$fn__28959.invoke(middleware.clj:142)»
«middleware$maybe_set_site_url$fn__29008.invoke(middleware.clj:268)»]

Перейти к контенту

My query is something like this. I try to get a status for a list of ids.

select order_number, order_status_name
from data.order_fact s
join data.order_status_dim l
on s.order_status_key = l.order_status_key
where 
order_number in (1512011196169,1512011760019,1512011898493,1512011972111)

I get an error though that says:

ERROR:  operator does not exist: character varying = bigint
LINE 6: order_number in (1512011196169,1512011760019,1512011898493,1...
                     ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

Do you have any clue on how I should reform the ids to get it work?
Thanks a lot!

asked Jan 12, 2016 at 10:06

Athanasia Ntalla's user avatar

If you can’t change the type of numbers within in, you could use cast:

select * from numbers_as_string
where cast(my_numbers_as_string as int) in (1,2,3)

answered Jun 6, 2020 at 1:05

Emeeus's user avatar

This happen too when you are using native query in sprinboot and you are passing a parameter as string but that field is a (integer or long) in your model/entity, also when you are comparing a string with a integer due that param is used like string without casting.
so you should cast it as integer in the native query like this

x::integer

for example:

       @Query(value=" 
        ......
    .....
         inner join tablex t on t.x::integer = pv.id n"+
....
....
        ")
         List<Object> getMyQuery(@Param("x") String x)

answered Dec 5, 2022 at 21:24

nativelectronic's user avatar

I am trying to run this query:

select *
from my_table
where column_one=${myValue}

I get the following error in Datagrip:

[42883] ERROR: operator does not exist: character varying = bigint Hint: No operator matches the given name and argument types. You might need to add explicit type casts.

Now, I have found this question, and I can fix the error by putting a string like this:

select *
from my_table
where column_one='123'

What I need is a way to pass in the ‘123’ as a parameter. I usually do this ${myValue} and it works, but I am not sure how to keep my variable there as an input so I can run dynamic queries in code and let Postgres understand I want to pass in a string and not a number.

Any suggestions?

Here’s a screenshot of how I am putting the parameter value in DataGrip…:
enter image description here

Ok, so, I just tried to put quotes in the data grip parameters input field for myValue @thirumal’s answer things work. I didn’t know I have to quote the value for it to work.
This is what it looks like:

enter image description here

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account


Closed

vjykumar opened this issue

Jul 13, 2018

· 15 comments

Assignees

@rwinch

Comments

@vjykumar

When trying to use Spring Security ACL, I am facing error: org.postgresql.util.PSQLException: ERROR: operator does not exist: bigint = character varying

Below is the error stack:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [select acl_object_identity.object_id_identity, acl_entry.ace_order, acl_object_identity.id as acl_id, acl_object_identity.parent_object, acl_object_identity.entries_inheriting, acl_entry.id as ace_id, acl_entry.mask, acl_entry.granting, acl_entry.audit_success, acl_entry.audit_failure, acl_sid.principal as ace_principal, acl_sid.sid as ace_sid, acli_sid.principal as acl_principal, acli_sid.sid as acl_sid, acl_class.class from acl_object_identity left join acl_sid acli_sid on acli_sid.id = acl_object_identity.owner_sid left join acl_class on acl_class.id = acl_object_identity.object_id_class left join acl_entry on acl_object_identity.id = acl_entry.acl_object_identity left join acl_sid on acl_entry.sid = acl_sid.id where ( (acl_object_identity.object_id_identity = ? and acl_class.class = ?)) order by acl_object_identity.object_id_identity asc, acl_entry.ace_order asc]; nested exception is org.postgresql.util.PSQLException: ERROR: operator does not exist: bigint = character varying
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Position: 781
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:101)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1402)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:620)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:657)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:688)
at org.springframework.security.acls.jdbc.BasicLookupStrategy.lookupObjectIdentities(BasicLookupStrategy.java:384)
at org.springframework.security.acls.jdbc.BasicLookupStrategy.readAclsById(BasicLookupStrategy.java:339)
at org.springframework.security.acls.jdbc.JdbcAclService.readAclsById(JdbcAclService.java:130)
at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:112)
at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:120)

I traced the issue till this line:

ps.setString((2 * i) + 1, identifier);

I am wondering if we have decided that Spring Security ACL will always support Long SID Identifiers, why are we converting the identifier to String and setting the parameter as String.
Any pointers in that direction?

@nenaraab

Hi,

I face the same issue. As recommended in the current Spring.io documentation i’ve setup the acl tables in my PostgreSQL database, with column acl_object_identity.object_id_identity of type varchar(36).

IMHO the args parameter in queryForObject method call is not properly specified.

It is new Object[]{oid.getType(), oid.getIdentifier()}, but it must be new Object[]{oid.getType(), "" + oid.getIdentifier()} as shown in the example below:

public class PostgresJdbcMutableAclService extends JdbcMutableAclService {
        //copy of this JdbcMutableAclService.selectObjectIdentityPrimaryKey
        private String selectObjectIdentityPrimaryKey = "select acl_object_identity.id from acl_object_identity, acl_class "
                + "where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? "
                + "and acl_object_identity.object_id_identity = ?";

        public PostgresJdbcMutableAclService(DataSource dataSource, LookupStrategy lookupStrategy, AclCache aclCache) {
            super(dataSource, lookupStrategy, aclCache);
        }
        
        @Override
        protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
            try {
                return (Long) this.jdbcTemplate.queryForObject(this.selectObjectIdentityPrimaryKey, Long.class, new Object[]{oid.getType(), "" + oid.getIdentifier()});
            } catch (DataAccessException var3) {
                return null;
            }
        }

        @Override
        public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
            Object[] args = new Object[]{"" + parentIdentity.getIdentifier(), parentIdentity.getType()};
            List<ObjectIdentity> objects = this.jdbcTemplate.query(this.findChildrenSql, args, new RowMapper<ObjectIdentity>() {
                public ObjectIdentity mapRow(ResultSet rs, int rowNum) throws SQLException {
                    String javaType = rs.getString("class");
                    Serializable identifier = (Serializable) rs.getObject("obj_id");
//                    identifier = JdbcAclService.this.aclClassIdUtils.identifierFrom(identifier, rs);
                    return new ObjectIdentityImpl(javaType, identifier);
                }
            });
            return objects.size() == 0 ? null : objects;
        }
}

Further references

  • Postgresql release notes: on-character data types are no longer automatically cast to TEXT

Any other ideas?

@rwinch

There is support for non int identifiers in Spring Security now. If someone wants to setup a sample to reproduce this then we can try and go from there.

@mangei

@nenaraab

@rwinch
Where to setup a PostgreSQL sample / is there any reference for other databases?

Unfortuantely, the support of non-integer identifiers does not fix my Postgres issue :-(

@rwinch

@nenaraab There isn’t a sample with Postgres. The contact sample is the reference for ACL support. However, I would caution you that we don’t typically recommend using ACL support because it requires doing in memory joins. If you have a million records and the user only is able to access 2, then you must process all the records in memory.

Instead, we recommend using the Spring Data support.

I see you were able to make some progress on this in #6050 Does that resolve your issue?

@mangei

In addition to my changes above, I had to adjust two more queries, to make it work with the correct types:

    @Bean
    public JdbcMutableAclService aclService() {
        JdbcMutableAclService jdbcMutableAclService = new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());

        // from documentation
        jdbcMutableAclService.setClassIdentityQuery("select currval(pg_get_serial_sequence('acl_class', 'id'))");
        jdbcMutableAclService.setSidIdentityQuery("select currval(pg_get_serial_sequence('acl_sid', 'id'))");

        // additional adjustments
        jdbcMutableAclService.setObjectIdentityPrimaryKeyQuery("select acl_object_identity.id from acl_object_identity, acl_class where acl_object_identity.object_id_class = acl_class.id and acl_class.class=? and acl_object_identity.object_id_identity = cast(? as varchar)");
        jdbcMutableAclService.setFindChildrenQuery("select obj.object_id_identity as obj_id, class.class as class from acl_object_identity obj, acl_object_identity parent, acl_class class where obj.parent_object = parent.id and obj.object_id_class = class.id and parent.object_id_identity = cast(? as varchar) and parent.object_id_class = (select id FROM acl_class where acl_class.class = ?)");

        return jdbcMutableAclService;
    }

@nenaraab

@mangei — your workaround looks much nicer than mine, leveraging the new setters :-)
Anyhow, this PR will hopefully make your additional adjustments obsolete.

@nenaraab

@rwinch thanks for the sample and the hint with ACL support… for the reasons you’ve mentioned we don’t use it for mass selects (like findChildren…) and we also don’t use @PostAuthorize for paginated REST calls.

Still, for single inserts / deletions we make

@rwinch
rwinch

changed the title
Error with postgres

Spring Security ACL Error with postgres

Nov 29, 2018

@rwinch
rwinch

changed the title
Spring Security ACL Error with postgres

Spring Security ACL: No operator matches the given name and argument type

Nov 29, 2018

@matt00000001

This comment has been minimized.

@rwinch

This comment has been minimized.

@mangei

@nenaraab & @rwinch: Thanks for your time and work to fix this issue! I appreciate this a lot =)

@fprumbau

We are using Spring-Security since acegi times, always with acl implementation. We updated to every release since. After trying 5.1.6 to 5.2.0 we reverted and tried again with 5.2.1 but have the same error. I wonder if it could be the aftermath of this change. Maybe someone have a clue?

We’are running on Oracle 12 and our error is

org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.math.BigDecimal] to type [java.lang.Long]     at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321)     at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194)     at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174)     at org.springframework.security.acls.jdbc.AclClassIdUtils.convertToLong(AclClassIdUtils.java:122)     at org.springframework.security.acls.jdbc.AclClassIdUtils.identifierFrom(AclClassIdUtils.java:71)     at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.convertCurrentResultIntoObject(BasicLookupStrategy.java:634)     at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:583)     at org.springframework.security.acls.jdbc.BasicLookupStrategy$ProcessResultSet.extractData(BasicLookupStrategy.java:558)     at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:679)     at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:617)     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:669)     at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:700)     at org.springframework.security.acls.jdbc.BasicLookupStrategy.lookupObjectIdentities(BasicLookupStrategy.java:381)     at org.springframework.security.acls.jdbc.BasicLookupStrategy.readAclsById(BasicLookupStrategy.java:336)     at org.springframework.security.acls.jdbc.JdbcAclService.readAclsById(JdbcAclService.java:129)     at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:111)     at org.springframework.security.acls.jdbc.JdbcAclService.readAclById(JdbcAclService.java:119)     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:344)     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:205)     at com.sun.proxy.$Proxy172.readAclById(Unknown Source)

@jzheaux

@fprumbau I think the one you are looking for is #4814

AclClassIdUtils has a default ConversionService that it uses now. As a workaround, you might consider configuring a GenericConversionService for BasicLookupStrategy. Otherwise, I’d recommend that you log an issue in case there is a way for the framework to take care of the concern.

@fprumbau

@jzheaux Thanx a lot, you made my day. After registering a proper implementation converting BigDecimal to long everything is good again. :-)

@urvashi01sharma

Hi @fprumbau — I am using spring-security-acl 5.2.2-RELEASE and facing same issue while converting from Integer to Long. I have my object_identity_id column defined as int in acl_object_identity table. Could you please explain me how you added your custom converter in GenericConversionService and then injected this instance to AclClassIdUtils. As I see AclClassIdUtils is using new instance of GenericConversionService.

I’ve updated paragraphs to the latest version (1.9) and tried to run the database updates.
(Sidenote — I’m using PostgreSQL as database system)
However, trying to run the post update function ‘paragraphs_post_update_rebuild_parent_fields’ results in a crash with the following error:

>  [notice] Update started: paragraphs_post_update_rebuild_parent_fields
>  [error]  SQLSTATE[42883]: Undefined function: 7 ERROR:  operator does not exist: character varying <> bigint
> LINE 5: WHERE (((p.parent_id <> f.entity_id)) OR (p.parent_type <> '...
>                              ^
> HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.: SELECT f.entity_id AS entity_id, f.field_paragraph_target_revision_id AS field_paragraph_target_revision_id, p.revision_id AS prevision_id
> FROM
> {paragraph_revision__field_paragraph} f
> INNER JOIN {paragraphs_item_revision_field_data} p ON f.field_paragraph_target_revision_id = p.revision_id
> WHERE (((p.parent_id <> f.entity_id)) OR (p.parent_type <> :db_condition_placeholder_0) OR (p.parent_field_name <> :db_condition_placeholder_1)) AND ((p.langcode = f.langcode))
> ORDER BY p.revision_id ASC NULLS FIRST
> LIMIT 100 OFFSET 0; Array
> (
>     [:db_condition_placeholder_0] => paragraph
>     [:db_condition_placeholder_1] => field_paragraph
> )
>
>  [error]  Update failed: paragraphs_post_update_rebuild_parent_fields
>  [error]  Update aborted by: paragraphs_post_update_rebuild_parent_fields

In my understanding this is caused by the type difference of the values that are being compared: ‘p.parent_id’ being ‘varying‘ and ‘f.entity_id’ being ‘bigint‘. What worked for me, was explicitly casting the value of type ‘bigint‘ to ‘varying (varchar)‘, so that the types are the same. The other way around would work too, but I thought it would be safer to cast a ‘bigint‘ to ‘varying (varchar)‘, in case the ‘p.parent_id’ wouldn’t contain a numerical value.

I’ve created a patch containing the change I did to solve this issue for me.

Tag1 supports the Drupal Project.Tag1 logo

ERROR: Operator does not exist: character varying = integer

Getting an error Operator does not exist: character varying = integer when executing an insight

Boyan Barnev avatar

Written by Boyan Barnev

Updated over a week ago

Problem

You created an SQL insight and when you execute it (or save it and view it) you get an error message stating: ERROR: Operator does not exist: character varying = integer

Cause

The above error means that somewhere in your insight you are trying to compare a text string to a numeric value. SQL can’t directly recognize the text as number, thus the comparison is not possible.

You can easily identify if that’s the case if you do a SELECT statement for the fields you want to use in your insight and observe their output by clicking the Execute button in your insight editor. If the value is surrounded in quotation marks, then it’s coming through as a text. If it’s not, then it’s numeric.

Here are two examples:

  1. In the below example, the values of the id and week fields are coming through as text:

{
"data_source_id": "5ec29e7c53e7610001d5f1be",
"id": "4",
"sync_date": "2020-06-25T00:00:00",
"week": "3"
}

2. In this example, the values of the id and week fields are coming through as numeric:

{
"data_source_id": "5ec29e7c53e7610001d5f1be",
"id": 4,
"sync_date": "2020-06-25T00:00:00",
"week": 3
}

Solution

If you must compare the values you’re extracting against numeric values, you have to cast your fields and specify the desired format. For example:

SELECT week FROM my_table WHERE id::int=4

instructs SQL to interpret the value in the id field as integer, and enables you to compare it to an integer value.

Additional information

  • In this article we use the :: operator to cast to a numeric type. You can read more about it here: PostgreSQL numeric data types

Here i am trying to create view as shown below in example:

Example:

 create view view1
 as 
 select table1.col1,table2.col1,table3.col3
 from table1 
 inner join
 table2 
 inner join 
 table3
 on 
 table1.col4 = table2.col5 
 /* Here col4 of table1 is of "integer" type and col5 of table2 is of type "varchar" */
 /* ERROR: operator does not exist: integer = character varying */
 ....;

Note: The same query executed in sql server but getting the above error in postgreSQL.

This question is related to
postgresql
casting
integer
varchar

I think it is telling you exactly what is wrong. You cannot compare an integer with a varchar. PostgreSQL is strict and does not do any magic typecasting for you. I’m guessing SQLServer does typecasting automagically (which is a bad thing).

If you want to compare these two different beasts, you will have to cast one to the other using the casting syntax ::.

Something along these lines:

create view view1
as 
select table1.col1,table2.col1,table3.col3
from table1 
inner join
table2 
inner join 
table3
on 
table1.col4::varchar = table2.col5
/* Here col4 of table1 is of "integer" type and col5 of table2 is of type "varchar" */
/* ERROR: operator does not exist: integer = character varying */
....;

Notice the varchar typecasting on the table1.col4.

Also note that typecasting might possibly render your index on that column unusable and has a performance penalty, which is pretty bad. An even better solution would be to see if you can permanently change one of the two column types to match the other one. Literately change your database design.

Or you could create a index on the casted values by using a custom, immutable function which casts the values on the column. But this too may prove suboptimal (but better than live casting).

The error org.postgresql.util.PSQLException: ERROR: operator does not exist: my_enum_type = character varying can be fixed by using implicit conversions in PostgreSQL or using explicit conversions by passing the java.sql.Types.OTHER to Spring JDBC.

The exception you will receive

When using Spring JDBC or Spring Data JDBC and custom Java enum types, you might run into the following problem:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT * FROM your_table where enum_column = :enum_value;] nested exception is org.postgresql.util.PSQLException: ERROR: operator does not exist: my_enum_type = character varying

Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.

The exception can occur if you are having enums with either

  1. or you are trying to persist an Spring Data JDBC entity with a repository save method
  2. executing a query on your own with one of Spring JDBC’s jdbcTemplate methods like query

Making Spring Data JDBC’s save method work with enumerations

With Spring Data JDBC you have probably an SQL definition like

CREATE TYPE my_enum_type AS ENUM('VALUE_1','VALUE_2')

CREATE TABLE my_table (enum_column my_enum_type);

The belonging Java source code will look like

public enum MyEnumType {
	VALUE_1, VALUE_2
}

@Table("my_table")
public class MyEntity {
	private MyEnumType type;
	// getter & setter ...
}

@Repository
public class MyTableRepository extends CrudRepository</* ... */> {
}

@Controller
public class MyTableController {
	@Autowired
	MyTableRepository
    
	@GetMapping("/")
	public void save() {
		MyEntity entity = new MyEntity();
		entity.setType(MyEnumType.VALUE_1);
		repository.save(entity);
	}
}

As soon as you try to call repository.save you will receive an exception. The problem is, that Spring Data JDBC does not support enumerations at the moment. See Jens Schauder’s answer at stackoverflow.

Jens does also link to another SO answer which describes how to solve the problem. To make the code sample above working, we can use PostgreSQL’s implicit conversion feature as described in the linked answer. The following SQL definition would reside somewhere in your Liquibase or Flyway migration definition:

<!-- Liquibase migration definition -->
<!-- as described above -->
<sql>CREATE TYPE my_enum_type AS ENUM('VALUE_1','VALUE_2')</sql>

<!-- add an additional type -->
<sql>CREATE CAST (varchar AS my_enum_type) WITH INOUT AS IMPLICIT</sql>

With help of the described CREATE CAST PostgreSQL will automatically try convert each String/varchar into the specified enum. You can now do something like

SELECT * FROM my_table WHERE enum_column = 'VALUE_1';
-- OR
INSERT INTO my_table(enum_column) VALUES('VALUE_1')

After that, repository.save() will work.

Using JdbcTemplate and enumerations

You might think that the specified CREATE CAST definition would also work for something like that:

public class MyRepository {
	@Autowired
    NamedParameterJdbcTemplate jdbcTemplate;

	public List<String> findAll() {
		MapSqlParameterSource parameters = new MapSqlParameterSource("type", MyEnumType.VALUE_1);
		
		return jdbcTemplate
			.queryForList("SELECT enum_column FROM my_table WHERE enum_column = :type", parameters);
	}
}

But this will drive you right into the exception you find at the beginning:

org.postgresql.util.PSQLException: ERROR: operator does not exist: my_enum_type = character varying

The reason for this behavior is how PostgreSQL handles the type casts. This Stackoverflow answer describes the reasons in detail. Spring JDBC does automatically convert the enum value into a Java String type and assigns it to the prepared statement. The underlying PgJDBC drivers then assigns the java.sql.Type.VARCHAR as type for this prepared statement parameter. Due to the assignment of the java.sql.Type, PostgreSQL will no longer try to apply our CREATE CAST conversion.

Solving it by configuration

You can configure your JDBC URL to use the parameter stringtype with value undefined. Each String parameter previously set with setString() will then not have the type definition java.sql.Type.VARCHAR. PostgreSQL applies will then apply our CREATE CAST definition.

Solving it programatically

If you don’t globally want to set stringtype to undefined, you have to use the java.sql.Types.OTHER when adding a value to the MapSqlParameterSource:

// does NOT WORK: 
// .addValue("type", MyEnumType.VALUE_1))
// one of the following does work:
.addValue("type", "VALUE_1", java.sql.Types.OTHER)
// or
.addValue("type", MyEnumType.VALUE_1.getName(), java.sql.Types.OTHER)
// or
.addValue("type", MyEnumType.VALUE_1, java.sql.Types.OTHER)

To make it more convenient, you can extend from MapSqlParameterSource to get something like this:

public static class CustomMapSqlParameterSource extends MapSqlParameterSource {
	public CustomMapSqlParameterSource addEnum(String paramName, Object value) {
		if (!value.getClass().isEnum()) {
			throw new IllegalArgumentException("Given parameter is not of Java type enum");
		}

		addValue(paramName, value, java.sql.Types.OTHER);

		return this;
	}
}

Wrapping it up

This blog post showed you, how you can use native PostgreSQL enumerations with native Java and make them both work with Spring Data JDBC and Spring JDBC.

Возможно, вам также будет интересно:

  • Ore варочная панель ошибка el
  • Ordinal not in range 128 ошибка
  • Ordersend error 4107 таблица ошибок
  • Ordersend error 131 ошибка
  • Orderselect вернул ошибку 4051

  • Понравилась статья? Поделить с друзьями:
    0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии