Revision 6791
Added by Aaron Marcuse-Kubitza about 12 years ago
vegbien.sql | ||
---|---|---|
2070 | 2070 |
|
2071 | 2071 |
|
2072 | 2072 |
-- |
2073 |
-- Name: sourcename; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
2073 |
-- Name: sourcelist; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
|
2074 | 2074 |
-- |
2075 | 2075 |
|
2076 |
CREATE TABLE sourcename (
|
|
2077 |
sourcename_id integer NOT NULL,
|
|
2076 |
CREATE TABLE sourcelist (
|
|
2077 |
sourcelist_id integer NOT NULL,
|
|
2078 | 2078 |
source_id integer NOT NULL, |
2079 |
name text NOT NULL, |
|
2080 |
matched_source_id integer |
|
2079 |
name text NOT NULL |
|
2081 | 2080 |
); |
2082 | 2081 |
|
2083 | 2082 |
|
... | ... | |
2343 | 2342 |
-- |
2344 | 2343 |
|
2345 | 2344 |
CREATE VIEW analytical_stem_view AS |
2346 |
SELECT source.shortname AS datasource, sourcename.name AS "institutionCode", specimenreplicate.collectioncode_dwc AS "collectionCode", specimenreplicate.catalognumber_dwc AS "catalogNumber", specimenreplicate.sourceaccessioncode AS "occurrenceID", canon_place.country, canon_place.stateprovince AS "stateProvince", datasource_place.county, coordinates.latitude_deg AS "decimalLatitude", coordinates.longitude_deg AS "decimalLongitude", coordinates.coordsaccuracy_m AS "coordinateUncertaintyInMeters", (canon_place.geovalid)::integer AS geovalid, ("newWorldCountries"."isNewWorld")::integer AS "isNewWorld", project.sourceaccessioncode AS "projectID", COALESCE(location.sourceaccessioncode, location.authorlocationcode) AS "locationName", location.elevation_m AS "elevationInMeters", _m2_to_ha(location.area_m2) AS "plotArea_ha", method.name AS "samplingProtocol", COALESCE(locationevent.obsstartdate, parent_event.obsstartdate, aggregateoccurrence.collectiondate) AS "dateCollected", family_higher_plant_group.higher_plant_group AS "higherPlantGroup", accepted_taxonverbatim.family, accepted_taxonverbatim.genus, ((accepted_taxonverbatim.genus || ' '::text) || accepted_taxonverbatim.specific_epithet) AS "speciesBinomial", COALESCE(accepted_taxonverbatim.taxonomicname, accepted_taxonverbatim.taxonname) AS "scientificName", accepted_taxonverbatim.author AS "scientificNameAuthorship", NULLIF(array_to_string(ARRAY[COALESCE(accepted_taxonverbatim.genus, accepted_taxonverbatim.family), COALESCE(accepted_taxonverbatim.specific_epithet, parsed_taxonverbatim.morphospecies)], ' '::text), ''::text) AS "speciesBinomialWithMorphospecies", NULLIF(array_to_string(ARRAY[accepted_taxonlabel.taxonomicname, parsed_taxonverbatim.morphospecies], ' '::text), ''::text) AS "scientificNameWithMorphospecies", ((threatened_taxonlabel.taxonlabel_id IS NOT NULL))::integer AS threatened, identifiedby.fullname AS "identifiedBy", taxonoccurrence.growthform AS "growthForm", (((cultivated_family_locations.country IS NOT NULL) OR _or(taxonoccurrence.iscultivated, location.iscultivated)))::integer AS cultivated, CASE WHEN (taxonoccurrence.iscultivated IS NOT NULL) THEN taxonoccurrence.cultivatedbasis WHEN (location.iscultivated IS NOT NULL) THEN NULL::text ELSE NULL::text END AS "cultivatedBasis", collector.fullname AS "recordedBy", plantobservation.collectionnumber AS "recordNumber", _fraction_to_percent(aggregateoccurrence.cover_fraction) AS "coverPercent", _m_to_cm(stemobservation.diameterbreastheight_m) AS "diameterBreastHeight_cm", stemobservation.height_m, stemobservation.tag, stemobservation.xposition_m AS "organismX_m", stemobservation.yposition_m AS "organismY_m", taxonoccurrence.sourceaccessioncode AS "taxonOccurrenceID", taxonoccurrence.authortaxoncode AS "authorTaxonCode", plantobservation.sourceaccessioncode AS "individualID", stemobservation.authorstemcode AS "authorStemCode" FROM ((((((((((((((((((((((((((((((source JOIN location USING (source_id)) LEFT JOIN locationevent USING (location_id)) LEFT JOIN location parent_location ON ((parent_location.location_id = location.parent_id))) LEFT JOIN locationplace ON ((locationplace.location_id = COALESCE(parent_location.location_id, location.location_id)))) LEFT JOIN place datasource_place USING (place_id)) LEFT JOIN place canon_place ON ((canon_place.place_id = datasource_place.canon_place_id))) LEFT JOIN coordinates ON ((coordinates.coordinates_id = canon_place.coordinates_id))) LEFT JOIN "newWorld".iso_code_gadm ON ((iso_code_gadm."GADM country" = canon_place.country))) LEFT JOIN "newWorld"."newWorldCountries" ON (("newWorldCountries"."isoCode" = iso_code_gadm."2-digit iso code"))) LEFT JOIN taxonoccurrence USING (locationevent_id)) LEFT JOIN locationevent parent_event ON ((parent_event.locationevent_id = locationevent.parent_id))) LEFT JOIN project ON ((project.project_id = COALESCE(locationevent.project_id, parent_event.project_id)))) LEFT JOIN method ON ((method.method_id = COALESCE(locationevent.method_id, parent_event.method_id)))) LEFT JOIN party collector ON ((collector.party_id = taxonoccurrence.collector_id))) LEFT JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) LEFT JOIN taxonverbatim datasource_taxonverbatim USING (taxonverbatim_id)) LEFT JOIN taxonlabel datasource_taxonlabel USING (taxonlabel_id)) LEFT JOIN taxonlabel parsed_taxonlabel ON ((parsed_taxonlabel.taxonlabel_id = datasource_taxonlabel.matched_label_id))) LEFT JOIN taxonverbatim parsed_taxonverbatim ON ((parsed_taxonverbatim.taxonlabel_id = parsed_taxonlabel.taxonlabel_id))) LEFT JOIN taxonlabel accepted_taxonlabel ON ((accepted_taxonlabel.taxonlabel_id = datasource_taxonlabel.canon_label_id))) LEFT JOIN taxonverbatim accepted_taxonverbatim ON ((accepted_taxonverbatim.taxonlabel_id = accepted_taxonlabel.taxonlabel_id))) LEFT JOIN threatened_taxonlabel ON ((threatened_taxonlabel.taxonlabel_id = accepted_taxonlabel.taxonlabel_id))) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN family_higher_plant_group ON ((family_higher_plant_group.family = accepted_taxonverbatim.family))) LEFT JOIN cultivated_family_locations ON (((cultivated_family_locations.family = accepted_taxonverbatim.family) AND (cultivated_family_locations.country = canon_place.country)))) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN stemobservation USING (plantobservation_id)) LEFT JOIN specimenreplicate USING (plantobservation_id)) LEFT JOIN sourcename ON ((sourcename.sourcename_id = specimenreplicate.institution_id))) WHERE COALESCE(taxondetermination.iscurrent, true);
|
|
2345 |
SELECT source.shortname AS datasource, sourcelist.name AS "institutionCode", specimenreplicate.collectioncode_dwc AS "collectionCode", specimenreplicate.catalognumber_dwc AS "catalogNumber", specimenreplicate.sourceaccessioncode AS "occurrenceID", canon_place.country, canon_place.stateprovince AS "stateProvince", datasource_place.county, coordinates.latitude_deg AS "decimalLatitude", coordinates.longitude_deg AS "decimalLongitude", coordinates.coordsaccuracy_m AS "coordinateUncertaintyInMeters", (canon_place.geovalid)::integer AS geovalid, ("newWorldCountries"."isNewWorld")::integer AS "isNewWorld", project.sourceaccessioncode AS "projectID", COALESCE(location.sourceaccessioncode, location.authorlocationcode) AS "locationName", location.elevation_m AS "elevationInMeters", _m2_to_ha(location.area_m2) AS "plotArea_ha", method.name AS "samplingProtocol", COALESCE(locationevent.obsstartdate, parent_event.obsstartdate, aggregateoccurrence.collectiondate) AS "dateCollected", family_higher_plant_group.higher_plant_group AS "higherPlantGroup", accepted_taxonverbatim.family, accepted_taxonverbatim.genus, ((accepted_taxonverbatim.genus || ' '::text) || accepted_taxonverbatim.specific_epithet) AS "speciesBinomial", COALESCE(accepted_taxonverbatim.taxonomicname, accepted_taxonverbatim.taxonname) AS "scientificName", accepted_taxonverbatim.author AS "scientificNameAuthorship", NULLIF(array_to_string(ARRAY[COALESCE(accepted_taxonverbatim.genus, accepted_taxonverbatim.family), COALESCE(accepted_taxonverbatim.specific_epithet, parsed_taxonverbatim.morphospecies)], ' '::text), ''::text) AS "speciesBinomialWithMorphospecies", NULLIF(array_to_string(ARRAY[accepted_taxonlabel.taxonomicname, parsed_taxonverbatim.morphospecies], ' '::text), ''::text) AS "scientificNameWithMorphospecies", ((threatened_taxonlabel.taxonlabel_id IS NOT NULL))::integer AS threatened, identifiedby.fullname AS "identifiedBy", taxonoccurrence.growthform AS "growthForm", (((cultivated_family_locations.country IS NOT NULL) OR _or(taxonoccurrence.iscultivated, location.iscultivated)))::integer AS cultivated, CASE WHEN (taxonoccurrence.iscultivated IS NOT NULL) THEN taxonoccurrence.cultivatedbasis WHEN (location.iscultivated IS NOT NULL) THEN NULL::text ELSE NULL::text END AS "cultivatedBasis", collector.fullname AS "recordedBy", plantobservation.collectionnumber AS "recordNumber", _fraction_to_percent(aggregateoccurrence.cover_fraction) AS "coverPercent", _m_to_cm(stemobservation.diameterbreastheight_m) AS "diameterBreastHeight_cm", stemobservation.height_m, stemobservation.tag, stemobservation.xposition_m AS "organismX_m", stemobservation.yposition_m AS "organismY_m", taxonoccurrence.sourceaccessioncode AS "taxonOccurrenceID", taxonoccurrence.authortaxoncode AS "authorTaxonCode", plantobservation.sourceaccessioncode AS "individualID", stemobservation.authorstemcode AS "authorStemCode" FROM ((((((((((((((((((((((((((((((source JOIN location USING (source_id)) LEFT JOIN locationevent USING (location_id)) LEFT JOIN location parent_location ON ((parent_location.location_id = location.parent_id))) LEFT JOIN locationplace ON ((locationplace.location_id = COALESCE(parent_location.location_id, location.location_id)))) LEFT JOIN place datasource_place USING (place_id)) LEFT JOIN place canon_place ON ((canon_place.place_id = datasource_place.canon_place_id))) LEFT JOIN coordinates ON ((coordinates.coordinates_id = canon_place.coordinates_id))) LEFT JOIN "newWorld".iso_code_gadm ON ((iso_code_gadm."GADM country" = canon_place.country))) LEFT JOIN "newWorld"."newWorldCountries" ON (("newWorldCountries"."isoCode" = iso_code_gadm."2-digit iso code"))) LEFT JOIN taxonoccurrence USING (locationevent_id)) LEFT JOIN locationevent parent_event ON ((parent_event.locationevent_id = locationevent.parent_id))) LEFT JOIN project ON ((project.project_id = COALESCE(locationevent.project_id, parent_event.project_id)))) LEFT JOIN method ON ((method.method_id = COALESCE(locationevent.method_id, parent_event.method_id)))) LEFT JOIN party collector ON ((collector.party_id = taxonoccurrence.collector_id))) LEFT JOIN taxondetermination USING (taxonoccurrence_id)) LEFT JOIN party identifiedby ON ((identifiedby.party_id = taxondetermination.party_id))) LEFT JOIN taxonverbatim datasource_taxonverbatim USING (taxonverbatim_id)) LEFT JOIN taxonlabel datasource_taxonlabel USING (taxonlabel_id)) LEFT JOIN taxonlabel parsed_taxonlabel ON ((parsed_taxonlabel.taxonlabel_id = datasource_taxonlabel.matched_label_id))) LEFT JOIN taxonverbatim parsed_taxonverbatim ON ((parsed_taxonverbatim.taxonlabel_id = parsed_taxonlabel.taxonlabel_id))) LEFT JOIN taxonlabel accepted_taxonlabel ON ((accepted_taxonlabel.taxonlabel_id = datasource_taxonlabel.canon_label_id))) LEFT JOIN taxonverbatim accepted_taxonverbatim ON ((accepted_taxonverbatim.taxonlabel_id = accepted_taxonlabel.taxonlabel_id))) LEFT JOIN threatened_taxonlabel ON ((threatened_taxonlabel.taxonlabel_id = accepted_taxonlabel.taxonlabel_id))) LEFT JOIN aggregateoccurrence USING (taxonoccurrence_id)) LEFT JOIN family_higher_plant_group ON ((family_higher_plant_group.family = accepted_taxonverbatim.family))) LEFT JOIN cultivated_family_locations ON (((cultivated_family_locations.family = accepted_taxonverbatim.family) AND (cultivated_family_locations.country = canon_place.country)))) LEFT JOIN plantobservation USING (aggregateoccurrence_id)) LEFT JOIN stemobservation USING (plantobservation_id)) LEFT JOIN specimenreplicate USING (plantobservation_id)) LEFT JOIN sourcelist ON ((sourcelist.sourcelist_id = specimenreplicate.institution_id))) WHERE COALESCE(taxondetermination.iscurrent, true);
|
|
2347 | 2346 |
|
2348 | 2347 |
|
2349 | 2348 |
-- |
... | ... | |
3816 | 3815 |
|
3817 | 3816 |
|
3818 | 3817 |
-- |
3819 |
-- Name: sourcename_sourcename_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
3818 |
-- Name: sourcelist_sourcelist_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
|
3820 | 3819 |
-- |
3821 | 3820 |
|
3822 |
CREATE SEQUENCE sourcename_sourcename_id_seq
|
|
3821 |
CREATE SEQUENCE sourcelist_sourcelist_id_seq
|
|
3823 | 3822 |
START WITH 1 |
3824 | 3823 |
INCREMENT BY 1 |
3825 | 3824 |
NO MINVALUE |
... | ... | |
3828 | 3827 |
|
3829 | 3828 |
|
3830 | 3829 |
-- |
3831 |
-- Name: sourcename_sourcename_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
3830 |
-- Name: sourcelist_sourcelist_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
|
3832 | 3831 |
-- |
3833 | 3832 |
|
3834 |
ALTER SEQUENCE sourcename_sourcename_id_seq OWNED BY sourcename.sourcename_id;
|
|
3833 |
ALTER SEQUENCE sourcelist_sourcelist_id_seq OWNED BY sourcelist.sourcelist_id;
|
|
3835 | 3834 |
|
3836 | 3835 |
|
3837 | 3836 |
-- |
3838 |
-- Name: sourcename_sourcename_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
|
3837 |
-- Name: sourcelist_sourcelist_id_seq; Type: SEQUENCE SET; Schema: public; Owner: -
|
|
3839 | 3838 |
-- |
3840 | 3839 |
|
3841 | 3840 |
|
3842 | 3841 |
|
3843 | 3842 |
-- |
3843 |
-- Name: sourcename; Type: TABLE; Schema: public; Owner: -; Tablespace: |
|
3844 |
-- |
|
3845 |
|
|
3846 |
CREATE TABLE sourcename ( |
|
3847 |
sourcelist_id integer NOT NULL, |
|
3848 |
name text NOT NULL, |
|
3849 |
matched_source_id integer |
|
3850 |
); |
|
3851 |
|
|
3852 |
|
|
3853 |
-- |
|
3844 | 3854 |
-- Name: specimen; Type: TABLE; Schema: public; Owner: -; Tablespace: |
3845 | 3855 |
-- |
3846 | 3856 |
|
... | ... | |
4750 | 4760 |
|
4751 | 4761 |
|
4752 | 4762 |
-- |
4753 |
-- Name: sourcename_id; Type: DEFAULT; Schema: public; Owner: -
|
|
4763 |
-- Name: sourcelist_id; Type: DEFAULT; Schema: public; Owner: -
|
|
4754 | 4764 |
-- |
4755 | 4765 |
|
4756 |
ALTER TABLE ONLY sourcename ALTER COLUMN sourcename_id SET DEFAULT nextval('sourcename_sourcename_id_seq'::regclass);
|
|
4766 |
ALTER TABLE ONLY sourcelist ALTER COLUMN sourcelist_id SET DEFAULT nextval('sourcelist_sourcelist_id_seq'::regclass);
|
|
4757 | 4767 |
|
4758 | 4768 |
|
4759 | 4769 |
-- |
... | ... | |
5224 | 5234 |
|
5225 | 5235 |
|
5226 | 5236 |
-- |
5237 |
-- Data for Name: sourcelist; Type: TABLE DATA; Schema: public; Owner: - |
|
5238 |
-- |
|
5239 |
|
|
5240 |
|
|
5241 |
|
|
5242 |
-- |
|
5227 | 5243 |
-- Data for Name: sourcename; Type: TABLE DATA; Schema: public; Owner: - |
5228 | 5244 |
-- |
5229 | 5245 |
|
... | ... | |
5752 | 5768 |
|
5753 | 5769 |
|
5754 | 5770 |
-- |
5771 |
-- Name: sourcelist_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: |
|
5772 |
-- |
|
5773 |
|
|
5774 |
ALTER TABLE ONLY sourcelist |
|
5775 |
ADD CONSTRAINT sourcelist_pkey PRIMARY KEY (sourcelist_id); |
|
5776 |
|
|
5777 |
|
|
5778 |
-- |
|
5755 | 5779 |
-- Name: sourcename_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: |
5756 | 5780 |
-- |
5757 | 5781 |
|
5758 | 5782 |
ALTER TABLE ONLY sourcename |
5759 |
ADD CONSTRAINT sourcename_pkey PRIMARY KEY (sourcename_id);
|
|
5783 |
ADD CONSTRAINT sourcename_pkey PRIMARY KEY (sourcelist_id, name);
|
|
5760 | 5784 |
|
5761 | 5785 |
|
5762 | 5786 |
-- |
... | ... | |
6273 | 6297 |
|
6274 | 6298 |
|
6275 | 6299 |
-- |
6276 |
-- Name: sourcename_unique; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
|
6300 |
-- Name: sourcelist_unique; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
|
6277 | 6301 |
-- |
6278 | 6302 |
|
6279 |
CREATE UNIQUE INDEX sourcename_unique ON sourcename USING btree (source_id, (COALESCE(name, '\N'::text)));
|
|
6303 |
CREATE UNIQUE INDEX sourcelist_unique ON sourcelist USING btree (source_id, (COALESCE(name, '\N'::text)));
|
|
6280 | 6304 |
|
6281 | 6305 |
|
6282 | 6306 |
-- |
... | ... | |
7235 | 7259 |
|
7236 | 7260 |
|
7237 | 7261 |
-- |
7262 |
-- Name: sourcelist_source_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - |
|
7263 |
-- |
|
7264 |
|
|
7265 |
ALTER TABLE ONLY sourcelist |
|
7266 |
ADD CONSTRAINT sourcelist_source_id_fkey FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE CASCADE ON DELETE CASCADE; |
|
7267 |
|
|
7268 |
|
|
7269 |
-- |
|
7238 | 7270 |
-- Name: sourcename_matched_source_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - |
7239 | 7271 |
-- |
7240 | 7272 |
|
... | ... | |
7243 | 7275 |
|
7244 | 7276 |
|
7245 | 7277 |
-- |
7246 |
-- Name: sourcename_source_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - |
|
7278 |
-- Name: sourcename_sourcelist_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
|
|
7247 | 7279 |
-- |
7248 | 7280 |
|
7249 | 7281 |
ALTER TABLE ONLY sourcename |
7250 |
ADD CONSTRAINT sourcename_source_id_fkey FOREIGN KEY (source_id) REFERENCES source(source_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
|
7282 |
ADD CONSTRAINT sourcename_sourcelist_id_fkey FOREIGN KEY (sourcelist_id) REFERENCES sourcelist(sourcelist_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
|
7251 | 7283 |
|
7252 | 7284 |
|
7253 | 7285 |
-- |
... | ... | |
7255 | 7287 |
-- |
7256 | 7288 |
|
7257 | 7289 |
ALTER TABLE ONLY specimenreplicate |
7258 |
ADD CONSTRAINT specimenreplicate_institution_id_fkey FOREIGN KEY (institution_id) REFERENCES sourcename(sourcename_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
|
7290 |
ADD CONSTRAINT specimenreplicate_institution_id_fkey FOREIGN KEY (institution_id) REFERENCES sourcelist(sourcelist_id) ON UPDATE CASCADE ON DELETE CASCADE;
|
|
7259 | 7291 |
|
7260 | 7292 |
|
7261 | 7293 |
-- |
... | ... | |
7745 | 7777 |
|
7746 | 7778 |
|
7747 | 7779 |
-- |
7748 |
-- Name: sourcename; Type: ACL; Schema: public; Owner: -
|
|
7780 |
-- Name: sourcelist; Type: ACL; Schema: public; Owner: -
|
|
7749 | 7781 |
-- |
7750 | 7782 |
|
7751 |
REVOKE ALL ON TABLE sourcename FROM PUBLIC;
|
|
7752 |
REVOKE ALL ON TABLE sourcename FROM bien;
|
|
7753 |
GRANT ALL ON TABLE sourcename TO bien;
|
|
7754 |
GRANT SELECT ON TABLE sourcename TO bien_read;
|
|
7783 |
REVOKE ALL ON TABLE sourcelist FROM PUBLIC;
|
|
7784 |
REVOKE ALL ON TABLE sourcelist FROM bien;
|
|
7785 |
GRANT ALL ON TABLE sourcelist TO bien;
|
|
7786 |
GRANT SELECT ON TABLE sourcelist TO bien_read;
|
|
7755 | 7787 |
|
7756 | 7788 |
|
7757 | 7789 |
-- |
... | ... | |
8145 | 8177 |
|
8146 | 8178 |
|
8147 | 8179 |
-- |
8180 |
-- Name: sourcename; Type: ACL; Schema: public; Owner: - |
|
8181 |
-- |
|
8182 |
|
|
8183 |
REVOKE ALL ON TABLE sourcename FROM PUBLIC; |
|
8184 |
REVOKE ALL ON TABLE sourcename FROM bien; |
|
8185 |
GRANT ALL ON TABLE sourcename TO bien; |
|
8186 |
GRANT SELECT ON TABLE sourcename TO bien_read; |
|
8187 |
|
|
8188 |
|
|
8189 |
-- |
|
8148 | 8190 |
-- Name: specimen; Type: ACL; Schema: public; Owner: - |
8149 | 8191 |
-- |
8150 | 8192 |
|
Also available in: Unified diff
schemas/vegbien.sql: Allow multiple institutionCodes for each specimenreplicate by linking new sourcelist table many-to-many to source via sourcename (which is now a linking table)