PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ postgis_valid_typmod()

GSERIALIZED* postgis_valid_typmod ( GSERIALIZED gser,
int32_t  typmod 
)

Check the consistency of the metadata we want to enforce in the typmod: srid, type and dimensionality.

If things are inconsistent, shut down the query.

Definition at line 119 of file gserialized_typmod.c.

References COLLECTIONTYPE, geometry_serialize(), gserialized_get_srid(), gserialized_get_type(), gserialized_has_m(), gserialized_has_z(), gserialized_is_empty(), gserialized_is_geodetic(), lwpoint_as_lwgeom(), lwpoint_construct_empty(), lwtype_name(), MULTILINETYPE, MULTIPOINTTYPE, MULTIPOLYGONTYPE, POINTTYPE, TYPMOD_GET_M, TYPMOD_GET_SRID, TYPMOD_GET_TYPE, and TYPMOD_GET_Z.

Referenced by geography_enforce_typmod(), geometry_enforce_typmod(), gserialized_geography_from_lwgeom(), LWGEOM_in(), and LWGEOM_recv().

120 {
121  int32 geom_srid = gserialized_get_srid(gser);
122  int32 geom_type = gserialized_get_type(gser);
123  int32 geom_z = gserialized_has_z(gser);
124  int32 geom_m = gserialized_has_m(gser);
125  int32 typmod_srid = TYPMOD_GET_SRID(typmod);
126  int32 typmod_type = TYPMOD_GET_TYPE(typmod);
127  int32 typmod_z = TYPMOD_GET_Z(typmod);
128  int32 typmod_m = TYPMOD_GET_M(typmod);
129 
130  POSTGIS_DEBUG(2, "Entered function");
131 
132  /* No typmod (-1) => no preferences */
133  if (typmod < 0) return gser;
134 
135  POSTGIS_DEBUGF(3, "Got geom(type = %d, srid = %d, hasz = %d, hasm = %d)", geom_type, geom_srid, geom_z, geom_m);
136  POSTGIS_DEBUGF(3, "Got typmod(type = %d, srid = %d, hasz = %d, hasm = %d)", typmod_type, typmod_srid, typmod_z, typmod_m);
137 
138  /*
139  * #3031: If a user is handing us a MULTIPOINT EMPTY but trying to fit it into
140  * a POINT geometry column, there's a strong chance the reason she has
141  * a MULTIPOINT EMPTY because we gave it to her during data dump,
142  * converting the internal POINT EMPTY into a EWKB MULTIPOINT EMPTY
143  * (because EWKB doesn't have a clean way to represent POINT EMPTY).
144  * In such a case, it makes sense to turn the MULTIPOINT EMPTY back into a
145  * point EMPTY, rather than throwing an error.
146  */
147  if ( typmod_type == POINTTYPE && geom_type == MULTIPOINTTYPE &&
148  gserialized_is_empty(gser) )
149  {
150  LWPOINT *empty_point = lwpoint_construct_empty(geom_srid, geom_z, geom_m);
151  geom_type = POINTTYPE;
152  pfree(gser);
153  if ( gserialized_is_geodetic(gser) )
154  gser = geography_serialize(lwpoint_as_lwgeom(empty_point));
155  else
156  gser = geometry_serialize(lwpoint_as_lwgeom(empty_point));
157  }
158 
159  /* Typmod has a preference for SRID? Geometry SRID had better match. */
160  if ( typmod_srid > 0 && typmod_srid != geom_srid )
161  {
162  ereport(ERROR, (
163  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
164  errmsg("Geometry SRID (%d) does not match column SRID (%d)", geom_srid, typmod_srid) ));
165  }
166 
167  /* Typmod has a preference for geometry type. */
168  if ( typmod_type > 0 &&
169  /* GEOMETRYCOLLECTION column can hold any kind of collection */
170  ((typmod_type == COLLECTIONTYPE && ! (geom_type == COLLECTIONTYPE ||
171  geom_type == MULTIPOLYGONTYPE ||
172  geom_type == MULTIPOINTTYPE ||
173  geom_type == MULTILINETYPE )) ||
174  /* Other types must be strictly equal. */
175  (typmod_type != geom_type)) )
176  {
177  ereport(ERROR, (
178  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
179  errmsg("Geometry type (%s) does not match column type (%s)", lwtype_name(geom_type), lwtype_name(typmod_type)) ));
180  }
181 
182  /* Mismatched Z dimensionality. */
183  if ( typmod_z && ! geom_z )
184  {
185  ereport(ERROR, (
186  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
187  errmsg("Column has Z dimension but geometry does not" )));
188  }
189 
190  /* Mismatched Z dimensionality (other way). */
191  if ( geom_z && ! typmod_z )
192  {
193  ereport(ERROR, (
194  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
195  errmsg("Geometry has Z dimension but column does not" )));
196  }
197 
198  /* Mismatched M dimensionality. */
199  if ( typmod_m && ! geom_m )
200  {
201  ereport(ERROR, (
202  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
203  errmsg("Column has M dimension but geometry does not" )));
204  }
205 
206  /* Mismatched M dimensionality (other way). */
207  if ( geom_m && ! typmod_m )
208  {
209  ereport(ERROR, (
210  errcode(ERRCODE_INVALID_PARAMETER_VALUE),
211  errmsg("Geometry has M dimension but column does not" )));
212  }
213 
214  return gser;
215 
216 }
#define TYPMOD_GET_TYPE(typmod)
Definition: liblwgeom.h:167
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
Definition: g_serialized.c:86
unsigned int int32
Definition: shpopen.c:273
#define TYPMOD_GET_M(typmod)
Definition: liblwgeom.h:171
int gserialized_has_m(const GSERIALIZED *gser)
Check if a GSERIALIZED has an M ordinate.
Definition: g_serialized.c:50
#define TYPMOD_GET_SRID(typmod)
Macros for manipulating the &#39;typemod&#39; int.
Definition: liblwgeom.h:165
#define MULTIPOINTTYPE
Definition: liblwgeom.h:88
LWPOINT * lwpoint_construct_empty(int srid, char hasz, char hasm)
Definition: lwpoint.c:151
int gserialized_has_z(const GSERIALIZED *gser)
Check if a GSERIALIZED has a Z ordinate.
Definition: g_serialized.c:45
int gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
Definition: g_serialized.c:179
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:218
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:90
GSERIALIZED * geometry_serialize(LWGEOM *lwgeom)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
Definition: lwgeom.c:303
int gserialized_is_geodetic(const GSERIALIZED *gser)
Check if a GSERIALIZED is a geography.
Definition: g_serialized.c:65
#define TYPMOD_GET_Z(typmod)
Definition: liblwgeom.h:169
#define MULTILINETYPE
Definition: liblwgeom.h:89
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:100
#define COLLECTIONTYPE
Definition: liblwgeom.h:91
Here is the call graph for this function:
Here is the caller graph for this function: