<resource schema="mpc">
	<meta name="title">Minor Planet Center - Asteroid Orbital Data</meta>
	<meta name="schema-rank">200</meta>
	<meta name="creationDate">2009-09-08T10:30:00Z</meta>
	<meta name="description" format="rst">
		Complete Asteroid Data from the Minor Planet Center (MPC),
		updated once per month.  The MPC operates at the Smithsonian Astrophysical
		Observatory under the auspices of Division III of the International
		Astronomical Union (IAU); for the upstream data, see
		https://www.minorplanetcenter.net/data.

		The MPC Orbit database contains orbital elements of minor
		planets that have been published in the Minor Planet Circulars,
		the Minor Planet Orbit Supplement and the Minor Planet
		Electronic Circulars.
	</meta>

	<meta name="creator">Williams, G.; Keys, S.; Rudenko, M.; Galache, J.L.</meta>
	<meta name="facility">MPC catalogue distributed by ARI/Zentrum für Astronomie Heidelberg.</meta>
	
	<meta name="referenceURL"
		>http://www.minorplanetcenter.org/</meta>

	<meta name="subject">asteroids</meta>
	<meta name="subject">surveys</meta>

	<meta name="copyright" format="rst">
		This research has made use of data and/or services provided by the
		International Astronomical Union's Minor Planet Center.  Updated data
		files are available at http://www.minorplanetcenter.org/iau/mpc.html
	</meta>
	<meta name="source">1980CeMec..22...63M</meta>
	<meta name="type">Catalog</meta>  <!-- or Archive, Survey -->

	<execute at="m21 4:00" title="Update MPC data">
		<job>
			<code>
				execDef.spawnPython("bin/updateData.py")
			</code>
		</job>
	</execute>

	<table onDisk="True" id="mpcorb" adql="True">
		<index columns="name"/>
		<index columns="mag"/>
		<index columns="semimaj_ax"/>

		<column name="designation" tablehead="Number/Prov." type="text"
			description="Asteroid number or provisional designation."
			ucd="meta.id;meta.main"
			verbLevel="12"/>
		<column name="mag"
			tablehead="Mag"
			description="Absolute Magnitude of the asteroid, i.e., the
				magnitude of the asteroid at a distance of 1 AU when viewed
				at a phase angle of 0°."
			ucd="phys.magAbs"
			unit="mag"
			verbLevel="1"/>
		<column name="slope"
			tablehead="Slope"
			description="Slope Parameter G. It describes how the magnitude
				of the asteroid varies as a function of
				changing illumination (phase angle)"
			ucd="src.morph.param"
			verbLevel="15"/>
		<column name="orb_epoch" type="double precision"
			tablehead="Epoch"
			description="Epoch of the orbit (julian years)"
			unit="yr"
			ucd="time.epoch"
			verbLevel="15"
			displayHint="sf=4"/>
		<column name="mean_anomaly"
			tablehead="Mean Anom."
			description="Mean anomaly at the epoch"
			ucd="src.orbital.meanAnomaly"
			unit="deg"	
			verbLevel="15"/>
		<column name="arg_perihel"
			tablehead="Arg. Perihel."
			description="Argument of Perihelion, J2000.0"
			ucd="src.orbital.periastron"
			unit="deg"
			verbLevel="15"/>
		<column name="long_asc"
			tablehead="Asc. Node"
			description="Longitude of ascending node, J2000.0"
			ucd="src.orbital.node"
			unit="deg"
			verbLevel="15"/>
		<column name="inclination"
			tablehead="i"
			description="Inclination of the orbit to the ecliptic, J2000.0"
			ucd="src.orbital.inclination"
			unit="deg"
			verbLevel="15"/>
		<column name="eccentricity"
			tablehead="e"
			description="Eccentricity of the orbit"
			ucd="src.orbital.eccentricity"
			verbLevel="1"/>
		<column name="mean_motion"
			tablehead="Mean Motion"
			description="Mean Daily Motion"
			ucd="pos.pm;arith.diff;phys.veloc"
			unit="deg/d"
			verbLevel="5"/>
		<column name="semimaj_ax"
			tablehead="Semimaj. ax."
			description="Orbital semimajor axis"
			ucd="phys.size.smajAxis"
			unit="AU"
			verbLevel="1"/>
		<column name="uncertainty_parameter" type="char"
			tablehead="Uncertainty"
			description="Quality code (0 is best) as per
				http://www.minorplanetcenter.org/iau/info/UValue.html.  Or:
				E -- the orbital eccentricity was
				assumed; D -- for one-opposition orbits this
				means a double (or multiple) designation is
				involved; F -- an e-assumed double (or multiple) designation
				is involved."
			ucd="meta.code.error"
			verbLevel="25">
			<values nullLiteral="0"/>
		</column>
		<column name="bib_reference" type="text"
			tablehead="Ref"
			description="Origin of the data"
			ucd="meta.bib"
			verbLevel="25"/>
		<column name="n_obs" type="integer"
			tablehead="#Obs"
			description="Number of Observations"
			ucd="meta.number;obs"
			verbLevel="15">
			<values nullLiteral="0"/>
		</column>
		<column name="n_opp" type="integer" required="True"
			tablehead="#Opp"
			description="Number of Oppositions"
			ucd="meta.number"
			verbLevel="15"/>
		<column name="arc_length" type="smallint"
			tablehead="Arc"
			description="Length of observed arcs for single-opposition orbits."
			ucd="time.interval"
			unit="d"
			verbLevel="15">
			<values nullLiteral="-1"/>
		</column>
		<column name="first_obs" type="smallint"
			tablehead="Disc. year"
			description="Discovery year for multi-opposition orbits."
			ucd="time.epoch"
			unit="yr"
			verbLevel="15">
			<values nullLiteral="-1"/>
		</column>
		<column name="rms_fit"
			tablehead="rms"
			description="RMS Residual of orbital fit"
			ucd="stat.fit.residual"
			unit="arcsec"
			verbLevel="15"/>
		<column name="perturbers" type="text"
			tablehead="Perturbers"
			description="Information on orbit perturbers; see table note."
			ucd="meta.note"
			verbLevel="25"
			note="1"/>
		<column name="computer" type="text"
			tablehead="Computer"
			description="Identifies the computer of the orbit"
			ucd="meta.note"
			verbLevel="25"/>

		<column name="orbit_class" type="text"
			tablehead="Class"
			description="Orbit family this object belongs to (note that
				the classification is based on cuts in osculating element
				space and is not 100% reliable."
			ucd="src.class"
			verbLevel="15"/>
		<column name="orbit_flags" type="text"
			tablehead="Flags"
			description="Additional classification flag(s) as comma-separated
				human-readable phrases"
			ucd="src.class"
			verbLevel="25"/>

		<column name="name" type="unicode"
			tablehead="Name"
			description="Human-readable designation of the Asteroid."
			ucd="meta.id"
			verbLevel="1"/>
		<column name="last_obs"
			tablehead="Last Obs."
			description="Date of last observation"
			unit="yr"
			ucd="time.epoch;obs"
			verbLevel="15"/>
		<column name="alt_target_name" type="unicode"
			hidden="True"
			verbLevel="40"/>
		<meta name="note" tag="1">
More information is available at
http://www.minorplanetcenter.net/iau/info/Perturbers.html

The first part of this is a descriptor of the system
used for the perturbing planets according to the follow scheme:

	=======    ======================================================
	(space)    Undefined/unknown, assume JPL DE200 positions + masses
	   d       JPL DE200 positions + masses
	   f       JPL DE245 positions + masses
	   h       JPL DE403 positions + masses
	   j       JPL DE405 positions + masses
	=======    ======================================================

The second part is a two-digit hexadecimal number
to be interpreted bitwise (this was taken literally from the MPC data
and will probably be parsed out at some point).  In the meantime,
here is the key to the bits:

	+------------+------+-------+-------------------------------+
	| Perturber  |  Bit | Value |                               |
	+============+======+=======+===============================+
	|   Hygiea   |   0  |  1    |                               |
	+------------+------+-------+-------------------------------+
	|    Earth   |   1  |  2    |  Bits 1 + 2 must              |
	+------------+------+-------+  both be set or both be       +
	|    Moon    |   2  |  4    |  unset!                       |
	+------------+------+-------+-------------------------------+
	|    Ceres   |   3  |  8    |                               |
	+------------+------+-------+-------------------------------+
	|    Pallas  |   4  |  16   |                               |
	+------------+------+-------+-------------------------------+
	|    Vesta   |   5  |  32   |                               |
	+------------+------+-------+-------------------------------+
	|    Eunomia |   6  |  64   |                               |
	+------------+------+-------+-------------------------------+

Sum the values of the included perturbers and convert to hexadecimal. Since
orbits will always include the major planets Mercury to Neptune there is no
need to include these bodies in the above scheme (other than allowing the earth
and moon to be treated separately).

Some examples of coarse and precise indicators are:

	 ======   =======    ============================================
	 Coarse   Precise    Perturbers (Mercury-Neptune+...)
	 ------   -------    --------------------------------------------
		 M-c      08       Ceres, EM barycenter
		 M-c      0E       Ceres, Earth, Moon
		 M-p      16       Pallas, Earth, Moon    [NOT RECOMMENDED]
		 M-p      18       Ceres, Pallas, EM barycenter
		 M-p      1E       Ceres, Pallas, Earth, Moon
		 M-v      38       Ceres, Pallas, Vesta, EM barycenter
		 M-v      3E       Ceres, Pallas, Vesta, Earth, Moon
		 M-e      78       Ceres, Pallas, Vesta, Euomia, EM barycenter
		 M-e      7E       Ceres, Pallas, Vesta, Euomia, Earth, Moon
		 M-h      39       Ceres, Pallas, Vesta, Hygiea, EM barycenter
	 ======   =======    ============================================

The default for Minor Planet Center orbits will henceforth be h (DE403), M-v (coarse) and 38 or 3E (precise, depending on whether the object is an earth-approacher or not). Additional perturbers will be added as necessary.
		</meta>

		</table>

	<service id="pla">
		<meta name="shortName">mpcorb_web</meta>
		<publish render="form" sets="local"/>

		<dbCore id="placore" queriedTable="mpcorb">
			<condDesc buildFrom="name"/>
			<condDesc buildFrom="designation"/>
			<condDesc buildFrom="semimaj_ax"/>
			<condDesc buildFrom="eccentricity"/>
			<condDesc buildFrom="inclination"/>
			<condDesc buildFrom="long_asc"/>
			<condDesc buildFrom="arg_perihel"/>
			<condDesc buildFrom="mean_anomaly"/>
			<condDesc buildFrom="orb_epoch"/>
			<condDesc buildFrom="mag"/>
			<condDesc buildFrom="orbit_class"/>
			<condDesc buildFrom="first_obs"/>
		</dbCore>
	 </service>

	<data id="import">
		<recreateAfter>createViews</recreateAfter>
		<sources pattern="data/MPCORB.DAT.gz"/>
		<!-- the thing isn't really latin1 but utf-8, but the columns are
		per-byte, so I can only properly decode after fielding -->
		<columnGrammar topIgnoredLines="43" preFilter="zcat" enc="latin1">
			<col key="designation">1-7</col>
			<col key="mag">9-13</col>
			<col key="slope">15-19</col>
			<col key="orb_epoch">21-25</col>
			<col key="mean_anomaly">27-35</col>
			<col key="arg_perihel">38-46</col>
			<col key="long_asc">49-57</col>
			<col key="inclination">60-68</col>
			<col key="eccentricity">71-79</col>
			<col key="mean_motion">81-91</col>
			<col key="semimaj_ax">93-103</col>
			<col key="uncertainty_parameter">106-106</col>
			<col key="bib_reference">108-116</col>
			<col key="n_obs">118-122</col>
			<col key="n_opp">124-126</col>
			<col key="obs_duration">128-136</col>		
			<col key="rms_fit">138-141</col>
			<col key="perturbers">143-149</col>
			<col key="computer">151-160</col>
			<col key="orbit_class">162-165</col>
			<col key="name">167-194</col>
			<col key="last_obs">195-202</col>

			<ignoreOn><keyIs key="designation" value=""/></ignoreOn>
		</columnGrammar>

		<rowmaker id="build_mpcorb" idmaps="*">
			<apply name="unpack_dates">
				<setup>
					<code>
						def unpackDate(val):
							century = 18+ord(val[0])-ord('I')
							year = int(val[1:3])
							try:
								month = int(val[3])
							except ValueError:
								month = 10+ord(val[3])-ord('A')
							try:
								day = int(val[4])
							except ValueError:
								day = 10+ord(val[4])-ord('A')
							return datetime.datetime(century*100+year, month, day)
					</code>
				</setup>
				<code>
					@orb_epoch = dateTimeToJYear(unpackDate(@orb_epoch))
				</code>
			</apply>

			<apply name="unpack_designation">
				<setup>
					<code>
						import string
						majInterpretation = dict((i, c) for c, i in enumerate(
							"0123456789"+string.ascii_uppercase+string.ascii_lowercase))

						def unpackDesig(val):
							year = (18+ord(val[0])-ord('I'))*100+int(val[1:3])
							letters = val[3]+val[6]
							cycle = majInterpretation[val[4]]*10+int(val[5])
							return "%d %s%s"%(
								year, letters, cycle or "")

						ORD0 = ord('0')
						ORDA = ord('A')
						ORDa = ord('a')

						def fromBase62(s):
							"""returns an integer from an MPC-style base-62 number.
							"""
							val = 0
							for c in s:
								val *= 62
								if c.isdigit():
									val += ord(c)-ORD0
								elif c.isupper():
									val += 10+(ord(c)-ORDA)
								elif c.islower():
									val += 36+(ord(c)-ORDa)
								else:
									raise ValueError(f"Invalid char in base-62 '{val}'")

							return val
					</code>
				</setup>

				<code>
					if @designation[0]=='~':
						@designation = "{:07d}".format(
							620000-fromBase62(@designation[1:]))

					elif len(@designation)==5:
						# it's a "packed number"
						digit = @designation[0]
						if digit.isdigit():
							tents = int(digit)
						elif digit.isupper():
							tents = ord(digit)-ord('A')+10
						elif digit.islower():
							tents = ord(digit)-ord('a')+36
						else:
							raise ValueError("Invalid packed number char")
						@designation = "%07d"%(tents*10000+int(@designation[1:]))

					else:
						# it's a survey or provisional designation
						for surv, abbrev in [
								("PLS", "P-L"),
								("T1S", "T-1"),
								("T2S", "T-2"),
								("T3S", "T-3")]:
							if @designation.startswith(surv):
								@designation = "%s %s"%(@designation[3:], abbrev)
								break
						else:
							@designation = unpackDesig(@designation)
				</code>
			</apply>

			<apply name="decode_flags">
				<setup>
					<code>
						familyCodes = {
							0:  None,
							1:  "Atira",
							2:  "Aten",
							3:  "Apollo",
							4:  "Amor",
							5:  "Object with q &lt; 1.665 AU",
							6:  "Hungaria",
							7:  "Phocaea",
							8:  "Hilda",
							9:  "Jupiter Trojan",
							10: "Distant object",
							}
					</code>
				</setup>
				<code>
					flags = int(@orbit_class, 16)
					res = familyCodes.get(flags&amp;0x3f, "PROBLEM -- Please contact"
						" the operators")
					@orbit_class = res
					
					extras = []
					for mask, msg in [
						(2048,  "Object is NEO"),
						(4096,  "Object is 1-km (or larger) NEO"),
						(8192,  "1-opposition object seen at earlier opposition"),
						(16384,  "Critical list numbered object"),
						(32768,  "Object is PHA")]:
						if flags&amp;mask:
							extras.append(msg)

					@orbit_flags = ", ".join(extras) or None
				</code>
			</apply>

			<apply name="disentagle_obs_duration">
				<code>
					try:
						if @obs_duration.endswith("days"):
							@arc_length = int(@obs_duration.split()[0])
							@first_obs = None
						else:
							@arc_length = None
							@first_obs = int(@obs_duration[:4])
					except ValueError:
						import warnings
						warnings.warn("Invalid obs_duration %s in Record %s"%(
							@obs_duration, @designation))
						@arc_length = @first_obs = None
				</code>
			</apply>

			<apply name="cleanup_target_name">
				<code>
					mat = re.match(r"\\((\\d+)\\)\\s*(.*)", @name)
					if mat:
						@name = mat.group(2)
						@alt_target_name = "{}#{}".format(mat.group(1), mat.group(2))
					else:
						@alt_target_name = None
				</code>
			</apply>

			<map key="last_obs" nullExcs="ValueError"
				>dateTimeToJYear(parseDate(@last_obs, "%Y%m%d"))</map>
		</rowmaker>

		<make table="mpcorb" rowmaker="build_mpcorb"/>
		<publish sets="ivo_managed"/>
	</data>

	<table id="epn_core">
		<meta name="title">
			EPN-TAP table for MPC Asteroid Orbital Data
		</meta>
		<meta name="shortName">MPC asteroids</meta>
		<meta name="description">
			The EPN-TAP 2.0 version of the complete asteroid data from the
			Minor Planet Center (MPC),
			updated once per month.  The MPC operates at the Smithsonian Astrophysical
			Observatory under the auspices of Division III of the International
			Astronomical Union (IAU).

			The MPC Orbit database contains orbital elements of minor
			planets that have been published in the Minor Planet Circulars,
			the Minor Planet Orbit Supplement and the Minor Planet
			Electronic Circulars.
		</meta>
		<publish/>

		<mixin spatial_frame_type="celestial"
			optional_columns="alt_target_name"
			>//epntap2#table-2_0</mixin>
		<LOOP>
			<csvItems>
				original_name, new_name
				mag,          magnitude
				slope,        slope_parameter
				orb_epoch,    orb_epoch
				mean_anomaly, mean_anomaly
				arg_perihel,  arg_perihel
				long_asc,     long_asc
				inclination,  inclination
				eccentricity, eccentricity
				mean_motion, mean_motion
				semimaj_ax, semi_major_axis
				uncertainty_parameter, uncertainty_parameter
				n_obs, n_obs
				n_opp, n_opp
				arc_length, arc_length
				rms_fit, rms_fit
				perturbers, perturbers
				computer, computer
				orbit_class, orbit_class
				orbit_flags, orbit_flags
				first_obs, first_obs
				last_obs, last_obs
				bib_reference, bib_reference
			</csvItems>
			<events>
				<column original="mpcorb.\original_name" name="\new_name"/>
			</events>
		</LOOP>

		<column original="target_name" type="unicode"/>
		<column original="alt_target_name" type="unicode"/>
  <viewStatement>
    CREATE VIEW \qName AS (
    	SELECT \colNames FROM (
                SELECT
                CAST (designation as text) AS granule_uid,
                text 'mpc' AS granule_gid,
                cast (designation as text)  AS obs_id,
                text 'ci' AS dataproduct_type,
                text 'phys.angSize.smajAxis;phys.size.smajAxis#src.orbital.eccentricity#src.orbital.node#src.orbital.periastron#src.orbital.meanAnomaly#phys.magAbs' AS measurement_type,
                integer '5' AS processing_level,
                cast (name as text) AS target_name,
                cast (alt_target_name as text) AS alt_target_name,
                text 'asteroid' AS target_class,
                CAST(NULL AS DOUBLE PRECISION) AS time_min,
                CAST(NULL AS DOUBLE PRECISION) AS time_max,
                CAST(NULL AS DOUBLE PRECISION) AS time_sampling_step_min,
                CAST(NULL AS DOUBLE PRECISION) AS time_sampling_step_max,
                CAST(NULL AS DOUBLE PRECISION) AS time_exp_min,
                CAST(NULL AS DOUBLE PRECISION) AS time_exp_max,
                CAST(NULL AS DOUBLE PRECISION) AS spectral_range_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_range_max,
CAST(NULL AS DOUBLE PRECISION) AS spectral_sampling_step_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_sampling_step_max,
CAST(NULL AS DOUBLE PRECISION) AS spectral_resolution_min,
CAST(NULL AS DOUBLE PRECISION) AS spectral_resolution_max,
CAST(NULL AS DOUBLE PRECISION) AS c1min,
CAST(NULL AS DOUBLE PRECISION) AS c1max,
CAST(NULL AS DOUBLE PRECISION) AS c2min,
CAST(NULL AS DOUBLE PRECISION) AS c2max,
CAST(NULL AS DOUBLE PRECISION) as c3min,
CAST(NULL AS DOUBLE PRECISION) as c3max,
CAST(NULL AS DOUBLE PRECISION) as c1_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c1_resol_max,
CAST(NULL AS DOUBLE PRECISION) as c2_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c2_resol_max,
               CAST(NULL AS DOUBLE PRECISION) as c3_resol_min,
CAST(NULL AS DOUBLE PRECISION) as c3_resol_max,
CAST('celestial' AS text) AS spatial_frame_type,
CAST(NULL AS DOUBLE PRECISION) as incidence_min,
CAST(NULL AS DOUBLE PRECISION) as incidence_max,
CAST(NULL AS DOUBLE PRECISION) as emergence_min,
CAST(NULL AS DOUBLE PRECISION) as emergence_max,
CAST(NULL AS DOUBLE PRECISION) as phase_min,
CAST(NULL AS DOUBLE PRECISION) as phase_max,
CAST(NULL AS text) AS instrument_host_name,
CAST(NULL AS text) AS instrument_name,
text 'mpc' AS service_title,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
	+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
	as release_date,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
	+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
	as creation_date,
make_timestamp(floor(last_obs)::integer, 1,1,0,0,0)
	+make_interval(0,0,0,((last_obs-floor(last_obs))*365.25)::integer)
	as modification_date,
CAST(NULL AS text) AS spatial_origin,
CAST(NULL AS text) AS time_origin,
CAST(NULL AS text) AS spatial_coordinate_description,
CAST(NULL AS text) AS publisher,
CAST(NULL AS text) AS access_md5,
CAST(NULL AS text) AS target_region,
CAST(NULL AS text) AS time_scale,
CAST(NULL AS text) as thumbnail_url,
CAST(NULL AS text) AS feature_name,
CAST(NULL AS text) AS file_name,
bib_reference AS bib_reference,
CAST(NULL AS text) AS access_format,
CAST(NULL AS text) as access_url,
integer '0' AS access_estsize,
CAST(NULL AS text) as species,
CAST(NULL AS spoly) AS s_region,
mag as magnitude,
slope as slope_parameter,
orb_epoch as orb_epoch,
mean_anomaly as mean_anomaly,
arg_perihel as arg_perihel,
long_asc as long_asc,
inclination as inclination,
eccentricity as eccentricity,
mean_motion as mean_motion,
semimaj_ax as semi_major_axis,
uncertainty_parameter as uncertainty_parameter,
n_obs as n_obs,
n_opp as n_opp,
arc_length as arc_length,
rms_fit as rms_fit,
perturbers as perturbers,
computer as computer,
orbit_class as orbit_class,
orbit_flags as orbit_flags,
first_obs as first_obs,
last_obs as last_obs
FROM mpc.mpcorb) as q)
</viewStatement>
</table>

  <data id="createViews" auto="False">
    <make table="epn_core"/>
  </data>

	<regSuite title="MPC regression">
		<regTest title="MPC EPN view works">
			<url lang="ADQL" query="select * from mpc.epn_core
				where granule_uid='0000457'">/tap/sync</url>
			<code>
				row = self.getFirstVOTableRow()
				self.assertAlmostEqual(row["semi_major_axis"],  3.09, places=1)
				self.assertTrue(isinstance(row['creation_date'],  datetime.datetime))
				self.assertEqual(row["target_name"], 'Alleghenia')
			</code>
		</regTest>

		<regTest title="MPC data plausible">
			<url parSet="form" _FORMAT="VOTable" designation="0000457">pla/form</url>
			<code>
				row = self.getFirstVOTableRow()
				self.assertAlmostEqual(row["mag"], 11.1, 0)
				self.assertTrue(row["orb_epoch"]>2015)
				self.assertTrue(row["last_obs"]>2015)
				self.assertEqual(row["arc_length"], None)
				self.assertEqual(row["first_obs"], 1900)
			</code>
		</regTest>

		<regTest title="Target names processed">
			<!-- this used to be a test for non-ascii names, but then
			upstream reverted the use of national characters.  Let's see
			how this develops. -->
			<url parSet="TAP" QUERY="SELECT
				target_name, alt_target_name
				FROM mpc.epn_core
				WHERE target_name LIKE 'V%'
					AND 1=ivo_hashlist_has(alt_target_name, '8639')">/tap/sync</url>
			<code>
				row = self.getFirstVOTableRow()
				self.assertEqual(row["target_name"], "Vonsovsky")
				self.assertEqual(row["alt_target_name"], "8639#Vonsovsky")
			</code>
		</regTest>
	</regSuite>

	<regSuite title="EPN-TAP regression">
		<regTest title="TIMESYS annotation in EPN-TAP">
			<url lang="ADQL" query="select * from mpc.epn_core
				where granule_uid='0000457'">/tap/sync</url>
			<code>
				self.assertXpath("//v:TIMESYS[@ID=//v:FIELD[@name='time_min']/@ref]",
					{"timeorigin": "0", "timescale": "UTC", "refposition": "TOPOCENTER"})
				self.assertXpath("//v:TIMESYS[@ID=//v:FIELD[@name='time_max']/@ref]",
					{"timeorigin": "0", "timescale": "UTC", "refposition": "TOPOCENTER"})
			</code>
		</regTest>
	</regSuite>
</resource>
