|
30 | 30 | Union[str,int,float,decimal.Decimal,bool,datetime.datetime,datetime.date] |
31 | 31 | ] |
32 | 32 |
|
| 33 | +_RANGE_ELEMENT_TYPE_STR= {"TIMESTAMP","DATETIME","DATE"} |
| 34 | + |
33 | 35 |
|
34 | 36 | classConnectionProperty: |
35 | 37 | """A connection-level property to customize query behavior. |
@@ -362,6 +364,129 @@ def __repr__(self): |
362 | 364 | returnf"{self.__class__.__name__}({items}{name}{description})" |
363 | 365 |
|
364 | 366 |
|
| 367 | +classRangeQueryParameterType(_AbstractQueryParameterType): |
| 368 | +"""Type representation for range query parameters. |
| 369 | +
|
| 370 | + Args: |
| 371 | + type_ (Union[ScalarQueryParameterType, str]): |
| 372 | + Type of range element, must be one of 'TIMESTAMP', 'DATETIME', or |
| 373 | + 'DATE'. |
| 374 | + name (Optional[str]): |
| 375 | + The name of the query parameter. Primarily used if the type is |
| 376 | + one of the subfields in ``StructQueryParameterType`` instance. |
| 377 | + description (Optional[str]): |
| 378 | + The query parameter description. Primarily used if the type is |
| 379 | + one of the subfields in ``StructQueryParameterType`` instance. |
| 380 | + """ |
| 381 | + |
| 382 | +@classmethod |
| 383 | +def_parse_range_element_type(self,type_): |
| 384 | +"""Helper method that parses the input range element type, which may |
| 385 | + be a string, or a ScalarQueryParameterType object. |
| 386 | +
|
| 387 | + Returns: |
| 388 | + google.cloud.bigquery.query.ScalarQueryParameterType: Instance |
| 389 | + """ |
| 390 | +ifisinstance(type_,str): |
| 391 | +iftype_notin_RANGE_ELEMENT_TYPE_STR: |
| 392 | +raiseValueError( |
| 393 | +"If given as a string, range element type must be one of " |
| 394 | +"'TIMESTAMP', 'DATE', or 'DATETIME'." |
| 395 | + ) |
| 396 | +returnScalarQueryParameterType(type_) |
| 397 | +elifisinstance(type_,ScalarQueryParameterType): |
| 398 | +iftype_._typenotin_RANGE_ELEMENT_TYPE_STR: |
| 399 | +raiseValueError( |
| 400 | +"If given as a ScalarQueryParameter object, range element " |
| 401 | +"type must be one of 'TIMESTAMP', 'DATE', or 'DATETIME' " |
| 402 | +"type." |
| 403 | + ) |
| 404 | +returntype_ |
| 405 | +else: |
| 406 | +raiseValueError( |
| 407 | +"range_type must be a string or ScalarQueryParameter object, " |
| 408 | +"of 'TIMESTAMP', 'DATE', or 'DATETIME' type." |
| 409 | + ) |
| 410 | + |
| 411 | +def__init__(self,type_,*,name=None,description=None): |
| 412 | +self.type_=self._parse_range_element_type(type_) |
| 413 | +self.name=name |
| 414 | +self.description=description |
| 415 | + |
| 416 | +@classmethod |
| 417 | +deffrom_api_repr(cls,resource): |
| 418 | +"""Factory: construct parameter type from JSON resource. |
| 419 | +
|
| 420 | + Args: |
| 421 | + resource (Dict): JSON mapping of parameter |
| 422 | +
|
| 423 | + Returns: |
| 424 | + google.cloud.bigquery.query.RangeQueryParameterType: Instance |
| 425 | + """ |
| 426 | +type_=resource["rangeElementType"]["type"] |
| 427 | +name=resource.get("name") |
| 428 | +description=resource.get("description") |
| 429 | + |
| 430 | +returncls(type_,name=name,description=description) |
| 431 | + |
| 432 | +defto_api_repr(self): |
| 433 | +"""Construct JSON API representation for the parameter type. |
| 434 | +
|
| 435 | + Returns: |
| 436 | + Dict: JSON mapping |
| 437 | + """ |
| 438 | +# Name and description are only used if the type is a field inside a struct |
| 439 | +# type, but it's StructQueryParameterType's responsibilty to use these two |
| 440 | +# attributes in the API representation when needed. Here we omit them. |
| 441 | +return { |
| 442 | +"type":"RANGE", |
| 443 | +"rangeElementType":self.type_.to_api_repr(), |
| 444 | + } |
| 445 | + |
| 446 | +defwith_name(self,new_name:Union[str,None]): |
| 447 | +"""Return a copy of the instance with ``name`` set to ``new_name``. |
| 448 | +
|
| 449 | + Args: |
| 450 | + name (Union[str, None]): |
| 451 | + The new name of the range query parameter type. If ``None``, |
| 452 | + the existing name is cleared. |
| 453 | +
|
| 454 | + Returns: |
| 455 | + google.cloud.bigquery.query.RangeQueryParameterType: |
| 456 | + A new instance with updated name. |
| 457 | + """ |
| 458 | +returntype(self)(self.type_,name=new_name,description=self.description) |
| 459 | + |
| 460 | +def__repr__(self): |
| 461 | +name=f", name={self.name!r}"ifself.nameisnotNoneelse"" |
| 462 | +description= ( |
| 463 | +f", description={self.description!r}" |
| 464 | +ifself.descriptionisnotNone |
| 465 | +else"" |
| 466 | + ) |
| 467 | +returnf"{self.__class__.__name__}({self.type_!r}{name}{description})" |
| 468 | + |
| 469 | +def_key(self): |
| 470 | +"""A tuple key that uniquely describes this field. |
| 471 | +
|
| 472 | + Used to compute this instance's hashcode and evaluate equality. |
| 473 | +
|
| 474 | + Returns: |
| 475 | + Tuple: The contents of this |
| 476 | + :class:`~google.cloud.bigquery.query.RangeQueryParameterType`. |
| 477 | + """ |
| 478 | +type_=self.type_.to_api_repr() |
| 479 | +return (self.name,type_,self.description) |
| 480 | + |
| 481 | +def__eq__(self,other): |
| 482 | +ifnotisinstance(other,RangeQueryParameterType): |
| 483 | +returnNotImplemented |
| 484 | +returnself._key()==other._key() |
| 485 | + |
| 486 | +def__ne__(self,other): |
| 487 | +returnnotself==other |
| 488 | + |
| 489 | + |
365 | 490 | class_AbstractQueryParameter(object): |
366 | 491 | """Base class for named / positional query parameters.""" |
367 | 492 |
|
@@ -811,6 +936,178 @@ def __repr__(self): |
811 | 936 | return"StructQueryParameter{}".format(self._key()) |
812 | 937 |
|
813 | 938 |
|
| 939 | +classRangeQueryParameter(_AbstractQueryParameter): |
| 940 | +"""Named / positional query parameters for range values. |
| 941 | +
|
| 942 | + Args: |
| 943 | + range_element_type (Union[str, RangeQueryParameterType]): |
| 944 | + The type of range elements. It must be one of 'TIMESTAMP', |
| 945 | + 'DATE', or 'DATETIME'. |
| 946 | +
|
| 947 | + start (Optional[Union[ScalarQueryParameter, str]]): |
| 948 | + The start of the range value. Must be the same type as |
| 949 | + range_element_type. If not provided, it's interpreted as UNBOUNDED. |
| 950 | +
|
| 951 | + end (Optional[Union[ScalarQueryParameter, str]]): |
| 952 | + The end of the range value. Must be the same type as |
| 953 | + range_element_type. If not provided, it's interpreted as UNBOUNDED. |
| 954 | +
|
| 955 | + name (Optional[str]): |
| 956 | + Parameter name, used via ``@foo`` syntax. If None, the |
| 957 | + parameter can only be addressed via position (``?``). |
| 958 | + """ |
| 959 | + |
| 960 | +@classmethod |
| 961 | +def_parse_range_element_type(self,range_element_type): |
| 962 | +ifisinstance(range_element_type,str): |
| 963 | +ifrange_element_typenotin_RANGE_ELEMENT_TYPE_STR: |
| 964 | +raiseValueError( |
| 965 | +"If given as a string, range_element_type must be one of " |
| 966 | +f"'TIMESTAMP', 'DATE', or 'DATETIME'. Got{range_element_type}." |
| 967 | + ) |
| 968 | +returnRangeQueryParameterType(range_element_type) |
| 969 | +elifisinstance(range_element_type,RangeQueryParameterType): |
| 970 | +ifrange_element_type.type_._typenotin_RANGE_ELEMENT_TYPE_STR: |
| 971 | +raiseValueError( |
| 972 | +"If given as a RangeQueryParameterType object, " |
| 973 | +"range_element_type must be one of 'TIMESTAMP', 'DATE', " |
| 974 | +"or 'DATETIME' type." |
| 975 | + ) |
| 976 | +returnrange_element_type |
| 977 | +else: |
| 978 | +raiseValueError( |
| 979 | +"range_element_type must be a string or " |
| 980 | +"RangeQueryParameterType object, of 'TIMESTAMP', 'DATE', " |
| 981 | +"or 'DATETIME' type. Got " |
| 982 | +f"{type(range_element_type)}:{range_element_type}" |
| 983 | + ) |
| 984 | + |
| 985 | +@classmethod |
| 986 | +def_serialize_range_element_value(self,value,type_): |
| 987 | +ifvalueisNoneorisinstance(value,str): |
| 988 | +returnvalue |
| 989 | +else: |
| 990 | +converter=_SCALAR_VALUE_TO_JSON_PARAM.get(type_) |
| 991 | +ifconverterisnotNone: |
| 992 | +returnconverter(value)# type: ignore |
| 993 | +else: |
| 994 | +raiseValueError( |
| 995 | +f"Cannot convert range element value from type{type_}, " |
| 996 | +"must be one of the strings 'TIMESTAMP', 'DATE' " |
| 997 | +"'DATETIME' or a RangeQueryParameterType object." |
| 998 | + ) |
| 999 | + |
| 1000 | +def__init__( |
| 1001 | +self, |
| 1002 | +range_element_type, |
| 1003 | +start=None, |
| 1004 | +end=None, |
| 1005 | +name=None, |
| 1006 | + ): |
| 1007 | +self.name=name |
| 1008 | +self.range_element_type=self._parse_range_element_type(range_element_type) |
| 1009 | +print(self.range_element_type.type_._type) |
| 1010 | +self.start=start |
| 1011 | +self.end=end |
| 1012 | + |
| 1013 | +@classmethod |
| 1014 | +defpositional( |
| 1015 | +cls,range_element_type,start=None,end=None |
| 1016 | + )->"RangeQueryParameter": |
| 1017 | +"""Factory for positional parameters. |
| 1018 | +
|
| 1019 | + Args: |
| 1020 | + range_element_type (Union[str, RangeQueryParameterType]): |
| 1021 | + The type of range elements. It must be one of `'TIMESTAMP'`, |
| 1022 | + `'DATE'`, or `'DATETIME'`. |
| 1023 | +
|
| 1024 | + start (Optional[Union[ScalarQueryParameter, str]]): |
| 1025 | + The start of the range value. Must be the same type as |
| 1026 | + range_element_type. If not provided, it's interpreted as |
| 1027 | + UNBOUNDED. |
| 1028 | +
|
| 1029 | + end (Optional[Union[ScalarQueryParameter, str]]): |
| 1030 | + The end of the range value. Must be the same type as |
| 1031 | + range_element_type. If not provided, it's interpreted as |
| 1032 | + UNBOUNDED. |
| 1033 | +
|
| 1034 | + Returns: |
| 1035 | + google.cloud.bigquery.query.RangeQueryParameter: Instance without |
| 1036 | + name. |
| 1037 | + """ |
| 1038 | +returncls(range_element_type,start,end) |
| 1039 | + |
| 1040 | +@classmethod |
| 1041 | +deffrom_api_repr(cls,resource:dict)->"RangeQueryParameter": |
| 1042 | +"""Factory: construct parameter from JSON resource. |
| 1043 | +
|
| 1044 | + Args: |
| 1045 | + resource (Dict): JSON mapping of parameter |
| 1046 | +
|
| 1047 | + Returns: |
| 1048 | + google.cloud.bigquery.query.RangeQueryParameter: Instance |
| 1049 | + """ |
| 1050 | +name=resource.get("name") |
| 1051 | +range_element_type= ( |
| 1052 | +resource.get("parameterType", {}).get("rangeElementType", {}).get("type") |
| 1053 | + ) |
| 1054 | +range_value=resource.get("parameterValue", {}).get("rangeValue", {}) |
| 1055 | +start=range_value.get("start", {}).get("value") |
| 1056 | +end=range_value.get("end", {}).get("value") |
| 1057 | + |
| 1058 | +returncls(range_element_type,start=start,end=end,name=name) |
| 1059 | + |
| 1060 | +defto_api_repr(self)->dict: |
| 1061 | +"""Construct JSON API representation for the parameter. |
| 1062 | +
|
| 1063 | + Returns: |
| 1064 | + Dict: JSON mapping |
| 1065 | + """ |
| 1066 | +range_element_type=self.range_element_type.to_api_repr() |
| 1067 | +type_=self.range_element_type.type_._type |
| 1068 | +start=self._serialize_range_element_value(self.start,type_) |
| 1069 | +end=self._serialize_range_element_value(self.end,type_) |
| 1070 | +resource= { |
| 1071 | +"parameterType":range_element_type, |
| 1072 | +"parameterValue": { |
| 1073 | +"rangeValue": { |
| 1074 | +"start": {"value":start}, |
| 1075 | +"end": {"value":end}, |
| 1076 | + }, |
| 1077 | + }, |
| 1078 | + } |
| 1079 | + |
| 1080 | +# distinguish between name not provided vs. name being empty string |
| 1081 | +ifself.nameisnotNone: |
| 1082 | +resource["name"]=self.name |
| 1083 | + |
| 1084 | +returnresource |
| 1085 | + |
| 1086 | +def_key(self): |
| 1087 | +"""A tuple key that uniquely describes this field. |
| 1088 | +
|
| 1089 | + Used to compute this instance's hashcode and evaluate equality. |
| 1090 | +
|
| 1091 | + Returns: |
| 1092 | + Tuple: The contents of this |
| 1093 | + :class:`~google.cloud.bigquery.query.RangeQueryParameter`. |
| 1094 | + """ |
| 1095 | + |
| 1096 | +range_element_type=self.range_element_type.to_api_repr() |
| 1097 | +return (self.name,range_element_type,self.start,self.end) |
| 1098 | + |
| 1099 | +def__eq__(self,other): |
| 1100 | +ifnotisinstance(other,RangeQueryParameter): |
| 1101 | +returnNotImplemented |
| 1102 | +returnself._key()==other._key() |
| 1103 | + |
| 1104 | +def__ne__(self,other): |
| 1105 | +returnnotself==other |
| 1106 | + |
| 1107 | +def__repr__(self): |
| 1108 | +return"RangeQueryParameter{}".format(self._key()) |
| 1109 | + |
| 1110 | + |
814 | 1111 | classSqlParameterScalarTypes: |
815 | 1112 | """Supported scalar SQL query parameter types as type objects.""" |
816 | 1113 |
|
|