Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rzFTV-002jIl-EY for pgsql-general@arkaria.postgresql.org; Tue, 23 Apr 2024 12:42:17 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rzFTT-008MkI-2M for pgsql-general@arkaria.postgresql.org; Tue, 23 Apr 2024 12:42:15 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rzFTS-008MkA-JX for pgsql-general@lists.postgresql.org; Tue, 23 Apr 2024 12:42:14 +0000 Received: from mail-ej1-x632.google.com ([2a00:1450:4864:20::632]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rzFTP-004FSR-RB for pgsql-general@lists.postgresql.org; Tue, 23 Apr 2024 12:42:13 +0000 Received: by mail-ej1-x632.google.com with SMTP id a640c23a62f3a-a58872c07d8so20311166b.0 for ; Tue, 23 Apr 2024 05:42:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=f10-com-br.20230601.gappssmtp.com; s=20230601; t=1713876130; x=1714480930; darn=lists.postgresql.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=FkNbzm2shiRfM76MVTkBeS4jJur8c9p2DqlVCeUqip8=; b=SSJCpzc9KZ1dd6/+WPjyeUN+rJbweCggEc11kBuV08IoDx/ziwg6Hla44khaRr16LB tv51vwddGHY+Ux0SY5UnEFWFPcBCgBHDjJM8czuxUrV5N3PGos3t7FLZfp4iyjkp+kFv 4+63nOqUBg47Sl2P9sgVc9G9O7ofP+19ZSdqTiZlonrL/oyXAlMvFd7iRUj7hR/TEvBX FNhMuyV24QIl3SFXck7Zoh16117mFn3garmZUseumQJmHsPph7gWCnKDVzrcwDi6eu7n ovhBiUb2YnCX19TVb4jmX5et+OCU1r0Y1ZsX0jwjkGylFLeyvpNtEuiToStg+GvilbvY vfzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713876130; x=1714480930; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=FkNbzm2shiRfM76MVTkBeS4jJur8c9p2DqlVCeUqip8=; b=RpB91a9yeP0ZR7SDRYCIF5D+SbUpwRLAXu7qCXD0yEBkTTeM1aayIvyJqzpOzduqZG nmD4rCh378yKTIDZ2zubJtVeasO7Ejh+gmn9CvleoIRn7UD5iPqZ7EZIYwfwVFXQOnLy NFXP9/7H1TyPfGi+s3yQrUTAnnbuJS9cEfTvNvyFT1LiV+o+DeGsPAmyLQdn/wiV8Ysg DHkg2fgmQaKtQyIyhqk97g5+JoXgCqxiJRAemfANBb0yG46RS4XmBhx7FVLmmpA5+FPy OZWVGpDAqYP3xO/jB1hRZTuApV8X1ovdViiogAM3q61M0Lq1kWcLscHdmSD8LR4Z1r3k lLqg== X-Gm-Message-State: AOJu0Yw6sMvA/wfgWn0GlTx5txVkLWaXxdOZUMcZ1hsSRHmAH87ALtlc CiZ89rDj3Q8pTjWimFyxvcKBViI88GHKg7cLNRl7RnvRNCzC7jCnjVy8k1rSPKSUvk3ve8b2Joj IQKua9CepjizaHfp87SvTVWjhWAdMTCeZOCiq35v4pwG2IC9ZSg== X-Google-Smtp-Source: AGHT+IE3WFA4Q92qEgUM2sBJt8NYxBz2kHVO9+hH+6QVvLU9UtaNPcFsQFAF6kxc+LfN/OTOeRNAzFzsjWbz361vTc4= X-Received: by 2002:a17:907:9707:b0:a58:868e:d662 with SMTP id jg7-20020a170907970700b00a58868ed662mr470838ejc.11.1713876129827; Tue, 23 Apr 2024 05:42:09 -0700 (PDT) MIME-Version: 1.0 References: <30b10437-647c-48c9-8bd8-0f45b4af2d7b@erinors.com> In-Reply-To: <30b10437-647c-48c9-8bd8-0f45b4af2d7b@erinors.com> From: Marcos Pegoraro Date: Tue, 23 Apr 2024 09:41:25 -0300 Message-ID: Subject: Re: query multiple schemas To: =?UTF-8?Q?Norbert_S=C3=A1ndor?= Cc: pgsql-general@lists.postgresql.org Content-Type: multipart/alternative; boundary="000000000000e869dd0616c2e135" List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --000000000000e869dd0616c2e135 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Em dom., 21 de abr. de 2024 =C3=A0s 17:12, Norbert S=C3=A1ndor < sandor.norbert@erinors.com> escreveu: > Hello, > > I have a database with multiple tenants with a separate schema for each > tenant. > The structure of each schema is identical, the tenant ID is the name of > the schema. > > What I would like to achieve is to able to query tables in all schemas at > once with the tenant IDs added to the result set. > I have a similar structure and do my multi tenant queries this way. The only problem I see is that we have to define every result type, because I return a record, but it runs fine. create function sql_per_tenant(sql text, tenants text[]) returns setof record language plpgsql AS $function$ declare Result record; schemas text; begin for schemas in select unnest(tenants) loop execute Format('set local search_path to %s, public;', schemas); for Result in execute Format('select $$%1$s$$ tenant, * from (%2$s) x', schemas, sql) loop return next Result; end loop; end loop; end;$function$; select * from sql_per_tenant('select Order_ID, sum(Value) from Orders inner join Items using(Order_ID) where Due_Date =3D Current_Date','{cus_001,cus_035,cus_175}') as (SchemaName text, Order_ID integer, sum_of_items Numeric) regards Marcos --000000000000e869dd0616c2e135 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Em dom., 21 de abr. de = 2024 =C3=A0s 17:12, Norbert S=C3=A1ndor <sandor.norbert@erinors.com> escreve= u:
=20 =20 =20

Hello,

I have a database with multiple tenants with a separate schema for each tenant.
The structure of each schema is identical, the tenant ID is the name of the schema.

What I would like to achieve is to able to query tables in all schemas at once with the tenant IDs added to the result=C2=A0 set.

I have a similar structure and= =C2=A0do my multi tenant queries this way.=
The only problem I see is that we have to def= ine every result type, because I return a record, but it runs fine.<= /div>

creat= e function sql_per_tenant(sql text, tenants text[]) returns setof record la= nguage plpgsql AS $function$
declare
=C2=A0 Result record;
=C2=A0 = schemas text;
begin
=C2=A0 for schemas in select unnest(tenants) loop=
=C2=A0 =C2=A0 execute Format('set local search_path to %s, public;&= #39;, schemas);
=C2=A0 =C2=A0 for Result in execute Format('select $= $%1$s$$ tenant, * from (%2$s) x', schemas, sql) loop
=C2=A0 =C2=A0 = =C2=A0 return next Result;
=C2=A0 =C2=A0 end loop;
=C2=A0 end loop;end;$function$;

select * from sql_per_tenant('select Order_ID,= sum(Value) from Orders inner join Items using(Order_ID)=C2=A0
=
where Due_Date =3D Current_Date','{cus_001,= cus_035,cus_175}')=C2=A0
as (Schema= Name text, Order_ID integer, sum_of_items Numeric)
regards
Marcos
--000000000000e869dd0616c2e135--