diff --git a/src/db_column.c b/src/db_column.c index a9dd104..ad15d6c 100644 --- a/src/db_column.c +++ b/src/db_column.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include @@ -9,6 +9,7 @@ #include "strext.h" +// PRIVATE size_t columnTypeToByteSize(e_column_type type) { switch(type) { @@ -52,7 +53,6 @@ size_t columnTypeToByteSize(e_column_type type) } return sizeof(char *); } - e_column_type simplifyFieldType(enum enum_field_types sql_type, int is_unsigned) { switch(sql_type) { @@ -115,6 +115,7 @@ e_column_type simplifyFieldType(enum enum_field_types sql_type, int is_unsigned) } +// PUBLIC struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const char *name, size_t name_len, const char *table, size_t table_len) { @@ -150,8 +151,8 @@ struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const ch col->n_values = 0; col->hasPointers = col->type == TYPE_STRING - || col->type == TYPE_BLOB - || col->type == TYPE_RAW; + || col->type == TYPE_BLOB + || col->type == TYPE_RAW; col->isUnsigned = col->type == TYPE_UINT8 || col->type == TYPE_UINT16 || col->type == TYPE_UINT32 @@ -163,9 +164,8 @@ struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const ch return col; } - -struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result, - uint64_t num_rows) +struct column_data_t *createColumnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result, + uint64_t num_rows) { MYSQL_FIELD *field; struct column_data_t *col; @@ -173,9 +173,9 @@ struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *r field = mysql_fetch_field(result); if (field == NULL) { fprintf( - stderr, "[%d]mysql_fetch_field: (%d) %s\n", - __LINE__, mysql_errno(SQCONN(sconn)), mysql_error(SQCONN(sconn)) - ); + stderr, "[%d]mysql_fetch_field: (%d) %s\n", + __LINE__, mysql_errno(SQCONN(sconn)), mysql_error(SQCONN(sconn)) + ); return 0; } @@ -290,8 +290,8 @@ void freeColumns(struct column_data_t **col_data, size_t n_cols) free(col_data); } - -int setColumnValue(struct column_data_t *col, uint64_t row, const char *value, size_t value_size) +int setColumnValueFromResult(struct column_data_t *col, uint64_t row, + const char *value, size_t value_size) { if (value == NULL) { columnRowSetNull(col, row); @@ -401,7 +401,8 @@ int setColumnValue(struct column_data_t *col, uint64_t row, const char *value, s return 0; } -struct column_data_t *findColumn(struct column_data_t **col_data, size_t n_cols, const char *name) +struct column_data_t *findColumnByName(struct column_data_t **col_data, size_t n_cols, + const char *name) { struct column_data_t *col = 0; size_t idx = 0; @@ -418,25 +419,105 @@ struct column_data_t *findColumn(struct column_data_t **col_data, size_t n_cols, return 0; } -char *createColumn(struct column_data_t *col, char **str, size_t *len) + +int columnRowIsNull(struct column_data_t *col, uint64_t row) +{ + return col->isNullable && (*(col->nulls + (row / 8)) & (1 << (row % 8))) > 0; +} +void columnRowSetNull(struct column_data_t *col, uint64_t row) +{ + if (col->isNullable) { + *(col->nulls + (row / 8)) |= (1 << (row % 8)); + } +} +void columnRowClearNull(struct column_data_t *col, uint64_t row) +{ + if (col->isNullable) { + *(col->nulls + (row / 8)) &= ~(1 << (row % 8)); + } +} + + +char *escapeColumnName(char **str, size_t *len, + const char *table, size_t table_len, const char *col, size_t col_len) { str_builder *sb; if ((sb = strbld_create()) == 0) { return 0; } - createColumn_sb(sb, col); + escapeColumnName_sb(sb, table, table_len, col, col_len); if (strbld_finalize_or_destroy(&sb, str, len) != 0) { return 0; } return *str; } -void createColumn_sb(str_builder *sb, struct column_data_t *col) +void escapeColumnName_sb(str_builder *sb, + const char *table, size_t table_len, const char *col, size_t col_len) { - strbld_str(sb, ", `", 3); - strbld_str(sb, col->name, col->name_len); - strbld_str(sb, "` ", 2); + if (table != 0) { + strbld_char(sb,'`'); + strbld_str(sb, table, table_len); + strbld_char(sb,'`'); + strbld_char(sb,'.'); + } + strbld_char(sb,'`'); + strbld_str(sb, col, col_len); + strbld_char(sb,'`'); +} + +char *escapeColumnNameAs(char **str, size_t *len, const char *tbl, size_t tbl_len, + const char *col, size_t col_len, const char *as, size_t as_len) +{ + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return 0; + } + escapeColumnNameAs_sb(sb, tbl, tbl_len, col, col_len, as, as_len); + if (strbld_finalize_or_destroy(&sb, str, len) != 0) { + return 0; + } + + return *str; +} +void escapeColumnNameAs_sb(str_builder *sb, const char *tbl, size_t tbl_len, + const char *col, size_t col_len, const char *as, size_t as_len) +{ + escapeColumnName_sb(sb, tbl, tbl_len, col, col_len); + strbld_str(sb, " AS ", 4); + escapeColumnName_sb(sb, 0, 0, as, as_len); +} + +char *escapeTableName(char **str, size_t *len, const char *table, size_t table_len) +{ + return escapeColumnName(str, len, 0, 0, table, table_len); +} +void escapeTableName_sb(str_builder *sb, const char *table, size_t table_len) +{ + escapeColumnName_sb(sb, 0, 0, table, table_len); +} + + +char *columnCreateStr(char **str, size_t *len, struct column_data_t *col) +{ + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return 0; + } + columnCreateStr_sb(sb, col); + if (strbld_finalize_or_destroy(&sb, str, len) != 0) { + return 0; + } + + return *str; +} +void columnCreateStr_sb(str_builder *sb, struct column_data_t *col) +{ + escapeColumnName_sb(sb, 0, 0, col->name, col->name_len); + strbld_char(sb, ' '); switch(col->type) { case TYPE_RAW: @@ -495,3 +576,79 @@ void createColumn_sb(str_builder *sb, struct column_data_t *col) strbld_str(sb, " AUTO_INCREMENT", 0); } } + +char *columnSetValueStr(char **set, size_t *set_len, + const char *column, e_column_type type, uint32_t n_args, ...) +{ + va_list args; + + va_start(args, n_args); + columnSetValueStr_va(set, set_len, column, type, n_args, args); + va_end(args); + + return *set; +} +char *columnSetValueStr_va(char **set, size_t *set_len, + const char *column, e_column_type type, uint32_t n_args, va_list args) +{ + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return 0; + } + columnSetValueStr_sbva(sb, column, type, n_args, args); + if (strbld_finalize_or_destroy(&sb, set, set_len) != 0) { + return 0; + } + + return *set; +} +void columnSetValueStr_sb(str_builder *sb, + const char *column, e_column_type type, uint32_t n_args, ...) +{ + va_list args; + va_start(args, n_args); + columnSetValueStr_sbva(sb, column, type, n_args, args); + va_end(args); +} +void columnSetValueStr_sbva(str_builder *sb, + const char *column, e_column_type type, uint32_t n_args, va_list args) +{ + escapeColumnName_sb(sb, 0, 0, column, 0); + strbld_str(sb, " = ", 0); + db_value_sbva(sb, type, n_args, args); +} + +char *joinStr(char **str, size_t *len, + const char *join_type, size_t join_type_len, int is_equals, + const char *tableA, size_t tableA_len, const char *colA, size_t colA_len, + const char *tableB, size_t tableB_len, const char *colB, size_t colB_len) +{ + str_builder *sb; + + if ((sb = strbld_create()) == 0) { + return 0; + } + joinStr_sb(sb, join_type, join_type_len, is_equals, + tableA, tableA_len, colA, colA_len, + tableB, tableB_len, colB, colB_len); + if (strbld_finalize_or_destroy(&sb, str, len) != 0) { + return 0; + } + + return *str; +} +void joinStr_sb(str_builder *sb, + const char *join_type, size_t join_type_len, int is_equals, + const char *tableA, size_t tableA_len, const char *colA, size_t colA_len, + const char *tableB, size_t tableB_len, const char *colB, size_t colB_len) +{ + strbld_str(sb, join_type, join_type_len); + strbld_str(sb, " JOIN ", 6); + escapeTableName_sb(sb, tableA, tableA_len); + strbld_str(sb, " ON ", 4); + escapeColumnName_sb(sb, tableA, tableA_len, colA, colA_len); + strbld_str(sb, (is_equals ? " = " : " != "), (is_equals ? 3 : 4)); + escapeColumnName_sb(sb, tableB, tableB_len, colB, colB_len); +} + diff --git a/src/db_column.h b/src/db_column.h index e786531..c993cc4 100644 --- a/src/db_column.h +++ b/src/db_column.h @@ -76,39 +76,64 @@ struct column_data_t { typedef struct column_data_t column_data; -// Null column value handling - maybe convert these to macros? -static inline int columnRowIsNull(struct column_data_t *col, uint64_t row) -{ - return col->isNullable && (*(col->nulls + (row / 8)) & (1 << (row % 8))) > 0; -} -static inline void columnRowSetNull(struct column_data_t *col, uint64_t row) -{ - if (col->isNullable) { - *(col->nulls + (row / 8)) |= (1 << (row % 8)); - } -} -static inline void columnRowClearNull(struct column_data_t *col, uint64_t row) -{ - if (col->isNullable) { - *(col->nulls + (row / 8)) &= ~(1 << (row % 8)); - } -} - struct column_data_t *initEmptyColumn(e_column_type type, int nullable, const char *name, size_t name_len, const char *table, size_t table_len); -struct column_data_t *columnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result, - uint64_t num_rows); +struct column_data_t *createColumnFromResult(struct stored_conn_t *sconn, MYSQL_RES *result, + uint64_t num_rows); void freeColumn(struct column_data_t *col); void freeColumns(struct column_data_t **col_data, size_t n_cols); -int setColumnValue(struct column_data_t *col, uint64_t row, const char *value, size_t value_size); +int setColumnValueFromResult(struct column_data_t *col, uint64_t row, + const char *value, size_t value_size); -struct column_data_t *findColumn(struct column_data_t **col_data, size_t n_cols, - const char *name); +struct column_data_t *findColumnByName(struct column_data_t **col_data, size_t n_cols, + const char *name); + +int columnRowIsNull(struct column_data_t *col, uint64_t row); +void columnRowSetNull(struct column_data_t *col, uint64_t row); +void columnRowClearNull(struct column_data_t *col, uint64_t row); -char *createColumn(struct column_data_t *col_data, char **str, size_t *len); -void createColumn_sb(str_builder *sb, struct column_data_t *col); +char *escapeColumnName(char **str, size_t *len, + const char *table, size_t table_len, + const char *column, size_t column_len); +void escapeColumnName_sb(str_builder *sb, + const char *table, size_t table_len, + const char *column, size_t column_len); + +char *escapeColumnNameAs(char **str, size_t *len, + const char *table, size_t table_len, + const char *column, size_t column_len, + const char *as_column, size_t as_column_len); +void escapeColumnNameAs_sb(str_builder *sb, + const char *table, size_t table_len, + const char *column, size_t column_len, + const char *as_column, size_t as_column_len); + +char *escapeTableName(char **str, size_t *len, const char *table, size_t table_len); +void escapeTableName_sb(str_builder *sb, const char *table, size_t table_len); + + +char *columnCreateStr(char **str, size_t *len, struct column_data_t *col); +void columnCreateStr_sb(str_builder *sb, struct column_data_t *col); + +char *columnSetValueStr(char **set, size_t *set_len, + const char *column, e_column_type type, uint32_t n_args, ...); +char *columnSetValueStr_va(char **set, size_t *set_len, + const char *column, e_column_type type, uint32_t n_args, va_list args); +void columnSetValueStr_sb(str_builder *sb, + const char *column, e_column_type type, uint32_t n_args, ...); +void columnSetValueStr_sbva(str_builder *sb, + const char *column, e_column_type type, uint32_t n_args, va_list args); + +char *joinStr(char **str, size_t *len, + const char *join_type, size_t join_type_len, int is_equals, + const char *tableA, size_t tableA_len, const char *colA, size_t colA_len, + const char *tableB, size_t tableB_len, const char *colB, size_t colB_len); +void joinStr_sb(str_builder *sb, + const char *join_type, size_t join_type_len, int is_equals, + const char *tableA, size_t tableA_len, const char *colA, size_t colA_len, + const char *tableB, size_t tableB_len, const char *colB, size_t colB_len); #endif // H__DB_COLUMN__ diff --git a/src/db_query.c b/src/db_query.c index 7d9babb..511b8de 100644 --- a/src/db_query.c +++ b/src/db_query.c @@ -114,7 +114,7 @@ uint64_t tableQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len for (unsigned int i = 0; i < *n_cols; i++) { - *(col_data + i) = columnFromResult(sconn, result, n_rows); + *(col_data + i) = createColumnFromResult(sconn, result, n_rows); if (*(col_data + i) == 0) { failed++; @@ -146,7 +146,7 @@ uint64_t tableQuery(struct stored_conn_t *sconn, const char *qry, size_t qry_len for (unsigned int c = 0; c < *n_cols; c++) { struct column_data_t *col = (*(col_data + c)); - if (setColumnValue(col, r, *(row + c), *(lens + c)) < 0) { + if (setColumnValueFromResult(col, r, *(row + c), *(lens + c)) < 0) { failed++; } } diff --git a/src/db_where-builder.c b/src/db_where-builder.c index 822ad83..864bd04 100644 --- a/src/db_where-builder.c +++ b/src/db_where-builder.c @@ -38,26 +38,8 @@ int compileWhereBuilder(where_builder *wb, char **str, size_t *str_len, int free } void compileWhereBuilder_sb(where_builder *wb, str_builder *sb, int free_wb) { - switch(wb->logic_type) { - case CLAUSE: - { - compileWhere_sb((where_clause *)wb, sb); - break; - } - case OR: - case AND: - { - compileLogic_sb((where_logic *)wb, sb); - break; - } - default: - { - break; - } - } - if (free_wb) { - freeWhereBuilder(&wb); - } + strbld_str(sb, " WHERE ", 7); + do_compileWhereBuilder_sb(wb, sb, free_wb); } void freeWhereBuilder(where_builder **wb_ptr) { diff --git a/src/db_where-builder_p.c b/src/db_where-builder_p.c index 1f683fc..592d4ff 100644 --- a/src/db_where-builder_p.c +++ b/src/db_where-builder_p.c @@ -4,6 +4,29 @@ #include "db_where-builder_p.h" +void do_compileWhereBuilder_sb(where_builder *wb, str_builder *sb, int free_wb) +{ + switch(wb->logic_type) { + case CLAUSE: + { + compileWhere_sb((where_clause *)wb, sb); + break; + } + case OR: + case AND: + { + compileLogic_sb((where_logic *)wb, sb); + break; + } + default: + { + break; + } + } + if (free_wb) { + freeWhereBuilder(&wb); + } +} where_logic *createLogic(e_where_logic type, size_t initial_size) { @@ -32,18 +55,6 @@ where_logic *createLogic(e_where_logic type, size_t initial_size) return logic; } -int compileLogic(where_logic *logic, char **str, size_t *str_len) -{ - struct str_builder_t *sb; - - if ((sb = strbld_create()) == 0) { - return -1; - } - - compileLogic_sb(logic, sb); - - return strbld_finalize_or_destroy(&sb, str, str_len); -} void compileLogic_sb(where_logic *logic, str_builder *sb) { if (logic->n_clauses == 0) { @@ -52,7 +63,7 @@ void compileLogic_sb(where_logic *logic, str_builder *sb) strbld_char(sb, '('); for (size_t i = 0; i < logic->n_clauses; i++) { - compileWhereBuilder_sb(logic->clauses[i], sb, 0); + do_compileWhereBuilder_sb(logic->clauses[i], sb, 0); if (i < (logic->n_clauses - 1)) { if (logic->logic_type == OR) { strbld_str(sb, " OR ", 4); @@ -154,18 +165,6 @@ where_clause *createWhere(const char *tbl, const char *col, e_where_op op) return clause; } -int compileWhere(where_clause *clause, char **str, size_t *str_len) -{ - struct str_builder_t *sb; - - if ((sb = strbld_create()) == 0) { - return -1; - } - - compileWhere_sb(clause, sb); - - return strbld_finalize_or_destroy(&sb, str, str_len); -} void compileWhere_sb(where_clause *clause, str_builder *sb) { size_t idx; diff --git a/src/db_where-builder_p.h b/src/db_where-builder_p.h index 87a5d2b..d548ed0 100644 --- a/src/db_where-builder_p.h +++ b/src/db_where-builder_p.h @@ -50,9 +50,10 @@ struct where_clause_t { typedef struct where_clause_t where_clause; DLL_LOCAL -where_logic *createLogic(e_where_logic type, size_t initial_size); +void do_compileWhereBuilder_sb(where_builder *wb, str_builder *sb, int free_wb); + DLL_LOCAL -int compileLogic(where_logic *logic, char **str, size_t *str_len); +where_logic *createLogic(e_where_logic type, size_t initial_size); DLL_LOCAL void compileLogic_sb(where_logic *logic, str_builder *sb); DLL_LOCAL @@ -64,8 +65,6 @@ where_builder *appendLogicClause(where_builder *wb, where_builder *wb_clause); DLL_LOCAL where_clause *createWhere(const char *tbl, const char *col, e_where_op op); DLL_LOCAL -int compileWhere(where_clause *clause, char **str, size_t *str_len); -DLL_LOCAL void compileWhere_sb(where_clause *clause, str_builder *sb); DLL_LOCAL void freeWhere(where_clause **where_ptr);