diff options
Diffstat (limited to 'src/pq/pq_query_helper.c')
-rw-r--r-- | src/pq/pq_query_helper.c | 259 |
1 files changed, 221 insertions, 38 deletions
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c index a7455fc5f..b2bbe8ad4 100644 --- a/src/pq/pq_query_helper.c +++ b/src/pq/pq_query_helper.c | |||
@@ -24,6 +24,7 @@ | |||
24 | */ | 24 | */ |
25 | #include "gnunet_common.h" | 25 | #include "gnunet_common.h" |
26 | #include "gnunet_pq_lib.h" | 26 | #include "gnunet_pq_lib.h" |
27 | #include "gnunet_time_lib.h" | ||
27 | #include "platform.h" | 28 | #include "platform.h" |
28 | #include "pq.h" | 29 | #include "pq.h" |
29 | 30 | ||
@@ -589,6 +590,24 @@ struct pq_array_header | |||
589 | } __attribute__((packed)); | 590 | } __attribute__((packed)); |
590 | 591 | ||
591 | /** | 592 | /** |
593 | * Internal types that are supported as array types. | ||
594 | */ | ||
595 | |||
596 | enum array_types | ||
597 | { | ||
598 | array_of_bool, | ||
599 | array_of_uint16, | ||
600 | array_of_uint32, | ||
601 | array_of_uint64, | ||
602 | array_of_byte, /* buffers of (char *), (void *), ... */ | ||
603 | array_of_string, /* NULL-terminated (char *) */ | ||
604 | array_of_abs_time, | ||
605 | array_of_rel_time, | ||
606 | array_of_timestamp, | ||
607 | array_of_MAX, /* must be last */ | ||
608 | }; | ||
609 | |||
610 | /** | ||
592 | * Closure for the array type handlers. | 611 | * Closure for the array type handlers. |
593 | * | 612 | * |
594 | * May contain sizes information for the data, given (and handled) by the | 613 | * May contain sizes information for the data, given (and handled) by the |
@@ -620,7 +639,7 @@ struct qconv_array_cls | |||
620 | /** | 639 | /** |
621 | * Type of the array elements | 640 | * Type of the array elements |
622 | */ | 641 | */ |
623 | enum GNUNET_PQ_DataTypes typ; | 642 | enum array_types typ; |
624 | 643 | ||
625 | /** | 644 | /** |
626 | * Oid of the array elements | 645 | * Oid of the array elements |
@@ -674,7 +693,6 @@ qconv_array ( | |||
674 | size_t total_size; | 693 | size_t total_size; |
675 | const size_t *sizes; | 694 | const size_t *sizes; |
676 | bool same_sized; | 695 | bool same_sized; |
677 | bool is_string_array; | ||
678 | size_t *string_lengths = NULL; | 696 | size_t *string_lengths = NULL; |
679 | void *elements = NULL; | 697 | void *elements = NULL; |
680 | bool noerror = true; | 698 | bool noerror = true; |
@@ -687,7 +705,6 @@ qconv_array ( | |||
687 | 705 | ||
688 | sizes = meta->sizes; | 706 | sizes = meta->sizes; |
689 | same_sized = (0 != meta->same_size); | 707 | same_sized = (0 != meta->same_size); |
690 | is_string_array = (GNUNET_PQ_DATATYPE_VARCHAR == meta->typ); | ||
691 | 708 | ||
692 | #define RETURN_UNLESS(cond) \ | 709 | #define RETURN_UNLESS(cond) \ |
693 | do { \ | 710 | do { \ |
@@ -724,7 +741,7 @@ qconv_array ( | |||
724 | else /* sizes are different per element */ | 741 | else /* sizes are different per element */ |
725 | { | 742 | { |
726 | /* for an array of strings we need to get their length's first */ | 743 | /* for an array of strings we need to get their length's first */ |
727 | if (is_string_array) | 744 | if (array_of_string == meta->typ) |
728 | { | 745 | { |
729 | string_lengths = GNUNET_new_array (num, size_t); | 746 | string_lengths = GNUNET_new_array (num, size_t); |
730 | 747 | ||
@@ -787,37 +804,38 @@ qconv_array ( | |||
787 | 804 | ||
788 | switch (meta->typ) | 805 | switch (meta->typ) |
789 | { | 806 | { |
790 | case GNUNET_PQ_DATATYPE_INT2: | 807 | case array_of_bool: |
808 | { | ||
809 | GNUNET_assert (sizeof(bool) == sz); | ||
810 | GNUNET_memcpy (out, in, sz); | ||
811 | in += sz; | ||
812 | break; | ||
813 | } | ||
814 | case array_of_uint16: | ||
791 | { | 815 | { |
792 | GNUNET_assert (sizeof(uint16_t) == sz); | 816 | GNUNET_assert (sizeof(uint16_t) == sz); |
793 | *(uint16_t *) out = htons (*(uint16_t *) in); | 817 | *(uint16_t *) out = htons (*(uint16_t *) in); |
794 | in += sz; | 818 | in += sz; |
795 | break; | 819 | break; |
796 | } | 820 | } |
797 | case GNUNET_PQ_DATATYPE_INT4: | 821 | case array_of_uint32: |
798 | { | 822 | { |
799 | GNUNET_assert (sizeof(uint32_t) == sz); | 823 | GNUNET_assert (sizeof(uint32_t) == sz); |
800 | *(uint32_t *) out = htonl (*(uint32_t *) in); | 824 | *(uint32_t *) out = htonl (*(uint32_t *) in); |
801 | in += sz; | 825 | in += sz; |
802 | break; | 826 | break; |
803 | } | 827 | } |
804 | case GNUNET_PQ_DATATYPE_INT8: | 828 | case array_of_uint64: |
805 | { | 829 | { |
806 | GNUNET_assert (sizeof(uint64_t) == sz); | 830 | GNUNET_assert (sizeof(uint64_t) == sz); |
807 | *(uint64_t *) out = GNUNET_htonll (*(uint64_t *) in); | 831 | *(uint64_t *) out = GNUNET_htonll (*(uint64_t *) in); |
808 | in += sz; | 832 | in += sz; |
809 | break; | 833 | break; |
810 | } | 834 | } |
811 | case GNUNET_PQ_DATATYPE_BOOL: | 835 | case array_of_byte: |
812 | { | ||
813 | GNUNET_assert (sizeof(bool) == sz); | ||
814 | GNUNET_memcpy (out, in, sz); | ||
815 | in += sz; | ||
816 | break; | ||
817 | } | ||
818 | case GNUNET_PQ_DATATYPE_BYTEA: | ||
819 | { | 836 | { |
820 | const void *ptr; | 837 | const void *ptr; |
838 | |||
821 | if (meta->continuous) | 839 | if (meta->continuous) |
822 | { | 840 | { |
823 | ptr = in; | 841 | ptr = in; |
@@ -829,7 +847,7 @@ qconv_array ( | |||
829 | GNUNET_memcpy (out, ptr, sz); | 847 | GNUNET_memcpy (out, ptr, sz); |
830 | break; | 848 | break; |
831 | } | 849 | } |
832 | case GNUNET_PQ_DATATYPE_VARCHAR: | 850 | case array_of_string: |
833 | { | 851 | { |
834 | const void *ptr; | 852 | const void *ptr; |
835 | if (meta->continuous) | 853 | if (meta->continuous) |
@@ -843,6 +861,63 @@ qconv_array ( | |||
843 | GNUNET_memcpy (out, ptr, sz); | 861 | GNUNET_memcpy (out, ptr, sz); |
844 | break; | 862 | break; |
845 | } | 863 | } |
864 | case array_of_abs_time: | ||
865 | { | ||
866 | const struct GNUNET_TIME_Absolute *abs; | ||
867 | |||
868 | if (meta->continuous) | ||
869 | { | ||
870 | abs = (const struct GNUNET_TIME_Absolute *) in; | ||
871 | in += sz; | ||
872 | } | ||
873 | else | ||
874 | abs = ((const struct GNUNET_TIME_Absolute **) data)[i]; | ||
875 | |||
876 | if (abs->abs_value_us > INT64_MAX) | ||
877 | *(uint64_t *) out = GNUNET_htonll (INT64_MAX); | ||
878 | else | ||
879 | *(uint64_t *) out = GNUNET_htonll (abs->abs_value_us); | ||
880 | |||
881 | break; | ||
882 | } | ||
883 | case array_of_rel_time: | ||
884 | { | ||
885 | const struct GNUNET_TIME_Relative *rel; | ||
886 | |||
887 | if (meta->continuous) | ||
888 | { | ||
889 | rel = (const struct GNUNET_TIME_Relative *) in; | ||
890 | in += sz; | ||
891 | } | ||
892 | else | ||
893 | rel = ((const struct GNUNET_TIME_Relative **) data)[i]; | ||
894 | |||
895 | if (rel->rel_value_us > INT64_MAX) | ||
896 | *(uint64_t *) out = GNUNET_htonll (INT64_MAX); | ||
897 | else | ||
898 | *(uint64_t *) out = GNUNET_htonll (rel->rel_value_us); | ||
899 | |||
900 | break; | ||
901 | } | ||
902 | case array_of_timestamp: | ||
903 | { | ||
904 | const struct GNUNET_TIME_Timestamp *ts; | ||
905 | |||
906 | if (meta->continuous) | ||
907 | { | ||
908 | ts = (const struct GNUNET_TIME_Timestamp *) in; | ||
909 | in += sz; | ||
910 | } | ||
911 | else | ||
912 | ts = ((const struct GNUNET_TIME_Timestamp **) data)[i]; | ||
913 | |||
914 | if (ts->abs_time.abs_value_us > INT64_MAX) | ||
915 | *(uint64_t *) out = GNUNET_htonll (INT64_MAX); | ||
916 | else | ||
917 | *(uint64_t *) out = GNUNET_htonll (ts->abs_time.abs_value_us); | ||
918 | |||
919 | break; | ||
920 | } | ||
846 | default: | 921 | default: |
847 | { | 922 | { |
848 | GNUNET_assert (0); | 923 | GNUNET_assert (0); |
@@ -868,14 +943,26 @@ qconv_array ( | |||
868 | } | 943 | } |
869 | 944 | ||
870 | 945 | ||
946 | /** | ||
947 | * Function to genreate a typ specific query parameter and corresponding closure | ||
948 | * | ||
949 | * @param num Number of elements in @a elements | ||
950 | * @param continuous If true, @a elements is an continuous array of data | ||
951 | * @param elements Array of @a num elements, either continuous or pointers | ||
952 | * @param sizes Array of @a num sizes, one per element, may be NULL | ||
953 | * @param same_size If not 0, all elements in @a elements have this size | ||
954 | * @param typ Supported internal type of each element in @a elements | ||
955 | * @param oid Oid of the type to be used in Postgres | ||
956 | * @return Query parameter | ||
957 | */ | ||
871 | static struct GNUNET_PQ_QueryParam | 958 | static struct GNUNET_PQ_QueryParam |
872 | query_param_array_generic ( | 959 | query_param_array_generic ( |
873 | unsigned int num, | 960 | unsigned int num, |
961 | bool continuous, | ||
874 | const void *elements, | 962 | const void *elements, |
875 | const size_t *sizes, | 963 | const size_t *sizes, |
876 | bool continuous, | ||
877 | size_t same_size, | 964 | size_t same_size, |
878 | enum GNUNET_PQ_DataTypes typ, | 965 | enum array_types typ, |
879 | Oid oid) | 966 | Oid oid) |
880 | { | 967 | { |
881 | struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); | 968 | struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); |
@@ -905,11 +992,11 @@ GNUNET_PQ_query_param_array_bool ( | |||
905 | const struct GNUNET_PQ_Context *db) | 992 | const struct GNUNET_PQ_Context *db) |
906 | { | 993 | { |
907 | return query_param_array_generic (num, | 994 | return query_param_array_generic (num, |
995 | true, | ||
908 | elements, | 996 | elements, |
909 | NULL, | 997 | NULL, |
910 | true, | ||
911 | sizeof(bool), | 998 | sizeof(bool), |
912 | GNUNET_PQ_DATATYPE_BOOL, | 999 | array_of_bool, |
913 | db->oids[GNUNET_PQ_DATATYPE_BOOL]); | 1000 | db->oids[GNUNET_PQ_DATATYPE_BOOL]); |
914 | } | 1001 | } |
915 | 1002 | ||
@@ -921,11 +1008,11 @@ GNUNET_PQ_query_param_array_uint16 ( | |||
921 | const struct GNUNET_PQ_Context *db) | 1008 | const struct GNUNET_PQ_Context *db) |
922 | { | 1009 | { |
923 | return query_param_array_generic (num, | 1010 | return query_param_array_generic (num, |
1011 | true, | ||
924 | elements, | 1012 | elements, |
925 | NULL, | 1013 | NULL, |
926 | true, | ||
927 | sizeof(uint16_t), | 1014 | sizeof(uint16_t), |
928 | GNUNET_PQ_DATATYPE_INT2, | 1015 | array_of_uint16, |
929 | db->oids[GNUNET_PQ_DATATYPE_INT2]); | 1016 | db->oids[GNUNET_PQ_DATATYPE_INT2]); |
930 | } | 1017 | } |
931 | 1018 | ||
@@ -937,11 +1024,11 @@ GNUNET_PQ_query_param_array_uint32 ( | |||
937 | const struct GNUNET_PQ_Context *db) | 1024 | const struct GNUNET_PQ_Context *db) |
938 | { | 1025 | { |
939 | return query_param_array_generic (num, | 1026 | return query_param_array_generic (num, |
1027 | true, | ||
940 | elements, | 1028 | elements, |
941 | NULL, | 1029 | NULL, |
942 | true, | ||
943 | sizeof(uint32_t), | 1030 | sizeof(uint32_t), |
944 | GNUNET_PQ_DATATYPE_INT4, | 1031 | array_of_uint32, |
945 | db->oids[GNUNET_PQ_DATATYPE_INT4]); | 1032 | db->oids[GNUNET_PQ_DATATYPE_INT4]); |
946 | } | 1033 | } |
947 | 1034 | ||
@@ -953,11 +1040,11 @@ GNUNET_PQ_query_param_array_uint64 ( | |||
953 | const struct GNUNET_PQ_Context *db) | 1040 | const struct GNUNET_PQ_Context *db) |
954 | { | 1041 | { |
955 | return query_param_array_generic (num, | 1042 | return query_param_array_generic (num, |
1043 | true, | ||
956 | elements, | 1044 | elements, |
957 | NULL, | 1045 | NULL, |
958 | true, | ||
959 | sizeof(uint64_t), | 1046 | sizeof(uint64_t), |
960 | GNUNET_PQ_DATATYPE_INT8, | 1047 | array_of_uint64, |
961 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | 1048 | db->oids[GNUNET_PQ_DATATYPE_INT8]); |
962 | } | 1049 | } |
963 | 1050 | ||
@@ -970,11 +1057,11 @@ GNUNET_PQ_query_param_array_bytes ( | |||
970 | const struct GNUNET_PQ_Context *db) | 1057 | const struct GNUNET_PQ_Context *db) |
971 | { | 1058 | { |
972 | return query_param_array_generic (num, | 1059 | return query_param_array_generic (num, |
1060 | true, | ||
973 | elements, | 1061 | elements, |
974 | sizes, | 1062 | sizes, |
975 | true, | ||
976 | 0, | 1063 | 0, |
977 | GNUNET_PQ_DATATYPE_BYTEA, | 1064 | array_of_byte, |
978 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); | 1065 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); |
979 | } | 1066 | } |
980 | 1067 | ||
@@ -987,11 +1074,11 @@ GNUNET_PQ_query_param_array_ptrs_bytes ( | |||
987 | const struct GNUNET_PQ_Context *db) | 1074 | const struct GNUNET_PQ_Context *db) |
988 | { | 1075 | { |
989 | return query_param_array_generic (num, | 1076 | return query_param_array_generic (num, |
1077 | false, | ||
990 | elements, | 1078 | elements, |
991 | sizes, | 1079 | sizes, |
992 | false, | ||
993 | 0, | 1080 | 0, |
994 | GNUNET_PQ_DATATYPE_BYTEA, | 1081 | array_of_byte, |
995 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); | 1082 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); |
996 | } | 1083 | } |
997 | 1084 | ||
@@ -1004,11 +1091,11 @@ GNUNET_PQ_query_param_array_bytes_same_size ( | |||
1004 | const struct GNUNET_PQ_Context *db) | 1091 | const struct GNUNET_PQ_Context *db) |
1005 | { | 1092 | { |
1006 | return query_param_array_generic (num, | 1093 | return query_param_array_generic (num, |
1094 | true, | ||
1007 | elements, | 1095 | elements, |
1008 | NULL, | 1096 | NULL, |
1009 | true, | ||
1010 | same_size, | 1097 | same_size, |
1011 | GNUNET_PQ_DATATYPE_BYTEA, | 1098 | array_of_byte, |
1012 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); | 1099 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); |
1013 | } | 1100 | } |
1014 | 1101 | ||
@@ -1021,11 +1108,11 @@ GNUNET_PQ_query_param_array_ptrs_bytes_same_size ( | |||
1021 | const struct GNUNET_PQ_Context *db) | 1108 | const struct GNUNET_PQ_Context *db) |
1022 | { | 1109 | { |
1023 | return query_param_array_generic (num, | 1110 | return query_param_array_generic (num, |
1111 | false, | ||
1024 | elements, | 1112 | elements, |
1025 | NULL, | 1113 | NULL, |
1026 | false, | ||
1027 | same_size, | 1114 | same_size, |
1028 | GNUNET_PQ_DATATYPE_BYTEA, | 1115 | array_of_byte, |
1029 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); | 1116 | db->oids[GNUNET_PQ_DATATYPE_BYTEA]); |
1030 | } | 1117 | } |
1031 | 1118 | ||
@@ -1037,11 +1124,11 @@ GNUNET_PQ_query_param_array_string ( | |||
1037 | const struct GNUNET_PQ_Context *db) | 1124 | const struct GNUNET_PQ_Context *db) |
1038 | { | 1125 | { |
1039 | return query_param_array_generic (num, | 1126 | return query_param_array_generic (num, |
1127 | true, | ||
1040 | elements, | 1128 | elements, |
1041 | NULL, | 1129 | NULL, |
1042 | true, | ||
1043 | 0, | 1130 | 0, |
1044 | GNUNET_PQ_DATATYPE_VARCHAR, | 1131 | array_of_string, |
1045 | db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); | 1132 | db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); |
1046 | } | 1133 | } |
1047 | 1134 | ||
@@ -1053,13 +1140,109 @@ GNUNET_PQ_query_param_array_ptrs_string ( | |||
1053 | const struct GNUNET_PQ_Context *db) | 1140 | const struct GNUNET_PQ_Context *db) |
1054 | { | 1141 | { |
1055 | return query_param_array_generic (num, | 1142 | return query_param_array_generic (num, |
1143 | false, | ||
1056 | elements, | 1144 | elements, |
1057 | NULL, | 1145 | NULL, |
1058 | false, | ||
1059 | 0, | 1146 | 0, |
1060 | GNUNET_PQ_DATATYPE_VARCHAR, | 1147 | array_of_string, |
1061 | db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); | 1148 | db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); |
1062 | } | 1149 | } |
1063 | 1150 | ||
1064 | 1151 | ||
1152 | struct GNUNET_PQ_QueryParam | ||
1153 | GNUNET_PQ_query_param_array_abs_time ( | ||
1154 | unsigned int num, | ||
1155 | const struct GNUNET_TIME_Absolute *elements, | ||
1156 | const struct GNUNET_PQ_Context *db) | ||
1157 | { | ||
1158 | return query_param_array_generic (num, | ||
1159 | true, | ||
1160 | elements, | ||
1161 | NULL, | ||
1162 | sizeof(struct GNUNET_TIME_Absolute), | ||
1163 | array_of_abs_time, | ||
1164 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1165 | } | ||
1166 | |||
1167 | |||
1168 | struct GNUNET_PQ_QueryParam | ||
1169 | GNUNET_PQ_query_param_array_ptrs_abs_time ( | ||
1170 | unsigned int num, | ||
1171 | const struct GNUNET_TIME_Absolute *elements[], | ||
1172 | const struct GNUNET_PQ_Context *db) | ||
1173 | { | ||
1174 | return query_param_array_generic (num, | ||
1175 | false, | ||
1176 | elements, | ||
1177 | NULL, | ||
1178 | sizeof(struct GNUNET_TIME_Absolute), | ||
1179 | array_of_abs_time, | ||
1180 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1181 | } | ||
1182 | |||
1183 | |||
1184 | struct GNUNET_PQ_QueryParam | ||
1185 | GNUNET_PQ_query_param_array_rel_time ( | ||
1186 | unsigned int num, | ||
1187 | const struct GNUNET_TIME_Relative *elements, | ||
1188 | const struct GNUNET_PQ_Context *db) | ||
1189 | { | ||
1190 | return query_param_array_generic (num, | ||
1191 | true, | ||
1192 | elements, | ||
1193 | NULL, | ||
1194 | sizeof(struct GNUNET_TIME_Relative), | ||
1195 | array_of_abs_time, | ||
1196 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1197 | } | ||
1198 | |||
1199 | |||
1200 | struct GNUNET_PQ_QueryParam | ||
1201 | GNUNET_PQ_query_param_array_ptrs_rel_time ( | ||
1202 | unsigned int num, | ||
1203 | const struct GNUNET_TIME_Relative *elements[], | ||
1204 | const struct GNUNET_PQ_Context *db) | ||
1205 | { | ||
1206 | return query_param_array_generic (num, | ||
1207 | false, | ||
1208 | elements, | ||
1209 | NULL, | ||
1210 | sizeof(struct GNUNET_TIME_Relative), | ||
1211 | array_of_abs_time, | ||
1212 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1213 | } | ||
1214 | |||
1215 | |||
1216 | struct GNUNET_PQ_QueryParam | ||
1217 | GNUNET_PQ_query_param_array_timestamp ( | ||
1218 | unsigned int num, | ||
1219 | const struct GNUNET_TIME_Timestamp *elements, | ||
1220 | const struct GNUNET_PQ_Context *db) | ||
1221 | { | ||
1222 | return query_param_array_generic (num, | ||
1223 | true, | ||
1224 | elements, | ||
1225 | NULL, | ||
1226 | sizeof(struct GNUNET_TIME_Timestamp), | ||
1227 | array_of_timestamp, | ||
1228 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1229 | } | ||
1230 | |||
1231 | |||
1232 | struct GNUNET_PQ_QueryParam | ||
1233 | GNUNET_PQ_query_param_array_ptrs_timestamp ( | ||
1234 | unsigned int num, | ||
1235 | const struct GNUNET_TIME_Timestamp *elements[], | ||
1236 | const struct GNUNET_PQ_Context *db) | ||
1237 | { | ||
1238 | return query_param_array_generic (num, | ||
1239 | false, | ||
1240 | elements, | ||
1241 | NULL, | ||
1242 | sizeof(struct GNUNET_TIME_Timestamp), | ||
1243 | array_of_timestamp, | ||
1244 | db->oids[GNUNET_PQ_DATATYPE_INT8]); | ||
1245 | } | ||
1246 | |||
1247 | |||
1065 | /* end of pq_query_helper.c */ | 1248 | /* end of pq_query_helper.c */ |