Details
-
Bug
-
Resolution: Done
-
Major
-
3.44.0, 3.45.0
-
1
-
NXRM Sentinels Sprint 50
-
maintenance
-
non-concept
-
2
Description
During the upgrade process to 3.45.0, various DB schema changes are performed, one of which is failing for the schema for SearchTableDAO
This appears to be due to a new dependency on a pg_trgm module
No indication of this new dependency is present in the release notes.
The nexus.log may contain a message like this:
2022-12-28 12:03:49,020-0500 INFO [FelixStartLevel] *SYSTEM org.sonatype.nexus.datastore.mybatis.MyBatisDataStore - nexus - Creating schema for SearchTableDAO 2022-12-28 12:03:49,064-0500 WARN [FelixStartLevel] *SYSTEM Sisu - Problem adding: org.eclipse.sisu.inject.LazyBeanEntry@2c00368 to: org.sonatype.nexus.datastore.mybatis.MyBatisDataStore$$EnhancerByGuice$$366511306@400e761a via: org.sonatype.nexus.datastore.internal.DataStoreManagerImpl$DataAccessMediator@4debec0a org.sonatype.nexus.datastore.api.DataAccessException: ### Error updating database. Cause: org.postgresql.util.PSQLException: ERROR: could not open extension control file "/usr/share/pgsql/extension/pg_trgm.control": No such file or directory Where: SQL statement "CREATE EXTENSION IF NOT EXISTS pg_trgm" PL/pgSQL function enable_pg_trgm() line 10 at SQL statement ### The error may exist in org/sonatype/nexus/repository/content/search/table/SearchTableDAO.xml ### The error may involve defaultParameterMap ### The error occurred while setting parameters ### SQL: CREATE TABLE IF NOT EXISTS search_components ( repository_id INTEGER NOT NULL, component_id INTEGER NOT NULL, format VARCHAR NOT NULL, namespace VARCHAR NOT NULL, search_component_name VARCHAR NOT NULL, component_kind VARCHAR NOT NULL, version VARCHAR NOT NULL, component_created TIMESTAMP WITH TIME ZONE NOT NULL, search_repository_name VARCHAR(200) NOT NULL, normalised_version VARCHAR NOT NULL, prerelease BOOLEAN NOT NULL DEFAULT false, keywords TSVECTOR, md5 TSVECTOR, sha1 TSVECTOR, sha256 TSVECTOR, sha512 TSVECTOR, format_field_values_1 TSVECTOR, format_field_values_2 TSVECTOR, format_field_values_3 TSVECTOR, format_field_values_4 TSVECTOR, format_field_values_5 TSVECTOR, uploaders TSVECTOR, uploader_ips TSVECTOR, paths VARCHAR, tsvector_paths TSVECTOR, tsvector_format TSVECTOR NOT NULL, tsvector_namespace TSVECTOR NOT NULL, tsvector_search_component_name TSVECTOR NOT NULL, tsvector_version TSVECTOR NOT NULL, tsvector_search_repository_name TSVECTOR NOT NULL, last_event_time TIMESTAMP WITH TIME ZONE, CONSTRAINT pk_search_components PRIMARY KEY (repository_id, component_id, format) ); CREATE INDEX IF NOT EXISTS idx_search_components_normalised_version ON search_components (normalised_version); CREATE INDEX IF NOT EXISTS idx_search_components_namespace ON search_components (namespace); CREATE INDEX IF NOT EXISTS idx_search_components_component_name ON search_components (search_component_name); CREATE INDEX IF NOT EXISTS idx_search_components_format ON search_components (format); CREATE INDEX IF NOT EXISTS idx_search_components_repository_name ON search_components (search_repository_name); CREATE INDEX IF NOT EXISTS idx_search_components_prerelease ON search_components (prerelease); CREATE INDEX IF NOT EXISTS idx_search_components_keywords ON search_components USING GIN (keywords); CREATE INDEX IF NOT EXISTS idx_search_components_md5 ON search_components USING GIN (md5); CREATE INDEX IF NOT EXISTS idx_search_components_sha1 ON search_components USING GIN (sha1); CREATE INDEX IF NOT EXISTS idx_search_components_sha256 ON search_components USING GIN (sha256); CREATE INDEX IF NOT EXISTS idx_search_components_sha512 ON search_components USING GIN (sha512); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_1 ON search_components USING GIN (format_field_values_1); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_2 ON search_components USING GIN (format_field_values_2); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_3 ON search_components USING GIN (format_field_values_3); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_4 ON search_components USING GIN (format_field_values_4); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_5 ON search_components USING GIN (format_field_values_5); CREATE INDEX IF NOT EXISTS idx_search_components_format_uploaders ON search_components USING GIN (uploaders); CREATE INDEX IF NOT EXISTS idx_search_components_format_uploader_ips ON search_components USING GIN (uploader_ips); CREATE INDEX IF NOT EXISTS idx_search_components_paths ON search_components (paths); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_paths ON search_components USING GIN (tsvector_paths); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_format ON search_components USING GIN (tsvector_format); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_namespace ON search_components USING GIN (tsvector_namespace); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_search_component_name ON search_components USING GIN (tsvector_search_component_name); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_version ON search_components USING GIN (tsvector_version); CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_search_repository_name ON search_components USING GIN (tsvector_search_repository_name); ALTER TABLE search_components DROP COLUMN IF EXISTS last_event_time; ALTER TABLE search_components ADD COLUMN IF NOT EXISTS entity_version INT; CREATE INDEX IF NOT EXISTS idx_search_components_entity_version ON search_components (entity_version); ALTER TABLE search_components ADD COLUMN IF NOT EXISTS tsvector_tags TSVECTOR; CREATE INDEX IF NOT EXISTS idx_search_components_tsvector_tags ON search_components USING GIN (tsvector_tags); --These columns hold untokenised versions of other searchable (i.e. tokenised) data. -- No index on them because they are not searched (i.e. not searchable) ALTER TABLE search_components ADD COLUMN IF NOT EXISTS attributes JSONB; ALTER TABLE search_components ADD COLUMN IF NOT EXISTS tags JSONB; ALTER TABLE search_components ADD COLUMN IF NOT EXISTS format_field_values_6 TSVECTOR; ALTER TABLE search_components ADD COLUMN IF NOT EXISTS format_field_values_7 TSVECTOR; CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_6 ON search_components USING GIN (format_field_values_6); CREATE INDEX IF NOT EXISTS idx_search_components_format_field_values_7 ON search_components USING GIN (format_field_values_7); CREATE OR REPLACE FUNCTION enable_pg_trgm() RETURNS VOID AS $$ DECLARE version_number INTEGER; db_version VARCHAR; BEGIN SELECT LOWER(version()) INTO db_version; IF db_version ~ '^postgresql \d\d' THEN SELECT SUBSTRING(db_version, CHAR_LENGTH('postgresql') + 2, 2) INTO version_number; IF version_number >= 13 THEN CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX IF NOT EXISTS trgm_idx_search_components_paths ON search_components USING GIST (paths gist_trgm_ops); END IF; END IF; END; $$ LANGUAGE plpgsql; SELECT enable_pg_trgm(); ### Cause: org.postgresql.util.PSQLException: ERROR: could not open extension control file "/usr/share/pgsql/extension/pg_trgm.control": No such file or directory Where: SQL statement "CREATE EXTENSION IF NOT EXISTS pg_trgm" PL/pgSQL function enable_pg_trgm() line 10 at SQL statement at org.sonatype.nexus.datastore.mybatis.DataAccessSqlSession.unwrapMyBatisException(DataAccessSqlSession.java:125) at org.sonatype.nexus.datastore.mybatis.DataAccessSqlSession.update(DataAccessSqlSession.java:86) at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181) at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62) at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145) at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) at com.sun.proxy.$Proxy202.createSchema(Unknown Source) at org.sonatype.nexus.datastore.mybatis.MyBatisDataStore.register(MyBatisDataStore.java:260) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl$DataAccessMediator.add(DataStoreManagerImpl.java:368) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl$DataAccessMediator.add(DataStoreManagerImpl.java:1) at org.eclipse.sisu.inject.WatchedBeans.add(WatchedBeans.java:80) at org.eclipse.sisu.inject.InjectorBindings.publishExactMatches(InjectorBindings.java:157) at org.eclipse.sisu.inject.InjectorBindings.subscribe(InjectorBindings.java:79) at org.eclipse.sisu.inject.DefaultBeanLocator.watch(DefaultBeanLocator.java:80) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl.doCreate(DataStoreManagerImpl.java:197) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl.tryRestore(DataStoreManagerImpl.java:175) at com.google.common.collect.ImmutableList.forEach(ImmutableList.java:406) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl.doStart(DataStoreManagerImpl.java:124) at org.sonatype.nexus.common.stateguard.StateGuardLifecycleSupport.start(StateGuardLifecycleSupport.java:69) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl$$EnhancerByGuice$$141081007.GUICE$TRAMPOLINE(<generated>) at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:74) at org.sonatype.nexus.common.stateguard.MethodInvocationAction.run(MethodInvocationAction.java:39) at org.sonatype.nexus.common.stateguard.StateGuard$TransitionImpl.run(StateGuard.java:193) at org.sonatype.nexus.common.stateguard.TransitionsInterceptor.invoke(TransitionsInterceptor.java:57) at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:75) at com.google.inject.internal.InterceptorStackCallback.invoke(InterceptorStackCallback.java:55) at org.sonatype.nexus.datastore.internal.DataStoreManagerImpl$$EnhancerByGuice$$141081007.start(<generated>) at org.sonatype.nexus.extender.NexusLifecycleManager.startComponent(NexusLifecycleManager.java:199) at org.sonatype.nexus.extender.NexusLifecycleManager.to(NexusLifecycleManager.java:111) at org.sonatype.nexus.extender.NexusContextListener.moveToPhase(NexusContextListener.java:319) at org.sonatype.nexus.extender.NexusContextListener.frameworkEvent(NexusContextListener.java:216) at org.apache.felix.framework.Felix.setActiveStartLevel(Felix.java:1597) at org.apache.felix.framework.FrameworkStartLevelImpl.run(FrameworkStartLevelImpl.java:308) at java.lang.Thread.run(Thread.java:748)
Impact
Startup and upgrade DOES NOT FAIL. Whether there is some other impact like certain database queries not returning expected results still needs investigation.
Expected
Given that the use of this module is unavoidable, this new dependency should be prominently documented to ensure the module is added to the Postgres instance before performing the upgrade.
If installing this modules is optional, simply log a WARN message when it can't be installed, instead of a concerning stack trace.
Workaround
Install the postgresql-contrib package in your linux distribution system. This will work for RHEL 7 and higher based systems, Fedora, and recent debian/ubuntu systems. Other distributions may provide this extension via a different package.