read_table.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #include "pg_compat.h"
  2. extern "C" {
  3. #include "postgres.h"
  4. #include "yql/read_table.h"
  5. }
  6. #include <yql/essentials/parser/pg_catalog/catalog.h>
  7. struct yql_table_iterator {
  8. const TVector<TMaybe<TString>>* Data;
  9. char* Error;
  10. size_t NumColumns;
  11. size_t* ColumnsRemap;
  12. size_t Pos;
  13. size_t RowStep;
  14. };
  15. extern "C" struct yql_table_iterator* yql_read_table(const char* name, int num_columns, const char* columns[]) {
  16. yql_table_iterator* res = (yql_table_iterator*)palloc(sizeof(yql_table_iterator));
  17. Zero(*res);
  18. if (!name || num_columns < 0 || !columns) {
  19. res->Error = pstrdup("bad arguments");
  20. return res;
  21. }
  22. TString fullName = name;
  23. auto pos = fullName.find('.');
  24. if (pos == TString::npos) {
  25. res->Error = pstrdup("expected full table name");
  26. return res;
  27. }
  28. auto schema = fullName.substr(0, pos);
  29. auto table = fullName.substr(pos + 1);
  30. res->NumColumns = num_columns;
  31. res->Pos = 0;
  32. if (num_columns) {
  33. res->ColumnsRemap = (size_t*)palloc(sizeof(size_t) * res->NumColumns);
  34. }
  35. TVector<TString> columnNames(res->NumColumns);
  36. for (size_t i = 0; i < res->NumColumns; ++i) {
  37. columnNames[i] = columns[i];
  38. }
  39. try {
  40. res->Data = NYql::NPg::ReadTable(NYql::NPg::TTableInfoKey{schema, table}, columnNames, res->ColumnsRemap, res->RowStep);
  41. } catch (yexception& e) {
  42. res->Error = pstrdup(e.what());
  43. }
  44. return res;
  45. }
  46. extern "C" const char* yql_iterator_error(struct yql_table_iterator* iterator) {
  47. if (!iterator) {
  48. return nullptr;
  49. }
  50. return iterator->Error;
  51. }
  52. extern "C" bool yql_iterator_has_data(struct yql_table_iterator* iterator) {
  53. if (!iterator || !iterator->Data) {
  54. return false;
  55. }
  56. return iterator->Pos < iterator->Data->size();
  57. }
  58. extern "C" bool yql_iterator_value(struct yql_table_iterator* iterator, int column_index, const char** value) {
  59. if (!iterator || !iterator->Data || !value) {
  60. return false;
  61. }
  62. if (column_index < 0 || column_index >= iterator->NumColumns) {
  63. return false;
  64. }
  65. const auto& cell = (*iterator->Data)[iterator->Pos + iterator->ColumnsRemap[column_index]];
  66. if (!cell) {
  67. *value = nullptr;
  68. return true;
  69. }
  70. *value = cell.GetRef().c_str();
  71. return true;
  72. }
  73. extern "C" void yql_iterator_move(struct yql_table_iterator* iterator) {
  74. if (!iterator || !iterator->Data) {
  75. return;
  76. }
  77. if (iterator->Pos < iterator->Data->size()) {
  78. iterator->Pos += iterator->RowStep;
  79. }
  80. }
  81. extern "C" void yql_iterator_close(struct yql_table_iterator** iterator) {
  82. if (!iterator || !*iterator) {
  83. return;
  84. }
  85. if ((*iterator)->ColumnsRemap) {
  86. pfree((*iterator)->ColumnsRemap);
  87. }
  88. if ((*iterator)->Error) {
  89. pfree((*iterator)->Error);
  90. }
  91. pfree(*iterator);
  92. *iterator = nullptr;
  93. }
  94. extern "C" ui64 TouchReadTableApi() {
  95. return
  96. (ui64)&yql_read_table +
  97. (ui64)&yql_iterator_error +
  98. (ui64)&yql_iterator_has_data +
  99. (ui64)&yql_iterator_value +
  100. (ui64)&yql_iterator_move +
  101. (ui64)&yql_iterator_close;
  102. }