trilogy 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);