diff --git a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json index 9dc202a5..b237103d 100644 --- a/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json +++ b/.github/upgrades/scenarios/new-dotnet-version_02bc64/scenario.json @@ -3,7 +3,7 @@ "operationId": "02bc6448-a69d-4ff4-a0ec-0db07ec3a09a", "description": "Upgrade solution or project to new version of .NET", "startTime": "2026-03-05T22:18:32.3921759Z", - "lastUpdateTime": "2026-03-07T18:05:10.0632722Z", + "lastUpdateTime": "2026-03-07T18:26:16.052623Z", "stage": "Execution", "properties": {}, "folderPath": "" diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 9a9d0192..3317cd70 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -117,12 +117,13 @@ - + - + - - + + + diff --git a/Jellyfin.Server/sql/schema_init/create_database_schema.sql b/Jellyfin.Server/sql/schema_init/create_database_schema.sql new file mode 100644 index 00000000..13126685 --- /dev/null +++ b/Jellyfin.Server/sql/schema_init/create_database_schema.sql @@ -0,0 +1,1876 @@ +-- +-- PostgreSQL database dump +-- + +\restrict BQanTgDKfPEe1ad123fH2eOQKfeiGuQ1HWaeH3TgqI0dLTNNmavSsSEklw1qhxQ + +-- Dumped from database version 18.3 +-- Dumped by pg_dump version 18.3 + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET transaction_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: activitylog; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA activitylog; + + +ALTER SCHEMA activitylog OWNER TO jellyfin; + +-- +-- Name: authentication; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA authentication; + + +ALTER SCHEMA authentication OWNER TO jellyfin; + +-- +-- Name: displaypreferences; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA displaypreferences; + + +ALTER SCHEMA displaypreferences OWNER TO jellyfin; + +-- +-- Name: library; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA library; + + +ALTER SCHEMA library OWNER TO jellyfin; + +-- +-- Name: users; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA users; + + +ALTER SCHEMA users OWNER TO jellyfin; + +-- +-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed'; + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: ActivityLogs; Type: TABLE; Schema: activitylog; Owner: jellyfin +-- + +CREATE TABLE activitylog."ActivityLogs" ( + "Id" integer NOT NULL, + "Name" character varying(512) NOT NULL, + "Overview" character varying(512), + "ShortOverview" character varying(512), + "Type" character varying(256) NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" character varying(256), + "DateCreated" timestamp with time zone NOT NULL, + "LogSeverity" integer NOT NULL, + "RowVersion" bigint NOT NULL +); + + +ALTER TABLE activitylog."ActivityLogs" OWNER TO jellyfin; + +-- +-- Name: ActivityLogs_Id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME activitylog."ActivityLogs_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ApiKeys; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."ApiKeys" ( + "Id" integer NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL, + "Name" character varying(64) NOT NULL, + "AccessToken" text NOT NULL +); + + +ALTER TABLE authentication."ApiKeys" OWNER TO jellyfin; + +-- +-- Name: ApiKeys_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."ApiKeys_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: DeviceOptions; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."DeviceOptions" ( + "Id" integer NOT NULL, + "DeviceId" text NOT NULL, + "CustomName" text +); + + +ALTER TABLE authentication."DeviceOptions" OWNER TO jellyfin; + +-- +-- Name: DeviceOptions_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."DeviceOptions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Devices; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."Devices" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "AccessToken" text NOT NULL, + "AppName" character varying(64) NOT NULL, + "AppVersion" character varying(32) NOT NULL, + "DeviceName" character varying(64) NOT NULL, + "DeviceId" character varying(256) NOT NULL, + "IsActive" boolean NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateModified" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL +); + + +ALTER TABLE authentication."Devices" OWNER TO jellyfin; + +-- +-- Name: Devices_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."Devices_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: CustomItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."CustomItemDisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "Key" text NOT NULL, + "Value" text +); + + +ALTER TABLE displaypreferences."CustomItemDisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: CustomItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."CustomItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: DisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."DisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "ShowSidebar" boolean NOT NULL, + "ShowBackdrop" boolean NOT NULL, + "ScrollDirection" integer NOT NULL, + "IndexBy" integer, + "SkipForwardLength" integer NOT NULL, + "SkipBackwardLength" integer NOT NULL, + "ChromecastVersion" integer NOT NULL, + "EnableNextVideoInfoOverlay" boolean NOT NULL, + "DashboardTheme" character varying(32), + "TvHome" character varying(32) +); + + +ALTER TABLE displaypreferences."DisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: DisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."DisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: HomeSection; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."HomeSection" ( + "Id" integer NOT NULL, + "DisplayPreferencesId" integer NOT NULL, + "Order" integer NOT NULL, + "Type" integer NOT NULL +); + + +ALTER TABLE displaypreferences."HomeSection" OWNER TO jellyfin; + +-- +-- Name: HomeSection_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."HomeSection_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."ItemDisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "ViewType" integer NOT NULL, + "RememberIndexing" boolean NOT NULL, + "IndexBy" integer, + "RememberSorting" boolean NOT NULL, + "SortBy" character varying(64) NOT NULL, + "SortOrder" integer NOT NULL +); + + +ALTER TABLE displaypreferences."ItemDisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: ItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."ItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: AncestorIds; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."AncestorIds" ( + "ParentItemId" uuid NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."AncestorIds" OWNER TO jellyfin; + +-- +-- Name: AttachmentStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."AttachmentStreamInfos" ( + "ItemId" uuid NOT NULL, + "Index" integer NOT NULL, + "Codec" text, + "CodecTag" text, + "Comment" text, + "Filename" text, + "MimeType" text +); + + +ALTER TABLE library."AttachmentStreamInfos" OWNER TO jellyfin; + +-- +-- Name: BaseItemImageInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemImageInfos" ( + "Id" uuid NOT NULL, + "Path" text NOT NULL, + "DateModified" timestamp with time zone, + "ImageType" integer NOT NULL, + "Width" integer NOT NULL, + "Height" integer NOT NULL, + "Blurhash" bytea, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemImageInfos" OWNER TO jellyfin; + +-- +-- Name: BaseItemMetadataFields; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemMetadataFields" ( + "Id" integer NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemMetadataFields" OWNER TO jellyfin; + +-- +-- Name: BaseItemProviders; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemProviders" ( + "ItemId" uuid NOT NULL, + "ProviderId" text NOT NULL, + "ProviderValue" text NOT NULL +); + + +ALTER TABLE library."BaseItemProviders" OWNER TO jellyfin; + +-- +-- Name: BaseItemTrailerTypes; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemTrailerTypes" ( + "Id" integer NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemTrailerTypes" OWNER TO jellyfin; + +-- +-- Name: BaseItems; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItems" ( + "Id" uuid NOT NULL, + "Type" text NOT NULL, + "Data" text, + "Path" text, + "StartDate" timestamp with time zone, + "EndDate" timestamp with time zone, + "ChannelId" uuid, + "IsMovie" boolean NOT NULL, + "CommunityRating" real, + "CustomRating" text, + "IndexNumber" integer, + "IsLocked" boolean NOT NULL, + "Name" text, + "OfficialRating" text, + "MediaType" text, + "Overview" text, + "ParentIndexNumber" integer, + "PremiereDate" timestamp with time zone, + "ProductionYear" integer, + "Genres" text, + "SortName" text, + "ForcedSortName" text, + "RunTimeTicks" bigint, + "DateCreated" timestamp with time zone, + "DateModified" timestamp with time zone, + "IsSeries" boolean NOT NULL, + "EpisodeTitle" text, + "IsRepeat" boolean NOT NULL, + "PreferredMetadataLanguage" text, + "PreferredMetadataCountryCode" text, + "DateLastRefreshed" timestamp with time zone, + "DateLastSaved" timestamp with time zone, + "IsInMixedFolder" boolean NOT NULL, + "Studios" text, + "ExternalServiceId" text, + "Tags" text, + "IsFolder" boolean NOT NULL, + "InheritedParentalRatingValue" integer, + "InheritedParentalRatingSubValue" integer, + "UnratedType" text, + "CriticRating" real, + "CleanName" text, + "PresentationUniqueKey" text, + "OriginalTitle" text, + "PrimaryVersionId" text, + "DateLastMediaAdded" timestamp with time zone, + "Album" text, + "LUFS" real, + "NormalizationGain" real, + "IsVirtualItem" boolean NOT NULL, + "SeriesName" text, + "SeasonName" text, + "ExternalSeriesId" text, + "Tagline" text, + "ProductionLocations" text, + "ExtraIds" text, + "TotalBitrate" integer, + "ExtraType" integer, + "Artists" text, + "AlbumArtists" text, + "ExternalId" text, + "SeriesPresentationUniqueKey" text, + "ShowId" text, + "OwnerId" text, + "Width" integer, + "Height" integer, + "Size" bigint, + "Audio" integer, + "ParentId" uuid, + "TopParentId" uuid, + "SeasonId" uuid, + "SeriesId" uuid +); + + +ALTER TABLE library."BaseItems" OWNER TO jellyfin; + +-- +-- Name: Chapters; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."Chapters" ( + "ItemId" uuid NOT NULL, + "ChapterIndex" integer NOT NULL, + "StartPositionTicks" bigint NOT NULL, + "Name" text, + "ImagePath" text, + "ImageDateModified" timestamp with time zone +); + + +ALTER TABLE library."Chapters" OWNER TO jellyfin; + +-- +-- Name: ImageInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ImageInfos" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Path" character varying(512) NOT NULL, + "LastModified" timestamp with time zone NOT NULL +); + + +ALTER TABLE library."ImageInfos" OWNER TO jellyfin; + +-- +-- Name: ImageInfos_Id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin +-- + +ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME library."ImageInfos_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ItemValues; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ItemValues" ( + "ItemValueId" uuid NOT NULL, + "Type" integer NOT NULL, + "Value" text NOT NULL, + "CleanValue" text NOT NULL +); + + +ALTER TABLE library."ItemValues" OWNER TO jellyfin; + +-- +-- Name: ItemValuesMap; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ItemValuesMap" ( + "ItemId" uuid NOT NULL, + "ItemValueId" uuid NOT NULL +); + + +ALTER TABLE library."ItemValuesMap" OWNER TO jellyfin; + +-- +-- Name: KeyframeData; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."KeyframeData" ( + "ItemId" uuid NOT NULL, + "TotalDuration" bigint NOT NULL, + "KeyframeTicks" bigint[] +); + + +ALTER TABLE library."KeyframeData" OWNER TO jellyfin; + +-- +-- Name: MediaSegments; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."MediaSegments" ( + "Id" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Type" integer NOT NULL, + "EndTicks" bigint NOT NULL, + "StartTicks" bigint NOT NULL, + "SegmentProviderId" text NOT NULL +); + + +ALTER TABLE library."MediaSegments" OWNER TO jellyfin; + +-- +-- Name: MediaStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."MediaStreamInfos" ( + "ItemId" uuid NOT NULL, + "StreamIndex" integer NOT NULL, + "StreamType" integer NOT NULL, + "Codec" text, + "Language" text, + "ChannelLayout" text, + "Profile" text, + "AspectRatio" text, + "Path" text, + "IsInterlaced" boolean, + "BitRate" integer, + "Channels" integer, + "SampleRate" integer, + "IsDefault" boolean NOT NULL, + "IsForced" boolean NOT NULL, + "IsExternal" boolean NOT NULL, + "Height" integer, + "Width" integer, + "AverageFrameRate" real, + "RealFrameRate" real, + "Level" real, + "PixelFormat" text, + "BitDepth" integer, + "IsAnamorphic" boolean, + "RefFrames" integer, + "CodecTag" text, + "Comment" text, + "NalLengthSize" text, + "IsAvc" boolean, + "Title" text, + "TimeBase" text, + "CodecTimeBase" text, + "ColorPrimaries" text, + "ColorSpace" text, + "ColorTransfer" text, + "DvVersionMajor" integer, + "DvVersionMinor" integer, + "DvProfile" integer, + "DvLevel" integer, + "RpuPresentFlag" integer, + "ElPresentFlag" integer, + "BlPresentFlag" integer, + "DvBlSignalCompatibilityId" integer, + "IsHearingImpaired" boolean, + "Rotation" integer, + "KeyFrames" text, + "Hdr10PlusPresentFlag" boolean +); + + +ALTER TABLE library."MediaStreamInfos" OWNER TO jellyfin; + +-- +-- Name: PeopleBaseItemMap; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."PeopleBaseItemMap" ( + "Role" text NOT NULL, + "ItemId" uuid NOT NULL, + "PeopleId" uuid NOT NULL, + "SortOrder" integer, + "ListOrder" integer +); + + +ALTER TABLE library."PeopleBaseItemMap" OWNER TO jellyfin; + +-- +-- Name: Peoples; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."Peoples" ( + "Id" uuid NOT NULL, + "Name" text NOT NULL, + "PersonType" text +); + + +ALTER TABLE library."Peoples" OWNER TO jellyfin; + +-- +-- Name: TrickplayInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."TrickplayInfos" ( + "ItemId" uuid NOT NULL, + "Width" integer NOT NULL, + "Height" integer NOT NULL, + "TileWidth" integer NOT NULL, + "TileHeight" integer NOT NULL, + "ThumbnailCount" integer NOT NULL, + "Interval" integer NOT NULL, + "Bandwidth" integer NOT NULL +); + + +ALTER TABLE library."TrickplayInfos" OWNER TO jellyfin; + +-- +-- Name: UserData; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."UserData" ( + "CustomDataKey" text NOT NULL, + "ItemId" uuid NOT NULL, + "UserId" uuid NOT NULL, + "Rating" double precision, + "PlaybackPositionTicks" bigint NOT NULL, + "PlayCount" integer NOT NULL, + "IsFavorite" boolean NOT NULL, + "LastPlayedDate" timestamp with time zone, + "Played" boolean NOT NULL, + "AudioStreamIndex" integer, + "SubtitleStreamIndex" integer, + "Likes" boolean, + "RetentionDate" timestamp with time zone +); + + +ALTER TABLE library."UserData" OWNER TO jellyfin; + +-- +-- Name: __EFMigrationsHistory; Type: TABLE; Schema: public; Owner: jellyfin +-- + +CREATE TABLE public."__EFMigrationsHistory" ( + "MigrationId" character varying(150) NOT NULL, + "ProductVersion" character varying(32) NOT NULL +); + + +ALTER TABLE public."__EFMigrationsHistory" OWNER TO jellyfin; + +-- +-- Name: bloat_tables; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.bloat_tables ( + count bigint +); + + +ALTER TABLE public.bloat_tables OWNER TO postgres; + +-- +-- Name: AccessSchedules; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."AccessSchedules" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "DayOfWeek" integer NOT NULL, + "StartHour" double precision NOT NULL, + "EndHour" double precision NOT NULL +); + + +ALTER TABLE users."AccessSchedules" OWNER TO jellyfin; + +-- +-- Name: AccessSchedules_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."AccessSchedules_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Permissions; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Permissions" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Kind" integer NOT NULL, + "Value" boolean NOT NULL, + "RowVersion" bigint NOT NULL, + "Permission_Permissions_Guid" uuid +); + + +ALTER TABLE users."Permissions" OWNER TO jellyfin; + +-- +-- Name: Permissions_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Permissions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Preferences; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Preferences" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Kind" integer NOT NULL, + "Value" character varying(65535) NOT NULL, + "RowVersion" bigint NOT NULL, + "Preference_Preferences_Guid" uuid +); + + +ALTER TABLE users."Preferences" OWNER TO jellyfin; + +-- +-- Name: Preferences_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Preferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Users; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Users" ( + "Id" uuid NOT NULL, + "Username" character varying(255) NOT NULL, + "Password" character varying(65535), + "MustUpdatePassword" boolean NOT NULL, + "AudioLanguagePreference" character varying(255), + "AuthenticationProviderId" character varying(255) NOT NULL, + "PasswordResetProviderId" character varying(255) NOT NULL, + "InvalidLoginAttemptCount" integer NOT NULL, + "LastActivityDate" timestamp with time zone, + "LastLoginDate" timestamp with time zone, + "LoginAttemptsBeforeLockout" integer, + "MaxActiveSessions" integer NOT NULL, + "SubtitleMode" integer NOT NULL, + "PlayDefaultAudioTrack" boolean NOT NULL, + "SubtitleLanguagePreference" character varying(255), + "DisplayMissingEpisodes" boolean NOT NULL, + "DisplayCollectionsView" boolean NOT NULL, + "EnableLocalPassword" boolean NOT NULL, + "HidePlayedInLatest" boolean NOT NULL, + "RememberAudioSelections" boolean NOT NULL, + "RememberSubtitleSelections" boolean NOT NULL, + "EnableNextEpisodeAutoPlay" boolean NOT NULL, + "EnableAutoLogin" boolean NOT NULL, + "EnableUserPreferenceAccess" boolean NOT NULL, + "MaxParentalRatingScore" integer, + "MaxParentalRatingSubScore" integer, + "RemoteClientBitrateLimit" integer, + "InternalId" bigint NOT NULL, + "SyncPlayAccess" integer NOT NULL, + "CastReceiverId" character varying(32), + "RowVersion" bigint NOT NULL +); + + +ALTER TABLE users."Users" OWNER TO jellyfin; + +-- +-- Name: ActivityLogs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE ONLY activitylog."ActivityLogs" + ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY ("Id"); + + +-- +-- Name: ApiKeys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."ApiKeys" + ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY ("Id"); + + +-- +-- Name: DeviceOptions PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."DeviceOptions" + ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY ("Id"); + + +-- +-- Name: Devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."Devices" + ADD CONSTRAINT "PK_Devices" PRIMARY KEY ("Id"); + + +-- +-- Name: CustomItemDisplayPreferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."CustomItemDisplayPreferences" + ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: DisplayPreferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."DisplayPreferences" + ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: HomeSection PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."HomeSection" + ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY ("Id"); + + +-- +-- Name: ItemDisplayPreferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" + ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: AncestorIds PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY ("ItemId", "ParentItemId"); + + +-- +-- Name: AttachmentStreamInfos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AttachmentStreamInfos" + ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY ("ItemId", "Index"); + + +-- +-- Name: BaseItemImageInfos PK_BaseItemImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemImageInfos" + ADD CONSTRAINT "PK_BaseItemImageInfos" PRIMARY KEY ("Id"); + + +-- +-- Name: BaseItemMetadataFields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemMetadataFields" + ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY ("Id", "ItemId"); + + +-- +-- Name: BaseItemProviders PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemProviders" + ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY ("ItemId", "ProviderId"); + + +-- +-- Name: BaseItemTrailerTypes PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemTrailerTypes" + ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY ("Id", "ItemId"); + + +-- +-- Name: BaseItems PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItems" + ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY ("Id"); + + +-- +-- Name: Chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Chapters" + ADD CONSTRAINT "PK_Chapters" PRIMARY KEY ("ItemId", "ChapterIndex"); + + +-- +-- Name: ImageInfos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ImageInfos" + ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY ("Id"); + + +-- +-- Name: ItemValues PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValues" + ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY ("ItemValueId"); + + +-- +-- Name: ItemValuesMap PK_ItemValuesMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "PK_ItemValuesMap" PRIMARY KEY ("ItemValueId", "ItemId"); + + +-- +-- Name: KeyframeData PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."KeyframeData" + ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY ("ItemId"); + + +-- +-- Name: MediaSegments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaSegments" + ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY ("Id"); + + +-- +-- Name: MediaStreamInfos PK_MediaStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaStreamInfos" + ADD CONSTRAINT "PK_MediaStreamInfos" PRIMARY KEY ("ItemId", "StreamIndex"); + + +-- +-- Name: PeopleBaseItemMap PK_PeopleBaseItemMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "PK_PeopleBaseItemMap" PRIMARY KEY ("ItemId", "PeopleId", "Role"); + + +-- +-- Name: Peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Peoples" + ADD CONSTRAINT "PK_Peoples" PRIMARY KEY ("Id"); + + +-- +-- Name: TrickplayInfos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."TrickplayInfos" + ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY ("ItemId", "Width"); + + +-- +-- Name: UserData PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "PK_UserData" PRIMARY KEY ("ItemId", "UserId", "CustomDataKey"); + + +-- +-- Name: __EFMigrationsHistory PK___EFMigrationsHistory; Type: CONSTRAINT; Schema: public; Owner: jellyfin +-- + +ALTER TABLE ONLY public."__EFMigrationsHistory" + ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"); + + +-- +-- Name: AccessSchedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."AccessSchedules" + ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY ("Id"); + + +-- +-- Name: Permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Permissions" + ADD CONSTRAINT "PK_Permissions" PRIMARY KEY ("Id"); + + +-- +-- Name: Preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Preferences" + ADD CONSTRAINT "PK_Preferences" PRIMARY KEY ("Id"); + + +-- +-- Name: Users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Users" + ADD CONSTRAINT "PK_Users" PRIMARY KEY ("Id"); + + +-- +-- Name: IX_ActivityLogs_DateCreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog."ActivityLogs" USING btree ("DateCreated"); + + +-- +-- Name: idx_activitylogs_userid_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog."ActivityLogs" USING btree ("UserId", "DateCreated" DESC) WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_ApiKeys_AccessToken; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication."ApiKeys" USING btree ("AccessToken"); + + +-- +-- Name: IX_DeviceOptions_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication."DeviceOptions" USING btree ("DeviceId"); + + +-- +-- Name: IX_Devices_AccessToken_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication."Devices" USING btree ("AccessToken", "DateLastActivity"); + + +-- +-- Name: IX_Devices_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId" ON authentication."Devices" USING btree ("DeviceId"); + + +-- +-- Name: IX_Devices_DeviceId_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication."Devices" USING btree ("DeviceId", "DateLastActivity"); + + +-- +-- Name: IX_Devices_UserId_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication."Devices" USING btree ("UserId", "DeviceId"); + + +-- +-- Name: IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences."CustomItemDisplayPreferences" USING btree ("UserId", "ItemId", "Client", "Key"); + + +-- +-- Name: IX_DisplayPreferences_UserId_ItemId_Client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences."DisplayPreferences" USING btree ("UserId", "ItemId", "Client"); + + +-- +-- Name: IX_HomeSection_DisplayPreferencesId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences."HomeSection" USING btree ("DisplayPreferencesId"); + + +-- +-- Name: IX_ItemDisplayPreferences_UserId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences."ItemDisplayPreferences" USING btree ("UserId"); + + +-- +-- Name: IX_AncestorIds_ParentItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_AncestorIds_ParentItemId" ON library."AncestorIds" USING btree ("ParentItemId"); + + +-- +-- Name: IX_BaseItemImageInfos_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library."BaseItemImageInfos" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItemMetadataFields_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library."BaseItemMetadataFields" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItemProviders_ProviderId_ProviderValue_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId" ON library."BaseItemProviders" USING btree ("ProviderId", "ProviderValue", "ItemId"); + + +-- +-- Name: IX_BaseItemTrailerTypes_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library."BaseItemTrailerTypes" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItems_Id_Type_IsFolder_IsVirtualItem; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library."BaseItems" USING btree ("Id", "Type", "IsFolder", "IsVirtualItem"); + + +-- +-- Name: IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~" ON library."BaseItems" USING btree ("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); + + +-- +-- Name: IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~" ON library."BaseItems" USING btree ("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_ParentId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_ParentId" ON library."BaseItems" USING btree ("ParentId"); + + +-- +-- Name: IX_BaseItems_Path; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Path" ON library."BaseItems" USING btree ("Path"); + + +-- +-- Name: IX_BaseItems_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_PresentationUniqueKey" ON library."BaseItems" USING btree ("PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_TopParentId_Id" ON library."BaseItems" USING btree ("TopParentId", "Id"); + + +-- +-- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); + + +-- +-- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library."BaseItems" USING btree ("Type", "TopParentId", "Id"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~" ON library."BaseItems" USING btree ("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_PresentationUniqueKey" ON library."BaseItems" USING btree ("Type", "TopParentId", "PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_StartDate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_StartDate" ON library."BaseItems" USING btree ("Type", "TopParentId", "StartDate"); + + +-- +-- Name: IX_ImageInfos_UserId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library."ImageInfos" USING btree ("UserId"); + + +-- +-- Name: IX_ItemValuesMap_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemValuesMap_ItemId" ON library."ItemValuesMap" USING btree ("ItemId"); + + +-- +-- Name: IX_ItemValues_Type_CleanValue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library."ItemValues" USING btree ("Type", "CleanValue"); + + +-- +-- Name: IX_ItemValues_Type_Value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library."ItemValues" USING btree ("Type", "Value"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex" ON library."MediaStreamInfos" USING btree ("StreamIndex"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex_StreamType; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex_StreamType_Language; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType_Language" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType", "Language"); + + +-- +-- Name: IX_MediaStreamInfos_StreamType; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamType" ON library."MediaStreamInfos" USING btree ("StreamType"); + + +-- +-- Name: IX_PeopleBaseItemMap_ItemId_ListOrder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_ItemId_ListOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "ListOrder"); + + +-- +-- Name: IX_PeopleBaseItemMap_ItemId_SortOrder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_ItemId_SortOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "SortOrder"); + + +-- +-- Name: IX_PeopleBaseItemMap_PeopleId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_PeopleId" ON library."PeopleBaseItemMap" USING btree ("PeopleId"); + + +-- +-- Name: IX_Peoples_Name; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_Peoples_Name" ON library."Peoples" USING btree ("Name"); + + +-- +-- Name: IX_UserData_ItemId_UserId_IsFavorite; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library."UserData" USING btree ("ItemId", "UserId", "IsFavorite"); + + +-- +-- Name: IX_UserData_ItemId_UserId_LastPlayedDate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library."UserData" USING btree ("ItemId", "UserId", "LastPlayedDate"); + + +-- +-- Name: IX_UserData_ItemId_UserId_PlaybackPositionTicks; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library."UserData" USING btree ("ItemId", "UserId", "PlaybackPositionTicks"); + + +-- +-- Name: IX_UserData_ItemId_UserId_Played; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library."UserData" USING btree ("ItemId", "UserId", "Played"); + + +-- +-- Name: IX_UserData_UserId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_UserId" ON library."UserData" USING btree ("UserId"); + + +-- +-- Name: baseitemproviders_providerid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitemproviders_providerid_idx ON library."BaseItemProviders" USING btree ("ProviderId", "ItemId"); + + +-- +-- Name: baseitemproviders_providervalue_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitemproviders_providervalue_idx ON library."BaseItemProviders" USING btree ("ProviderValue", "ProviderId"); + + +-- +-- Name: baseitems_communityrating_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_communityrating_idx ON library."BaseItems" USING btree ("CommunityRating" DESC); + + +-- +-- Name: baseitems_datecreated_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datecreated_idx ON library."BaseItems" USING btree ("DateCreated" DESC); + + +-- +-- Name: baseitems_datemodified_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datemodified_idx ON library."BaseItems" USING btree ("DateModified" DESC); + + +-- +-- Name: baseitems_parentid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_parentid_idx ON library."BaseItems" USING btree ("ParentId", "Type"); + + +-- +-- Name: baseitems_premieredate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_premieredate_idx ON library."BaseItems" USING btree ("PremiereDate" DESC); + + +-- +-- Name: baseitems_productionyear_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_productionyear_idx ON library."BaseItems" USING btree ("ProductionYear" DESC); + + +-- +-- Name: baseitems_seriespresentationuniquekey_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_seriespresentationuniquekey_idx ON library."BaseItems" USING btree ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); + + +-- +-- Name: baseitems_sortname_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_sortname_idx ON library."BaseItems" USING btree ("SortName"); + + +-- +-- Name: baseitems_topparentid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_topparentid_idx ON library."BaseItems" USING btree ("TopParentId", "Type"); + + +-- +-- Name: idx_baseitems_datecreated_filtered; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_datecreated_filtered ON library."BaseItems" USING btree ("DateCreated" DESC, "Type", "IsVirtualItem") WHERE (("DateCreated" IS NOT NULL) AND ("IsVirtualItem" = false)); + + +-- +-- Name: idx_baseitems_presentationuniquekey_episodes; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_presentationuniquekey_episodes ON library."BaseItems" USING btree ("PresentationUniqueKey", "TopParentId", "IsVirtualItem") WHERE (("Type" = 'MediaBrowser.Controller.Entities.TV.Episode'::text) AND ("PresentationUniqueKey" IS NOT NULL)); + + +-- +-- Name: idx_baseitems_topparentid_isfolder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_topparentid_isfolder ON library."BaseItems" USING btree ("TopParentId", "IsFolder", "IsVirtualItem") WHERE ("TopParentId" IS NOT NULL); + + +-- +-- Name: idx_baseitems_type_isvirtualitem_topparentid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_type_isvirtualitem_topparentid ON library."BaseItems" USING btree ("Type", "IsVirtualItem", "TopParentId") WHERE ("IsVirtualItem" = false); + + +-- +-- Name: idx_itemvalues_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_cleanvalue ON library."ItemValues" USING btree ("CleanValue") WHERE ("CleanValue" IS NOT NULL); + + +-- +-- Name: idx_itemvalues_id_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_id_cleanvalue ON library."ItemValues" USING btree ("ItemValueId", "CleanValue"); + + +-- +-- Name: idx_itemvalues_value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_value ON library."ItemValues" USING btree ("Value") WHERE ("Value" IS NOT NULL); + + +-- +-- Name: idx_itemvaluesmap_itemvalueid_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library."ItemValuesMap" USING btree ("ItemValueId", "ItemId"); + + +-- +-- Name: mediastreaminfos_codec_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_codec_idx ON library."MediaStreamInfos" USING btree ("Codec"); + + +-- +-- Name: mediastreaminfos_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_itemid_idx ON library."MediaStreamInfos" USING btree ("ItemId", "StreamType"); + + +-- +-- Name: peoplebaseitemmap_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_itemid_idx ON library."PeopleBaseItemMap" USING btree ("ItemId", "PeopleId"); + + +-- +-- Name: peoplebaseitemmap_peopleid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_peopleid_idx ON library."PeopleBaseItemMap" USING btree ("PeopleId", "ItemId"); + + +-- +-- Name: userdata_lastplayeddate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_lastplayeddate_idx ON library."UserData" USING btree ("LastPlayedDate" DESC); + + +-- +-- Name: userdata_userid_isfavorite_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_isfavorite_idx ON library."UserData" USING btree ("UserId", "IsFavorite"); + + +-- +-- Name: userdata_userid_played_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_played_idx ON library."UserData" USING btree ("UserId", "Played"); + + +-- +-- Name: IX_AccessSchedules_UserId; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE INDEX "IX_AccessSchedules_UserId" ON users."AccessSchedules" USING btree ("UserId"); + + +-- +-- Name: IX_Permissions_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users."Permissions" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_Preferences_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users."Preferences" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_Users_Username; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Users_Username" ON users."Users" USING btree ("Username"); + + +-- +-- Name: Devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."Devices" + ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: DisplayPreferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."DisplayPreferences" + ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: HomeSection FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."HomeSection" + ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY ("DisplayPreferencesId") REFERENCES displaypreferences."DisplayPreferences"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemDisplayPreferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" + ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: AncestorIds FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: AncestorIds FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY ("ParentItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: AttachmentStreamInfos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AttachmentStreamInfos" + ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemImageInfos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemImageInfos" + ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemMetadataFields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemMetadataFields" + ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemProviders FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemProviders" + ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemTrailerTypes FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemTrailerTypes" + ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItems FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItems" + ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY ("ParentId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: Chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Chapters" + ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: ImageInfos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ImageInfos" + ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemValuesMap FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemValuesMap FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY ("ItemValueId") REFERENCES library."ItemValues"("ItemValueId") ON DELETE CASCADE; + + +-- +-- Name: KeyframeData FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."KeyframeData" + ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: MediaStreamInfos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaStreamInfos" + ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY ("PeopleId") REFERENCES library."Peoples"("Id") ON DELETE CASCADE; + + +-- +-- Name: UserData FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: UserData FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: AccessSchedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."AccessSchedules" + ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: Permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Permissions" + ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: Preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Preferences" + ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- PostgreSQL database dump complete +-- + +\unrestrict BQanTgDKfPEe1ad123fH2eOQKfeiGuQ1HWaeH3TgqI0dLTNNmavSsSEklw1qhxQ + diff --git a/apply-supplementary-indexes-migration.sql b/apply-supplementary-indexes-migration.sql new file mode 100644 index 00000000..e69de29b diff --git a/fix-activitylog-index.sql b/fix-activitylog-index.sql new file mode 100644 index 00000000..e69de29b diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs index d2f925cf..be92c1fa 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs @@ -375,12 +375,11 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider logger.LogWarning("Database configuration not available. Database existence check skipped."); } - logger.LogInformation("Checking PostgreSQL database for missing tables..."); + logger.LogInformation("Checking PostgreSQL database schema..."); var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); await using (context.ConfigureAwait(false)) { - // Check if database is empty (no schema or no tables) and initialize if needed var connection = context.Database.GetDbConnection(); var wasConnectionOpened = false; @@ -392,160 +391,67 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider wasConnectionOpened = true; } - // Check if the library schema exists + // Check if the library schema exists (indicates database is initialized) var schemaCheckQuery = "SELECT COUNT(*) FROM information_schema.schemata WHERE schema_name = 'library'"; await using (var schemaCheckCommand = connection.CreateCommand()) { schemaCheckCommand.CommandText = schemaCheckQuery; - var schemaExists = (long?)await schemaCheckCommand.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); + var schemaCount = (long?)await schemaCheckCommand.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false); - if (schemaExists == 0) + if (schemaCount == 0) { - logger.LogInformation("Database is empty (library schema not found). Attempting to initialize from SQL script..."); + // Database is empty - initialize from SQL script + logger.LogInformation("Database is empty (library schema not found). Initializing from SQL script..."); - // Try to load and execute create_database_schema.sql var schemaScriptPath = Path.Combine(AppContext.BaseDirectory, "sql", "schema_init", "create_database_schema.sql"); - if (File.Exists(schemaScriptPath)) + if (!File.Exists(schemaScriptPath)) { - logger.LogInformation("Found schema script at: {Path}", schemaScriptPath); - logger.LogInformation("Executing create_database_schema.sql to initialize database..."); - - try - { - var schemaScript = await File.ReadAllTextAsync(schemaScriptPath, cancellationToken).ConfigureAwait(false); - - // Execute the schema creation script - await using (var schemaCommand = connection.CreateCommand()) - { - schemaCommand.CommandText = schemaScript; - schemaCommand.CommandTimeout = 600; // 10 minutes for large schema creation - await schemaCommand.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false); - } - - logger.LogInformation("Successfully initialized database from SQL script"); - } - catch (Exception scriptEx) - { - logger.LogError(scriptEx, "Failed to execute schema creation script. You may need to run it manually: {Path}", schemaScriptPath); - throw; - } - } - else - { - logger.LogError("Database is empty but schema script not found at: {Path}", schemaScriptPath); - logger.LogError("Please create the database manually using the SQL script from sql/schema_init/create_database_schema.sql"); + logger.LogError("Schema script not found at: {Path}", schemaScriptPath); + logger.LogError("Cannot initialize database automatically. Please run the SQL script manually."); throw new FileNotFoundException($"Schema initialization script not found: {schemaScriptPath}"); } + + logger.LogInformation("Found schema script at: {Path}", schemaScriptPath); + logger.LogInformation("Executing create_database_schema.sql (this may take several minutes)..."); + + try + { + var schemaScript = await File.ReadAllTextAsync(schemaScriptPath, cancellationToken).ConfigureAwait(false); + + // Split script by statement terminator and execute each part + // PostgreSQL dump scripts may have multiple statements + await using (var command = connection.CreateCommand()) + { + command.CommandText = schemaScript; + command.CommandTimeout = 600; // 10 minutes + await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false); + } + + logger.LogInformation("✅ Successfully initialized database from SQL script"); + logger.LogInformation("Database is ready. You can now start Jellyfin."); + } + catch (Exception scriptEx) + { + logger.LogError(scriptEx, "Failed to execute schema creation script"); + logger.LogError("Please run the SQL script manually: psql -U jellyfin -d jellyfin -f {Path}", schemaScriptPath); + throw; + } } - } - - // DISABLED for .NET 11 preview: EnsureCreatedAsync bypasses migrations and creates schema directly - // This prevents proper migration tracking. Use manual SQL scripts instead. - // await context.Database.EnsureCreatedAsync(cancellationToken).ConfigureAwait(false); - - logger.LogInformation("Database schema verification complete."); - - // Close connection before getting migrations to allow EF to manage connections - if (wasConnectionOpened && connection.State == System.Data.ConnectionState.Open) - { - await connection.CloseAsync().ConfigureAwait(false); - wasConnectionOpened = false; - } - } - catch - { - // Ensure connection is closed on error - if (wasConnectionOpened && connection.State == System.Data.ConnectionState.Open) - { - await connection.CloseAsync().ConfigureAwait(false); - } - - throw; - } - - // Get applied migrations - var appliedMigrations = await context.Database.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false); - var appliedMigrationsList = appliedMigrations.ToList(); - logger.LogDebug("Found {Count} applied migrations", appliedMigrationsList.Count); - - // Get pending migrations - var pendingMigrations = await context.Database.GetPendingMigrationsAsync(cancellationToken).ConfigureAwait(false); - var pendingMigrationsList = pendingMigrations.ToList(); - - if (pendingMigrationsList.Count > 0) - { - logger.LogInformation("Found {Count} pending migrations: {Migrations}", pendingMigrationsList.Count, string.Join(", ", pendingMigrationsList)); - - // DISABLED: EF Core migrations don't work with .NET 11 preview - // Use manual SQL scripts in Jellyfin.Server/sql/schema_init/ directory instead - logger.LogWarning("EF Core migrations are disabled for .NET 11 preview. Please apply migrations manually using SQL scripts in sql/schema_init/ directory."); - logger.LogWarning("Run the following script: apply-supplementary-indexes-migration.sql"); - - /* COMMENTED OUT - EF migrations not compatible with .NET 11 preview - logger.LogInformation("Applying migrations..."); - - try - { - // Apply all pending migrations - await context.Database.MigrateAsync(cancellationToken).ConfigureAwait(false); - logger.LogInformation("Successfully applied {Count} migrations", pendingMigrationsList.Count); - } - catch (Npgsql.PostgresException pgEx) when (pgEx.SqlState == "42P07") // relation already exists - { - // Table already exists - this can happen if migrations were partially applied - logger.LogWarning("Migration attempted to create existing table. This may indicate a previous failed migration. Error: {Message}", pgEx.Message); - logger.LogWarning("Attempting to mark migration as applied in history table..."); - - // Try to manually record the migration as applied - try + else { - await RecordMigrationAsAppliedAsync(context, pendingMigrationsList, cancellationToken).ConfigureAwait(false); - logger.LogInformation("Successfully recovered from partial migration state"); - } - catch (Exception recordEx) - { - logger.LogError(recordEx, "Failed to recover from partial migration. Manual intervention may be required."); - throw; + logger.LogInformation("Database schema exists (library schema found)"); } } - catch (InvalidOperationException ex) when (ex.Message.Contains("pending changes", StringComparison.OrdinalIgnoreCase)) - { - // This can happen if the model has changed but migrations haven't been generated - logger.LogWarning("Model has pending changes. This may indicate missing migration files. Error: {Message}", ex.Message); - logger.LogWarning("If you're seeing this on a test/production system, ensure all migration files are deployed."); - throw; - } - */ - } - else - { - logger.LogInformation("All database tables are up to date. No migrations needed."); - } - // Verify all expected tables exist in each schema - // Reopen connection for verification - if (connection.State != System.Data.ConnectionState.Open) - { - await connection.OpenAsync(cancellationToken).ConfigureAwait(false); - wasConnectionOpened = true; - } - - try - { + // Verify all expected schemas and tables exist foreach (var schema in Schemas.All) { - // Count tables in the schema - var countQuery = @" - SELECT COUNT(*) - FROM information_schema.tables - WHERE table_schema = @schema AND table_type = 'BASE TABLE'"; - + var tableCountQuery = "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = $1 AND table_type = 'BASE TABLE'"; await using (var command = connection.CreateCommand()) { - command.CommandText = countQuery; + command.CommandText = tableCountQuery; var parameter = command.CreateParameter(); - parameter.ParameterName = "@schema"; parameter.Value = schema; command.Parameters.Add(parameter); @@ -557,12 +463,12 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider } else { - logger.LogWarning("Schema '{Schema}' exists but contains no tables. This may indicate an incomplete migration.", schema); + logger.LogWarning("Schema '{Schema}' exists but contains no tables. This may indicate an incomplete initialization.", schema); } } } - logger.LogInformation("Database table verification complete"); + logger.LogInformation("✅ Database schema verification complete"); } finally { @@ -572,10 +478,15 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider } } } + + // NOTE: EF Core migrations are DISABLED for .NET 11 preview + // Database schema is created via SQL scripts (create_database_schema.sql) + // Any future migrations must be applied manually using SQL scripts + logger.LogInformation("EF Core migration system is disabled for .NET 11 preview. Use SQL scripts for schema changes."); } catch (Exception ex) { - logger.LogError(ex, "Failed to ensure PostgreSQL tables exist. Error: {Message}", ex.Message); + logger.LogError(ex, "Failed to verify or initialize PostgreSQL database"); throw; } }