trilogy 2.4.0 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -12,6 +12,12 @@
12
12
  #define TRILOGY_CMD_PING 0x0e
13
13
  #define TRILOGY_CMD_SET_OPTION 0x1b
14
14
 
15
+ #define TRILOGY_CMD_STMT_PREPARE 0x16
16
+ #define TRILOGY_CMD_STMT_EXECUTE 0x17
17
+ #define TRILOGY_CMD_STMT_SEND_LONG_DATA 0x18
18
+ #define TRILOGY_CMD_STMT_CLOSE 0x19
19
+ #define TRILOGY_CMD_STMT_RESET 0x1a
20
+
15
21
  #define SCRAMBLE_LEN 20
16
22
 
17
23
  static size_t min(size_t a, size_t b)
@@ -395,6 +401,37 @@ fail:
395
401
  return rc;
396
402
  }
397
403
 
404
+ int trilogy_parse_stmt_ok_packet(const uint8_t *buff, size_t len, trilogy_stmt_ok_packet_t *out_packet)
405
+ {
406
+ int rc;
407
+
408
+ trilogy_reader_t reader = TRILOGY_READER(buff, len);
409
+
410
+ // skip packet type
411
+ CHECKED(trilogy_reader_get_uint8(&reader, NULL));
412
+
413
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_packet->id));
414
+
415
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_packet->column_count));
416
+
417
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_packet->parameter_count));
418
+
419
+ uint8_t filler;
420
+
421
+ CHECKED(trilogy_reader_get_uint8(&reader, &filler));
422
+
423
+ if (filler != 0) {
424
+ return TRILOGY_PROTOCOL_VIOLATION;
425
+ }
426
+
427
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_packet->warning_count));
428
+
429
+ return trilogy_reader_finish(&reader);
430
+
431
+ fail:
432
+ return rc;
433
+ }
434
+
398
435
  static void trilogy_pack_scramble_native_hash(const char *scramble, const char *password, size_t password_len,
399
436
  uint8_t *buffer, unsigned int *buffer_len)
400
437
  {
@@ -683,4 +720,470 @@ fail:
683
720
  return rc;
684
721
  }
685
722
 
723
+ int trilogy_build_stmt_prepare_packet(trilogy_builder_t *builder, const char *sql, size_t sql_len)
724
+ {
725
+ int rc = TRILOGY_OK;
726
+
727
+ CHECKED(trilogy_builder_write_uint8(builder, TRILOGY_CMD_STMT_PREPARE));
728
+
729
+ CHECKED(trilogy_builder_write_buffer(builder, sql, sql_len));
730
+
731
+ trilogy_builder_finalize(builder);
732
+
733
+ return TRILOGY_OK;
734
+
735
+ fail:
736
+ return rc;
737
+ }
738
+
739
+ int trilogy_build_stmt_execute_packet(trilogy_builder_t *builder, uint32_t stmt_id, uint8_t flags,
740
+ trilogy_binary_value_t *binds, uint16_t num_binds)
741
+ {
742
+ int rc = TRILOGY_OK;
743
+
744
+ CHECKED(trilogy_builder_write_uint8(builder, TRILOGY_CMD_STMT_EXECUTE));
745
+
746
+ CHECKED(trilogy_builder_write_uint32(builder, stmt_id));
747
+
748
+ CHECKED(trilogy_builder_write_uint8(builder, flags));
749
+
750
+ // apparently, iteration-count is always 1
751
+ CHECKED(trilogy_builder_write_uint32(builder, 1));
752
+
753
+ int i;
754
+
755
+ if (num_binds > 0) {
756
+ if (binds == NULL) {
757
+ return TRILOGY_PROTOCOL_VIOLATION;
758
+ }
759
+
760
+ uint8_t current_bits = 0;
761
+
762
+ for (i = 0; i < num_binds; i++) {
763
+ if (binds[i].is_null) {
764
+ current_bits |= 1 << (i % 8);
765
+ }
766
+
767
+ // If we hit a byte boundary, write the bits we have so far and continue
768
+ if ((i % 8) == 7) {
769
+ CHECKED(trilogy_builder_write_uint8(builder, current_bits))
770
+
771
+ current_bits = 0;
772
+ }
773
+ }
774
+
775
+ // If there would have been any remainder bits, finally write those as well
776
+ if (num_binds % 8) {
777
+ CHECKED(trilogy_builder_write_uint8(builder, current_bits))
778
+ }
779
+
780
+ // new params bound flag
781
+ CHECKED(trilogy_builder_write_uint8(builder, 0x1));
782
+
783
+ for (i = 0; i < num_binds; i++) {
784
+ CHECKED(trilogy_builder_write_uint8(builder, binds[i].type));
785
+
786
+ if (binds[i].is_unsigned) {
787
+ CHECKED(trilogy_builder_write_uint8(builder, 0x80));
788
+ } else {
789
+ CHECKED(trilogy_builder_write_uint8(builder, 0x00));
790
+ }
791
+ }
792
+
793
+ for (i = 0; i < num_binds; i++) {
794
+ trilogy_binary_value_t val = binds[i];
795
+
796
+ switch (val.type) {
797
+ case TRILOGY_TYPE_TINY:
798
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.uint8));
799
+
800
+ break;
801
+ case TRILOGY_TYPE_SHORT:
802
+ CHECKED(trilogy_builder_write_uint16(builder, val.as.uint16));
803
+
804
+ break;
805
+ case TRILOGY_TYPE_INT24:
806
+ case TRILOGY_TYPE_LONG:
807
+ CHECKED(trilogy_builder_write_uint32(builder, val.as.uint32));
808
+
809
+ break;
810
+ case TRILOGY_TYPE_LONGLONG:
811
+ CHECKED(trilogy_builder_write_uint64(builder, val.as.uint64));
812
+
813
+ break;
814
+ case TRILOGY_TYPE_FLOAT:
815
+ CHECKED(trilogy_builder_write_float(builder, val.as.flt));
816
+
817
+ break;
818
+ case TRILOGY_TYPE_DOUBLE:
819
+ CHECKED(trilogy_builder_write_double(builder, val.as.dbl));
820
+
821
+ break;
822
+ case TRILOGY_TYPE_YEAR:
823
+ CHECKED(trilogy_builder_write_uint16(builder, val.as.year));
824
+
825
+ break;
826
+ case TRILOGY_TYPE_TIME: {
827
+ uint8_t field_len = 0;
828
+
829
+ if (val.as.time.micro_seconds) {
830
+ field_len = 12;
831
+ } else if (val.as.time.hour || val.as.time.minute || val.as.time.second) {
832
+ field_len = 8;
833
+ } else {
834
+ field_len = 0;
835
+ }
836
+
837
+ CHECKED(trilogy_builder_write_uint8(builder, field_len));
838
+
839
+ if (field_len > 0) {
840
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.time.is_negative));
841
+
842
+ CHECKED(trilogy_builder_write_uint32(builder, val.as.time.days));
843
+
844
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.time.hour));
845
+
846
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.time.minute));
847
+
848
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.time.second));
849
+
850
+ if (field_len > 8) {
851
+ CHECKED(trilogy_builder_write_uint32(builder, val.as.time.micro_seconds));
852
+ }
853
+ }
854
+
855
+ break;
856
+ }
857
+ case TRILOGY_TYPE_DATE:
858
+ case TRILOGY_TYPE_DATETIME:
859
+ case TRILOGY_TYPE_TIMESTAMP: {
860
+ uint8_t field_len = 0;
861
+
862
+ if (val.as.date.datetime.micro_seconds) {
863
+ field_len = 11;
864
+ } else if (val.as.date.datetime.hour || val.as.date.datetime.minute || val.as.date.datetime.second) {
865
+ field_len = 7;
866
+ } else if (val.as.date.year || val.as.date.month || val.as.date.day) {
867
+ field_len = 4;
868
+ } else {
869
+ field_len = 0;
870
+ }
871
+
872
+ CHECKED(trilogy_builder_write_uint8(builder, field_len));
873
+
874
+ if (field_len > 0) {
875
+ CHECKED(trilogy_builder_write_uint16(builder, val.as.date.year));
876
+
877
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.date.month));
878
+
879
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.date.day));
880
+
881
+ if (field_len > 4) {
882
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.date.datetime.hour));
883
+
884
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.date.datetime.minute));
885
+
886
+ CHECKED(trilogy_builder_write_uint8(builder, val.as.date.datetime.second));
887
+
888
+ if (field_len > 7) {
889
+ CHECKED(trilogy_builder_write_uint32(builder, val.as.date.datetime.micro_seconds));
890
+ }
891
+ }
892
+ }
893
+
894
+ break;
895
+ }
896
+ case TRILOGY_TYPE_DECIMAL:
897
+ case TRILOGY_TYPE_VARCHAR:
898
+ case TRILOGY_TYPE_BIT:
899
+ case TRILOGY_TYPE_NEWDECIMAL:
900
+ case TRILOGY_TYPE_ENUM:
901
+ case TRILOGY_TYPE_SET:
902
+ case TRILOGY_TYPE_TINY_BLOB:
903
+ case TRILOGY_TYPE_BLOB:
904
+ case TRILOGY_TYPE_MEDIUM_BLOB:
905
+ case TRILOGY_TYPE_LONG_BLOB:
906
+ case TRILOGY_TYPE_VAR_STRING:
907
+ case TRILOGY_TYPE_STRING:
908
+ case TRILOGY_TYPE_GEOMETRY:
909
+ CHECKED(trilogy_builder_write_lenenc_buffer(builder, val.as.str.data, val.as.str.len));
910
+
911
+ break;
912
+ case TRILOGY_TYPE_NULL:
913
+ // already handled by the null bitmap
914
+ break;
915
+ default:
916
+ return TRILOGY_UNKNOWN_TYPE;
917
+ }
918
+ }
919
+ }
920
+
921
+ trilogy_builder_finalize(builder);
922
+
923
+ return TRILOGY_OK;
924
+
925
+ fail:
926
+ return rc;
927
+ }
928
+
929
+ int trilogy_build_stmt_bind_data_packet(trilogy_builder_t *builder, uint32_t stmt_id, uint16_t param_id, uint8_t *data,
930
+ size_t data_len)
931
+ {
932
+ int rc = TRILOGY_OK;
933
+
934
+ CHECKED(trilogy_builder_write_uint8(builder, TRILOGY_CMD_STMT_SEND_LONG_DATA));
935
+
936
+ CHECKED(trilogy_builder_write_uint32(builder, stmt_id));
937
+
938
+ CHECKED(trilogy_builder_write_uint16(builder, param_id));
939
+
940
+ CHECKED(trilogy_builder_write_buffer(builder, data, data_len));
941
+
942
+ trilogy_builder_finalize(builder);
943
+
944
+ return TRILOGY_OK;
945
+
946
+ fail:
947
+ return rc;
948
+ }
949
+
950
+ int trilogy_build_stmt_reset_packet(trilogy_builder_t *builder, uint32_t stmt_id)
951
+ {
952
+ int rc = TRILOGY_OK;
953
+
954
+ CHECKED(trilogy_builder_write_uint8(builder, TRILOGY_CMD_STMT_RESET));
955
+
956
+ CHECKED(trilogy_builder_write_uint32(builder, stmt_id));
957
+
958
+ trilogy_builder_finalize(builder);
959
+
960
+ return TRILOGY_OK;
961
+
962
+ fail:
963
+ return rc;
964
+ }
965
+
966
+ int trilogy_build_stmt_close_packet(trilogy_builder_t *builder, uint32_t stmt_id)
967
+ {
968
+ int rc = TRILOGY_OK;
969
+
970
+ CHECKED(trilogy_builder_write_uint8(builder, TRILOGY_CMD_STMT_CLOSE));
971
+
972
+ CHECKED(trilogy_builder_write_uint32(builder, stmt_id));
973
+
974
+ trilogy_builder_finalize(builder);
975
+
976
+ return TRILOGY_OK;
977
+
978
+ fail:
979
+ return rc;
980
+ }
981
+
982
+ static inline int is_null(uint8_t *null_bitmap, uint64_t bitmap_len, uint64_t column_offset, bool *col_is_null)
983
+ {
984
+ if (column_offset > (bitmap_len * 8) - 1) {
985
+ return TRILOGY_PROTOCOL_VIOLATION;
986
+ }
987
+
988
+ column_offset += 2;
989
+
990
+ uint64_t byte_offset = column_offset / 8;
991
+
992
+ // for the binary protocol result row packet, we need to offset the bit check
993
+ // by 2
994
+ *col_is_null = (null_bitmap[byte_offset] & (1 << (column_offset % 8))) != 0;
995
+
996
+ return TRILOGY_OK;
997
+ }
998
+
999
+ int trilogy_parse_stmt_row_packet(const uint8_t *buff, size_t len, trilogy_column_packet_t *columns,
1000
+ uint64_t column_count, trilogy_binary_value_t *out_values)
1001
+ {
1002
+ int rc;
1003
+
1004
+ trilogy_reader_t reader = TRILOGY_READER(buff, len);
1005
+
1006
+ // skip packet header
1007
+ CHECKED(trilogy_reader_get_uint8(&reader, NULL));
1008
+
1009
+ uint8_t *null_bitmap = NULL;
1010
+ uint64_t bitmap_len = (column_count + 7 + 2) / 8;
1011
+
1012
+ CHECKED(trilogy_reader_get_buffer(&reader, bitmap_len, (const void **)&null_bitmap));
1013
+
1014
+ for (uint64_t i = 0; i < column_count; i++) {
1015
+ CHECKED(is_null(null_bitmap, bitmap_len, i, &out_values[i].is_null));
1016
+ if (out_values[i].is_null) {
1017
+ out_values[i].type = TRILOGY_TYPE_NULL;
1018
+ } else {
1019
+ out_values[i].is_null = false;
1020
+
1021
+ out_values[i].type = columns[i].type;
1022
+
1023
+ if (columns[i].flags & TRILOGY_COLUMN_FLAG_UNSIGNED) {
1024
+ out_values[i].is_unsigned = true;
1025
+ }
1026
+
1027
+ switch (columns[i].type) {
1028
+ case TRILOGY_TYPE_STRING:
1029
+ case TRILOGY_TYPE_VARCHAR:
1030
+ case TRILOGY_TYPE_VAR_STRING:
1031
+ case TRILOGY_TYPE_ENUM:
1032
+ case TRILOGY_TYPE_SET:
1033
+ case TRILOGY_TYPE_LONG_BLOB:
1034
+ case TRILOGY_TYPE_MEDIUM_BLOB:
1035
+ case TRILOGY_TYPE_BLOB:
1036
+ case TRILOGY_TYPE_TINY_BLOB:
1037
+ case TRILOGY_TYPE_GEOMETRY:
1038
+ case TRILOGY_TYPE_BIT:
1039
+ case TRILOGY_TYPE_DECIMAL:
1040
+ case TRILOGY_TYPE_NEWDECIMAL:
1041
+ case TRILOGY_TYPE_JSON:
1042
+ CHECKED(trilogy_reader_get_lenenc_buffer(&reader, &out_values[i].as.str.len,
1043
+ (const void **)&out_values[i].as.str.data));
1044
+
1045
+ break;
1046
+ case TRILOGY_TYPE_LONGLONG:
1047
+ CHECKED(trilogy_reader_get_uint64(&reader, &out_values[i].as.uint64));
1048
+
1049
+ break;
1050
+ case TRILOGY_TYPE_DOUBLE:
1051
+ CHECKED(trilogy_reader_get_double(&reader, &out_values[i].as.dbl));
1052
+
1053
+ break;
1054
+ case TRILOGY_TYPE_LONG:
1055
+ case TRILOGY_TYPE_INT24:
1056
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_values[i].as.uint32));
1057
+
1058
+ break;
1059
+ case TRILOGY_TYPE_FLOAT:
1060
+ CHECKED(trilogy_reader_get_float(&reader, &out_values[i].as.flt));
1061
+
1062
+ break;
1063
+ case TRILOGY_TYPE_SHORT:
1064
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_values[i].as.uint16));
1065
+
1066
+ break;
1067
+ case TRILOGY_TYPE_YEAR:
1068
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_values[i].as.year));
1069
+
1070
+ break;
1071
+ case TRILOGY_TYPE_TINY:
1072
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.uint8));
1073
+
1074
+ break;
1075
+ case TRILOGY_TYPE_DATE:
1076
+ case TRILOGY_TYPE_DATETIME:
1077
+ case TRILOGY_TYPE_TIMESTAMP: {
1078
+ uint8_t time_len;
1079
+
1080
+ CHECKED(trilogy_reader_get_uint8(&reader, &time_len));
1081
+
1082
+ out_values[i].as.date.year = 0;
1083
+ out_values[i].as.date.month = 0;
1084
+ out_values[i].as.date.day = 0;
1085
+ out_values[i].as.date.datetime.hour = 0;
1086
+ out_values[i].as.date.datetime.minute = 0;
1087
+ out_values[i].as.date.datetime.second = 0;
1088
+ out_values[i].as.date.datetime.micro_seconds = 0;
1089
+
1090
+ switch (time_len) {
1091
+ case 0:
1092
+ break;
1093
+ case 4:
1094
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_values[i].as.date.year));
1095
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.month));
1096
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.day));
1097
+
1098
+ break;
1099
+ case 7:
1100
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_values[i].as.date.year));
1101
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.month));
1102
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.day));
1103
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.hour));
1104
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.minute));
1105
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.second));
1106
+
1107
+ break;
1108
+ case 11:
1109
+ CHECKED(trilogy_reader_get_uint16(&reader, &out_values[i].as.date.year));
1110
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.month));
1111
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.day));
1112
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.hour));
1113
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.minute));
1114
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.date.datetime.second));
1115
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_values[i].as.date.datetime.micro_seconds));
1116
+
1117
+ break;
1118
+ default:
1119
+ return TRILOGY_PROTOCOL_VIOLATION;
1120
+ }
1121
+
1122
+ break;
1123
+ }
1124
+ case TRILOGY_TYPE_TIME: {
1125
+ uint8_t time_len;
1126
+
1127
+ CHECKED(trilogy_reader_get_uint8(&reader, &time_len));
1128
+
1129
+ out_values[i].as.time.is_negative = false;
1130
+ out_values[i].as.time.days = 0;
1131
+ out_values[i].as.time.hour = 0;
1132
+ out_values[i].as.time.minute = 0;
1133
+ out_values[i].as.time.second = 0;
1134
+ out_values[i].as.time.micro_seconds = 0;
1135
+
1136
+ switch (time_len) {
1137
+ case 0:
1138
+ break;
1139
+ case 8: {
1140
+ uint8_t is_negative;
1141
+
1142
+ CHECKED(trilogy_reader_get_uint8(&reader, &is_negative));
1143
+
1144
+ out_values[i].as.time.is_negative = is_negative == 1;
1145
+
1146
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_values[i].as.time.days));
1147
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.hour));
1148
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.minute));
1149
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.second));
1150
+
1151
+ break;
1152
+ }
1153
+ case 12: {
1154
+ uint8_t is_negative;
1155
+
1156
+ CHECKED(trilogy_reader_get_uint8(&reader, &is_negative));
1157
+
1158
+ out_values[i].as.time.is_negative = is_negative == 1;
1159
+
1160
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_values[i].as.time.days));
1161
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.hour));
1162
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.minute));
1163
+ CHECKED(trilogy_reader_get_uint8(&reader, &out_values[i].as.time.second));
1164
+ CHECKED(trilogy_reader_get_uint32(&reader, &out_values[i].as.time.micro_seconds));
1165
+
1166
+ break;
1167
+ }
1168
+ default:
1169
+ return TRILOGY_PROTOCOL_VIOLATION;
1170
+ }
1171
+
1172
+ break;
1173
+ }
1174
+ case TRILOGY_TYPE_NULL:
1175
+ default:
1176
+ // we cover TRILOGY_TYPE_NULL here because we should never hit this case
1177
+ // explicitly as it should be covered in the null bitmap
1178
+ return TRILOGY_UNKNOWN_TYPE;
1179
+ }
1180
+ }
1181
+ }
1182
+
1183
+ return trilogy_reader_finish(&reader);
1184
+
1185
+ fail:
1186
+ return rc;
1187
+ }
1188
+
686
1189
  #undef CHECKED
@@ -95,6 +95,44 @@ int trilogy_reader_get_uint64(trilogy_reader_t *reader, uint64_t *out)
95
95
  return TRILOGY_OK;
96
96
  }
97
97
 
98
+ int trilogy_reader_get_float(trilogy_reader_t *reader, float *out)
99
+ {
100
+ CHECK(4);
101
+
102
+ union {
103
+ float f;
104
+ uint32_t u;
105
+ } float_val;
106
+
107
+ int rc = trilogy_reader_get_uint32(reader, &float_val.u);
108
+ if (rc != TRILOGY_OK) {
109
+ return rc;
110
+ }
111
+
112
+ *out = float_val.f;
113
+
114
+ return TRILOGY_OK;
115
+ }
116
+
117
+ int trilogy_reader_get_double(trilogy_reader_t *reader, double *out)
118
+ {
119
+ CHECK(8);
120
+
121
+ union {
122
+ double d;
123
+ uint64_t u;
124
+ } double_val;
125
+
126
+ int rc = trilogy_reader_get_uint64(reader, &double_val.u);
127
+ if (rc != TRILOGY_OK) {
128
+ return rc;
129
+ }
130
+
131
+ *out = double_val.d;
132
+
133
+ return TRILOGY_OK;
134
+ }
135
+
98
136
  int trilogy_reader_get_lenenc(trilogy_reader_t *reader, uint64_t *out)
99
137
  {
100
138
  CHECK(1);