diff --git a/vlib/mssql/README.md b/vlib/mssql/README.md deleted file mode 100644 index 41baf2fa41..0000000000 --- a/vlib/mssql/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# SQL Server ODBC - -The `mssql` module has been moved to `db.mssql`. -Update your code to do: `import db.mssql` instead. diff --git a/vlib/mssql/_cdef_nix.c.v b/vlib/mssql/_cdef_nix.c.v deleted file mode 100644 index 0a9ec00ea9..0000000000 --- a/vlib/mssql/_cdef_nix.c.v +++ /dev/null @@ -1,6 +0,0 @@ -module mssql - -#flag -lodbc - -#include -#include diff --git a/vlib/mssql/_cdef_windows.c.v b/vlib/mssql/_cdef_windows.c.v deleted file mode 100644 index 61724eecc0..0000000000 --- a/vlib/mssql/_cdef_windows.c.v +++ /dev/null @@ -1,12 +0,0 @@ -module mssql - -// mssql module does not support tcc on windows - -// odbc32 lib comes with windows sdk and does not need to be installed separately. -// v builder for msvc can resolve the sdk includes search path, so no need to repeat here. -#flag windows -lodbc32 - -// Special handling of sql headers on windows. -// Source is in v third party folder. -#flag windows -I@VEXEROOT/thirdparty/mssql/include -#include diff --git a/vlib/mssql/_cdefs.c.v b/vlib/mssql/_cdefs.c.v deleted file mode 100644 index 7ce0d08da6..0000000000 --- a/vlib/mssql/_cdefs.c.v +++ /dev/null @@ -1,27 +0,0 @@ -module mssql - -fn C.SQLAllocHandle(handle_type C.SQLSMALLINT, input_handle C.SQLHANDLE, output_handle &C.SQLHANDLE) C.SQLRETURN - -fn C.SQLSetEnvAttr(environment_handle C.SQLHENV, attribute C.SQLINTEGER, value C.SQLPOINTER, string_length C.SQLINTEGER) C.SQLRETURN - -fn C.SQLGetDiagRec(handle_type C.SQLSMALLINT, handle C.SQLHANDLE, rec_number C.SQLSMALLINT, sql_state &C.SQLCHAR, native_error &C.SQLINTEGER, message_text &C.SQLCHAR, buffer_length C.SQLSMALLINT, text_length &C.SQLSMALLINT) C.SQLRETURN - -fn C.SQLSetConnectAttr(connection_handle C.SQLHDBC, attribute C.SQLINTEGER, value C.SQLPOINTER, string_length C.SQLINTEGER) C.SQLRETURN - -fn C.SQLDriverConnect(hdbc C.SQLHDBC, hwnd C.SQLHWND, sz_conn_str_in &C.SQLCHAR, cb_conn_str_in C.SQLSMALLINT, sz_conn_str_out &C.SQLCHAR, cb_conn_str_out_max C.SQLSMALLINT, pcb_conn_str_out &C.SQLSMALLINT, f_driver_completion C.SQLUSMALLINT) C.SQLRETURN - -fn C.SQLDisconnect(connection_handle C.SQLHDBC) C.SQLRETURN - -fn C.SQLExecDirect(statement_handle C.SQLHSTMT, statement_text &C.SQLCHAR, text_length C.SQLINTEGER) C.SQLRETURN - -fn C.SQLBindCol(statement_handle C.SQLHSTMT, column_number C.SQLUSMALLINT, target_type C.SQLSMALLINT, target_value C.SQLPOINTER, buffer_length C.SQLLEN, str_len_or_ind &C.SQLLEN) C.SQLRETURN - -fn C.SQLFetch(statement_handle C.SQLHSTMT) C.SQLRETURN - -fn C.SQLFreeHandle(handle_type C.SQLSMALLINT, handle C.SQLHANDLE) C.SQLRETURN - -fn C.SQLNumResultCols(statement_handle C.SQLHSTMT, column_count &C.SQLSMALLINT) C.SQLRETURN - -fn C.SQLColAttribute(statement_handle C.SQLHSTMT, column_number C.SQLUSMALLINT, field_identifier C.SQLUSMALLINT, character_attribute C.SQLPOINTER, buffer_length C.SQLSMALLINT, string_length C.SQLSMALLINT, numeric_attribute &C.SQLLEN) C.SQLRETURN - -fn C.SQLRowCount(statement_handle C.SQLHSTMT, row_count &C.SQLLEN) C.SQLRETURN diff --git a/vlib/mssql/config.v b/vlib/mssql/config.v deleted file mode 100644 index 5f02645466..0000000000 --- a/vlib/mssql/config.v +++ /dev/null @@ -1,20 +0,0 @@ -module mssql - -pub struct Config { -pub: - driver string - server string - uid string - pwd string - // if dbname empty, conn str will not contain Database info, - // and it is up to the server to choose which db to connect to. - dbname string -} - -pub fn (cfg Config) get_conn_str() string { - mut str := 'Driver=${cfg.driver};Server=${cfg.server};UID=${cfg.uid};PWD=${cfg.pwd}' - if cfg.dbname != '' { - str += ';Database=${cfg.dbname}' - } - return str -} diff --git a/vlib/mssql/mssql.v b/vlib/mssql/mssql.v deleted file mode 100644 index f0d9ea3c64..0000000000 --- a/vlib/mssql/mssql.v +++ /dev/null @@ -1,125 +0,0 @@ -module mssql - -pub struct Connection { -mut: - henv C.SQLHENV = C.SQLHENV(C.SQL_NULL_HENV) // Environment - hdbc C.SQLHDBC = C.SQLHDBC(C.SQL_NULL_HDBC) // Connection handle -pub mut: - conn_str string -} - -// connect to db -pub fn (mut conn Connection) connect(conn_str string) !bool { - conn_str_c := unsafe { &C.SQLCHAR(conn_str.str) } - mut retcode := C.SQLRETURN(C.SQL_SUCCESS) - // Allocate environment handle - retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_ENV), C.SQLHANDLE(C.SQL_NULL_HANDLE), - unsafe { &C.SQLHANDLE(&conn.henv) }) - check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_ENV)', C.SQLHANDLE(conn.henv), C.SQLSMALLINT(C.SQL_HANDLE_ENV))! - - // Set the ODBC version environment attribute - retcode = C.SQLSetEnvAttr(conn.henv, C.SQLINTEGER(C.SQL_ATTR_ODBC_VERSION), &C.SQLPOINTER(C.SQL_OV_ODBC3), - C.SQLINTEGER(0)) - check_error(retcode, 'SQLSetEnvAttr(SQL_ATTR_ODBC_VERSION)', C.SQLHANDLE(conn.henv), - C.SQLSMALLINT(C.SQL_HANDLE_ENV))! - - // Allocate connection handle - retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_DBC), C.SQLHANDLE(conn.henv), - unsafe { &C.SQLHANDLE(&conn.hdbc) }) - check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_DBC)', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))! - - // Set login timeout to 5 seconds - retcode = C.SQLSetConnectAttr(conn.hdbc, C.SQLINTEGER(C.SQL_LOGIN_TIMEOUT), C.SQLPOINTER(5), - C.SQLINTEGER(0)) - check_error(retcode, 'SQLSetConnectAttr(SQL_LOGIN_TIMEOUT)', C.SQLHANDLE(conn.hdbc), - C.SQLSMALLINT(C.SQL_HANDLE_DBC))! - - // Connect to data source - mut outstr := [1024]char{} - mut outstrlen := C.SQLSMALLINT(0) - retcode = C.SQLDriverConnect(conn.hdbc, C.SQLHWND(0), conn_str_c, C.SQLSMALLINT(C.SQL_NTS), - &C.SQLCHAR(&outstr[0]), C.SQLSMALLINT(sizeof(outstr)), &outstrlen, C.SQLUSMALLINT(C.SQL_DRIVER_NOPROMPT)) - check_error(retcode, 'SQLDriverConnect()', C.SQLHANDLE(conn.hdbc), C.SQLSMALLINT(C.SQL_HANDLE_DBC))! - conn.conn_str = conn_str - return true -} - -// close - closes the connection. -pub fn (mut conn Connection) close() { - // Connection - if conn.hdbc != C.SQLHDBC(C.SQL_NULL_HDBC) { - C.SQLDisconnect(conn.hdbc) - C.SQLFreeHandle(C.SQLSMALLINT(C.SQL_HANDLE_DBC), C.SQLHANDLE(conn.hdbc)) - conn.hdbc = C.SQLHDBC(C.SQL_NULL_HDBC) - } - // Environment - if conn.henv != C.SQLHENV(C.SQL_NULL_HENV) { - C.SQLFreeHandle(C.SQLSMALLINT(C.SQL_HANDLE_ENV), C.SQLHANDLE(conn.henv)) - conn.henv = C.SQLHENV(C.SQL_NULL_HENV) - } -} - -// query executes a sql query -pub fn (mut conn Connection) query(q string) !Result { - mut hstmt := new_hstmt(conn.hdbc)! - defer { - hstmt.close() - } - - hstmt.exec(q)! - - affected := hstmt.retrieve_affected_rows()! - - hstmt.prepare_read()! - raw_rows := hstmt.read_rows()! - - mut res := Result{ - rows: []Row{} - num_rows_affected: affected - } - - for rr in raw_rows { - res.rows << Row{ - vals: rr - } - } - - return res -} - -// check_error checks odbc return code and extract error string if available -fn check_error(e C.SQLRETURN, s string, h C.SQLHANDLE, t C.SQLSMALLINT) ! { - if e != C.SQLRETURN(C.SQL_SUCCESS) && e != C.SQLRETURN(C.SQL_SUCCESS_WITH_INFO) { - err_str := extract_error(s, h, t) - return error(err_str) - } -} - -// extract_error extracts error string from odbc -fn extract_error(fnName string, handle C.SQLHANDLE, tp C.SQLSMALLINT) string { - mut err_str := fnName - mut i := 0 - mut native_error := C.SQLINTEGER(0) - mut sql_state := [7]char{} - mut message_text := [256]char{} - mut text_length := C.SQLSMALLINT(0) - mut ret := C.SQLRETURN(C.SQL_SUCCESS) - - for ret == C.SQLRETURN(C.SQL_SUCCESS) { - i++ - ret = C.SQLGetDiagRec(tp, handle, C.SQLSMALLINT(i), &C.SQLCHAR(&sql_state[0]), - &native_error, &C.SQLCHAR(&message_text[0]), C.SQLSMALLINT(sizeof(message_text)), - &text_length) - - // add driver error string - if ret == C.SQLRETURN(C.SQL_SUCCESS) || ret == C.SQLRETURN(C.SQL_SUCCESS_WITH_INFO) { - unsafe { - state_str := (&sql_state[0]).vstring() - native_error_code := int(native_error) - txt_str := (&message_text[0]).vstring() - err_str += '\n\todbc=${state_str}:${i}:${native_error_code}:${txt_str}' - } - } - } - return err_str -} diff --git a/vlib/mssql/result.v b/vlib/mssql/result.v deleted file mode 100644 index f5483a2858..0000000000 --- a/vlib/mssql/result.v +++ /dev/null @@ -1,13 +0,0 @@ -module mssql - -pub struct Row { -pub mut: - vals []string -} - -pub struct Result { -pub mut: - rows []Row - // the number of rows affected by sql statement - num_rows_affected int -} diff --git a/vlib/mssql/stmt_handle.v b/vlib/mssql/stmt_handle.v deleted file mode 100644 index e229c8aca1..0000000000 --- a/vlib/mssql/stmt_handle.v +++ /dev/null @@ -1,127 +0,0 @@ -module mssql - -// HStmt is handle for sql statement -struct HStmt { -mut: - // db connection reference. Owner is Connection struct. - hdbc C.SQLHDBC = C.SQLHDBC(C.SQL_NULL_HDBC) - // statement handle - hstmt C.SQLHSTMT = C.SQLHSTMT(C.SQL_NULL_HSTMT) - // fields used for computation - column_count int = -1 - // columns - buffers [][]char - // indicators for each column - indicators []C.SQLLEN -} - -// new_hstmt constructs a new statement handle -fn new_hstmt(hdbc C.SQLHDBC) !HStmt { - mut retcode := C.SQLRETURN(C.SQL_SUCCESS) - mut hstmt := C.SQLHSTMT(C.SQL_NULL_HSTMT) - // Allocate statement handle - retcode = C.SQLAllocHandle(C.SQLSMALLINT(C.SQL_HANDLE_STMT), C.SQLHANDLE(hdbc), unsafe { &C.SQLHANDLE(&hstmt) }) - check_error(retcode, 'SQLAllocHandle(SQL_HANDLE_STMT)', C.SQLHANDLE(hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - - return HStmt{ - hdbc: hdbc - hstmt: hstmt - } -} - -// close the statement handle -fn (mut h HStmt) close() { - // Deallocate handle - if h.hstmt != C.SQLHSTMT(C.SQL_NULL_HSTMT) { - // check error code? - C.SQLFreeHandle(C.SQLSMALLINT(C.SQL_HANDLE_STMT), C.SQLHANDLE(h.hstmt)) - h.hstmt = C.SQLHSTMT(C.SQL_NULL_HSTMT) - } -} - -// exec executes a Sql statement. Result is stored in odbc driver, and not yet read. -fn (h HStmt) exec(sql string) ! { - retcode := C.SQLExecDirect(h.hstmt, sql.str, C.SQLINTEGER(C.SQL_NTS)) - check_error(retcode, 'SQLExecDirect()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! -} - -// retrieve_affected_rows returns number of rows affected/modified by the last operation. -1 if not applicable. -fn (h HStmt) retrieve_affected_rows() !int { - count_ret := C.SQLLEN(0) - retcode := C.SQLRowCount(h.hstmt, &count_ret) - check_error(retcode, 'SQLRowCount()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - return int(count_ret) -} - -fn (h HStmt) retrieve_column_count() !int { - mut retcode := C.SQLRETURN(C.SQL_SUCCESS) - col_count_buff := C.SQLSMALLINT(0) - retcode = C.SQLNumResultCols(h.hstmt, &col_count_buff) - check_error(retcode, 'SQLNumResultCols()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - return int(col_count_buff) -} - -// allocate buffers and bind them to drivers -fn (mut h HStmt) prepare_read() ! { - mut retcode := C.SQLRETURN(C.SQL_SUCCESS) - - column_count := h.retrieve_column_count()! - h.column_count = column_count // remember the count because read will need it - - h.buffers = [][]char{len: h.column_count} - h.indicators = []C.SQLLEN{len: h.column_count} - - for i := 0; i < h.column_count; i++ { - i_col := C.SQLUSMALLINT(i + 1) // col number starts with 1 - size_ret := C.SQLLEN(0) - // find out buffer size needed to read data in this column - retcode = C.SQLColAttribute(h.hstmt, i_col, C.SQLUSMALLINT(C.SQL_DESC_LENGTH), - C.SQLPOINTER(0), C.SQLSMALLINT(0), C.SQLSMALLINT(0), &size_ret) - check_error(retcode, 'SQLColAttribute()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - - // buffer allocation is the size + 1 to include termination char, since SQL_DESC_LENGTH does not include it. - allocate_size := size_ret + C.SQLLEN(1) - allocate_size_int := int(allocate_size) - buff := []char{len: allocate_size_int} - - // bind the buffer - retcode = C.SQLBindCol(h.hstmt, C.SQLUSMALLINT(i_col), C.SQLSMALLINT(C.SQL_C_CHAR), - C.SQLPOINTER(&buff[0]), allocate_size, &h.indicators[i]) - check_error(retcode, 'SQLBindCol()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - - // record the buffer in HStmt - h.buffers[i] = buff - } -} - -// fetch all rows -fn (h HStmt) read_rows() ![][]string { - mut retcode := C.SQLRETURN(C.SQL_SUCCESS) - - mut res := [][]string{} - - if h.column_count <= 0 { - // there is nothing in the driver to read from - return res - } - - // Fetch and print each row of data until SQL_NO_DATA returned. - for { - mut row := []string{} - retcode = C.SQLFetch(h.hstmt) - if retcode == C.SQLRETURN(C.SQL_SUCCESS) || retcode == C.SQLRETURN(C.SQL_SUCCESS_WITH_INFO) { - // copy buffered result to res - for content in h.buffers { - row << unsafe { cstring_to_vstring(content.data) } - } - } else { - if retcode != C.SQLRETURN(C.SQL_NO_DATA) { - check_error(retcode, 'SQLFetch()', C.SQLHANDLE(h.hstmt), C.SQLSMALLINT(C.SQL_HANDLE_STMT))! - } else { - break - } - } - res << row - } - return res -} diff --git a/vlib/mssql/z_deprecated.v b/vlib/mssql/z_deprecated.v deleted file mode 100644 index c09ca15705..0000000000 --- a/vlib/mssql/z_deprecated.v +++ /dev/null @@ -1,3 +0,0 @@ -[deprecated: 'import db.mssql instead'] -[deprecated_after: '2023-02-01'] -module mssql diff --git a/vlib/mysql/README.md b/vlib/mysql/README.md deleted file mode 100644 index 4c1d359dc0..0000000000 --- a/vlib/mysql/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Description: - -The `mysql` module has been moved to `db.mysql`. -Update your code to do: `import db.mysql` instead. diff --git a/vlib/mysql/_cdefs.c.v b/vlib/mysql/_cdefs.c.v deleted file mode 100644 index 9c69d33a28..0000000000 --- a/vlib/mysql/_cdefs.c.v +++ /dev/null @@ -1,103 +0,0 @@ -module mysql - -[typedef] -struct C.MYSQL { -} - -[typedef] -struct C.MYSQL_RES { -} - -[typedef] -struct C.MYSQL_FIELD { - name &u8 // Name of column - org_name &u8 // Original column name, if an alias - table &u8 // Table of column if column was a field - org_table &u8 // Org table name, if table was an alias - db &u8 // Database for table - catalog &u8 // Catalog for table - def &u8 // Default value (set by mysql_list_fields) - length int // Width of column (create length) - max_length int // Max width for selected set - name_length u32 - org_name_length u32 - table_length u32 - org_table_length u32 - db_length u32 - catalog_length u32 - def_length u32 - flags u32 // Div flags - decimals u32 // Number of decimals in field - charsetnr u32 // Character set - @type int // Type of field. See mysql_com.h for types -} - -fn C.mysql_init(mysql &C.MYSQL) &C.MYSQL - -fn C.mysql_real_connect(mysql &C.MYSQL, host &char, user &char, passwd &char, db &char, port u32, unix_socket &char, client_flag ConnectionFlag) &C.MYSQL - -fn C.mysql_query(mysql &C.MYSQL, q &u8) int - -fn C.mysql_use_result(mysql &C.MYSQL) - -fn C.mysql_real_query(mysql &C.MYSQL, q &u8, len u32) int - -fn C.mysql_select_db(mysql &C.MYSQL, db &u8) int - -fn C.mysql_change_user(mysql &C.MYSQL, user &u8, password &u8, db &u8) bool - -fn C.mysql_affected_rows(mysql &C.MYSQL) u64 - -fn C.mysql_options(mysql &C.MYSQL, option int, arg voidptr) int - -fn C.mysql_get_option(mysql &C.MYSQL, option int, arg voidptr) int - -fn C.mysql_list_tables(mysql &C.MYSQL, wild &u8) &C.MYSQL_RES - -fn C.mysql_num_fields(res &C.MYSQL_RES) int - -fn C.mysql_num_rows(res &C.MYSQL_RES) u64 - -fn C.mysql_autocommit(mysql &C.MYSQL, mode bool) - -fn C.mysql_refresh(mysql &C.MYSQL, options u32) int - -fn C.mysql_reset_connection(mysql &C.MYSQL) int - -fn C.mysql_ping(mysql &C.MYSQL) int - -fn C.mysql_store_result(mysql &C.MYSQL) &C.MYSQL_RES - -fn C.mysql_fetch_row(res &C.MYSQL_RES) &&u8 - -fn C.mysql_fetch_fields(res &C.MYSQL_RES) &C.MYSQL_FIELD - -fn C.mysql_free_result(res &C.MYSQL_RES) - -fn C.mysql_real_escape_string(mysql &C.MYSQL, to &u8, from &u8, len u64) u64 - -// fn C.mysql_real_escape_string_quote(mysql &C.MYSQL, to &byte, from &byte, len u64, quote byte) u64 (Don't exist in mariadb) - -fn C.mysql_close(sock &C.MYSQL) - -// INFO & VERSION -fn C.mysql_info(mysql &C.MYSQL) &u8 - -fn C.mysql_get_host_info(mysql &C.MYSQL) &u8 - -fn C.mysql_get_server_info(mysql &C.MYSQL) &u8 - -fn C.mysql_get_server_version(mysql &C.MYSQL) u64 - -fn C.mysql_get_client_version() u64 - -fn C.mysql_get_client_info() &u8 - -// DEBUG & ERROR INFO -fn C.mysql_error(mysql &C.MYSQL) &u8 - -fn C.mysql_errno(mysql &C.MYSQL) int - -fn C.mysql_dump_debug_info(mysql &C.MYSQL) int - -fn C.mysql_debug(debug &u8) diff --git a/vlib/mysql/_cdefs_nix.c.v b/vlib/mysql/_cdefs_nix.c.v deleted file mode 100644 index 1f37210529..0000000000 --- a/vlib/mysql/_cdefs_nix.c.v +++ /dev/null @@ -1,11 +0,0 @@ -module mysql - -// Need to check if mysqlclient is not there and use mariadb as alternative because newer system doesn't support mysql 8.0 as default - -$if $pkgconfig('mysqlclient') { - #pkgconfig mysqlclient - #include # Please install the libmysqlclient-dev development headers -} $else { - #pkgconfig mariadb - #include # Please install the libmariadb-dev development headers -} diff --git a/vlib/mysql/_cdefs_windows.c.v b/vlib/mysql/_cdefs_windows.c.v deleted file mode 100644 index 9e186966ed..0000000000 --- a/vlib/mysql/_cdefs_windows.c.v +++ /dev/null @@ -1,5 +0,0 @@ -module mysql - -#flag windows -I@VEXEROOT/thirdparty/mysql/include -#flag windows @VEXEROOT/thirdparty/mysql/lib/libmysql.dll -#include # Please install https://dev.mysql.com/downloads/installer/ , then put the include/ and lib/ folders in thirdparty/mysql diff --git a/vlib/mysql/consts.v b/vlib/mysql/consts.v deleted file mode 100644 index 2e9962a335..0000000000 --- a/vlib/mysql/consts.v +++ /dev/null @@ -1,13 +0,0 @@ -module mysql - -// MYSQL REFRESH FLAGS -pub const ( - refresh_grant = u32(C.REFRESH_GRANT) - refresh_log = u32(C.REFRESH_LOG) - refresh_tables = u32(C.REFRESH_TABLES) - refresh_hosts = u32(C.REFRESH_HOSTS) - refresh_status = u32(C.REFRESH_STATUS) - refresh_threads = u32(C.REFRESH_THREADS) - refresh_slave = u32(C.REFRESH_SLAVE) - refresh_master = u32(C.REFRESH_MASTER) -) diff --git a/vlib/mysql/enums.v b/vlib/mysql/enums.v deleted file mode 100644 index e2bfef564b..0000000000 --- a/vlib/mysql/enums.v +++ /dev/null @@ -1,78 +0,0 @@ -module mysql - -pub enum FieldType { - type_decimal - type_tiny - type_short - type_long - type_float - type_double - type_null - type_timestamp - type_longlong - type_int24 - type_date - type_time - type_datetime - type_year - type_newdate - type_varchar - type_bit - type_timestamp2 - type_datetime2 - type_time2 - type_json = 245 - type_newdecimal - type_enum - type_set - type_tiny_blob - type_medium_blob - type_long_blob - type_blob - type_var_string - type_string - type_geometry -} - -pub fn (f FieldType) str() string { - return match f { - .type_decimal { 'decimal' } - .type_tiny { 'tiny' } - .type_short { 'short' } - .type_long { 'long' } - .type_float { 'float' } - .type_double { 'double' } - .type_null { 'null' } - .type_timestamp { 'timestamp' } - .type_longlong { 'longlong' } - .type_int24 { 'int24' } - .type_date { 'date' } - .type_time { 'time' } - .type_datetime { 'datetime' } - .type_year { 'year' } - .type_newdate { 'newdate' } - .type_varchar { 'varchar' } - .type_bit { 'bit' } - .type_timestamp2 { 'timestamp2' } - .type_datetime2 { 'datetime2' } - .type_time2 { 'time2' } - .type_json { 'json' } - .type_newdecimal { 'newdecimal' } - .type_enum { 'enum' } - .type_set { 'set' } - .type_tiny_blob { 'tiny_blob' } - .type_medium_blob { 'medium_blob' } - .type_long_blob { 'long_blob' } - .type_blob { 'blob' } - .type_var_string { 'var_string' } - .type_string { 'string' } - .type_geometry { 'geometry' } - } -} - -pub fn (f FieldType) get_len() u32 { - return match f { - .type_blob { 262140 } - else { 0 } - } -} diff --git a/vlib/mysql/mysql.v b/vlib/mysql/mysql.v deleted file mode 100644 index b03e8a0b6f..0000000000 --- a/vlib/mysql/mysql.v +++ /dev/null @@ -1,250 +0,0 @@ -module mysql - -// Values for the capabilities flag bitmask used by the MySQL protocol. -// See more on https://dev.mysql.com/doc/dev/mysql-server/latest/group__group__cs__capabilities__flags.html#details -pub enum ConnectionFlag { - // CAN_HANDLE_EXPIRED_PASSWORDS = C.CAN_HANDLE_EXPIRED_PASSWORDS - client_compress = C.CLIENT_COMPRESS - client_found_rows = C.CLIENT_FOUND_ROWS - client_ignore_sigpipe = C.CLIENT_IGNORE_SIGPIPE - client_ignore_space = C.CLIENT_IGNORE_SPACE - client_interactive = C.CLIENT_INTERACTIVE - client_local_files = C.CLIENT_LOCAL_FILES - client_multi_results = C.CLIENT_MULTI_RESULTS - client_multi_statements = C.CLIENT_MULTI_STATEMENTS - client_no_schema = C.CLIENT_NO_SCHEMA - client_odbc = C.CLIENT_ODBC - // client_optional_resultset_metadata = C.CLIENT_OPTIONAL_RESULTSET_METADATA - client_ssl = C.CLIENT_SSL - client_remember_options = C.CLIENT_REMEMBER_OPTIONS -} - -struct SQLError { - MessageError -} - -// TODO: Documentation -pub struct Connection { -mut: - conn &C.MYSQL = C.mysql_init(0) -pub mut: - host string = '127.0.0.1' - port u32 = 3306 - username string - password string - dbname string - flag ConnectionFlag -} - -// connect - create a new connection to the MySQL server. -pub fn (mut conn Connection) connect() !bool { - instance := C.mysql_init(conn.conn) - conn.conn = C.mysql_real_connect(instance, conn.host.str, conn.username.str, conn.password.str, - conn.dbname.str, conn.port, 0, conn.flag) - if isnil(conn.conn) { - return error_with_code(get_error_msg(instance), get_errno(instance)) - } - return true -} - -// query - make an SQL query and receive the results. -// `query()` cannot be used for statements that contain binary data; -// Use `real_query()` instead. -pub fn (conn Connection) query(q string) !Result { - if C.mysql_query(conn.conn, q.str) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - res := C.mysql_store_result(conn.conn) - return Result{res} -} - -// use_result - reads the result of a query -// used after invoking mysql_real_query() or mysql_query(), -// for every statement that successfully produces a result set -// (SELECT, SHOW, DESCRIBE, EXPLAIN, CHECK TABLE, and so forth). -// This reads the result of a query directly from the server -// without storing it in a temporary table or local buffer, -// mysql_use_result is faster and uses much less memory than C.mysql_store_result(). -// You must mysql_free_result() after you are done with the result set. -pub fn (conn Connection) use_result() { - C.mysql_use_result(conn.conn) -} - -// real_query - make an SQL query and receive the results. -// `real_query()` can be used for statements containing binary data. -// (Binary data may contain the `\0` character, which `query()` -// interprets as the end of the statement string). In addition, -// `real_query()` is faster than `query()`. -pub fn (mut conn Connection) real_query(q string) !Result { - if C.mysql_real_query(conn.conn, q.str, q.len) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - res := C.mysql_store_result(conn.conn) - return Result{res} -} - -// select_db - change the default database for database queries. -pub fn (mut conn Connection) select_db(dbname string) !bool { - if C.mysql_select_db(conn.conn, dbname.str) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return true -} - -// change_user - change the mysql user for the connection. -// Passing an empty string for the `dbname` parameter, resultsg in only changing -// the user and not changing the default database for the connection. -pub fn (mut conn Connection) change_user(username string, password string, dbname string) !bool { - mut ret := true - if dbname != '' { - ret = C.mysql_change_user(conn.conn, username.str, password.str, dbname.str) - } else { - ret = C.mysql_change_user(conn.conn, username.str, password.str, 0) - } - if !ret { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return ret -} - -// affected_rows - return the number of rows changed/deleted/inserted -// by the last `UPDATE`, `DELETE`, or `INSERT` query. -pub fn (conn &Connection) affected_rows() u64 { - return C.mysql_affected_rows(conn.conn) -} - -// autocommit - turns on/off the auto-committing mode for the connection. -// When it is on, then each query is commited right away. -pub fn (mut conn Connection) autocommit(mode bool) { - C.mysql_autocommit(conn.conn, mode) -} - -// tables - returns a list of the names of the tables in the current database, -// that match the simple regular expression specified by the `wildcard` parameter. -// The `wildcard` parameter may contain the wildcard characters `%` or `_`. -// If an empty string is passed, it will return all tables. -// Calling `tables()` is similar to executing query `SHOW TABLES [LIKE wildcard]`. -pub fn (conn &Connection) tables(wildcard string) ![]string { - cres := C.mysql_list_tables(conn.conn, wildcard.str) - if isnil(cres) { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - res := Result{cres} - mut tables := []string{} - for row in res.rows() { - tables << row.vals[0] - } - return tables -} - -// escape_string - creates a legal SQL string for use in an SQL statement. -// The `s` argument is encoded to produce an escaped SQL string, -// taking into account the current character set of the connection. -pub fn (conn &Connection) escape_string(s string) string { - unsafe { - to := malloc_noscan(2 * s.len + 1) - C.mysql_real_escape_string(conn.conn, to, s.str, s.len) - return to.vstring() - } -} - -// set_option - sets extra connect options that affect the behavior of -// a connection. This function may be called multiple times to set several -// options. To retrieve the current values for an option, use `get_option()`. -pub fn (mut conn Connection) set_option(option_type int, val voidptr) { - C.mysql_options(conn.conn, option_type, val) -} - -// get_option - return the value of an option, settable by `set_option`. -// https://dev.mysql.com/doc/c-api/5.7/en/mysql-get-option.html -pub fn (conn &Connection) get_option(option_type int) !voidptr { - ret := unsafe { nil } - if C.mysql_get_option(conn.conn, option_type, &ret) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return ret -} - -// refresh - flush the tables or caches, or resets replication server -// information. The connected user must have the `RELOAD` privilege. -pub fn (mut conn Connection) refresh(options u32) !bool { - if C.mysql_refresh(conn.conn, options) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return true -} - -// reset - resets the connection, and clear the session state. -pub fn (mut conn Connection) reset() !bool { - if C.mysql_reset_connection(conn.conn) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return true -} - -// ping - pings a server connection, or tries to reconnect if the connection -// has gone down. -pub fn (mut conn Connection) ping() !bool { - if C.mysql_ping(conn.conn) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return true -} - -// close - closes the connection. -pub fn (mut conn Connection) close() { - C.mysql_close(conn.conn) -} - -// info - returns information about the most recently executed query. -// See more on https://dev.mysql.com/doc/c-api/8.0/en/mysql-info.html -pub fn (conn &Connection) info() string { - return resolve_nil_str(C.mysql_info(conn.conn)) -} - -// get_host_info - returns a string describing the type of connection in use, -// including the server host name. -pub fn (conn &Connection) get_host_info() string { - return unsafe { C.mysql_get_host_info(conn.conn).vstring() } -} - -// get_server_info - returns a string representing the MySQL server version. -// For example, `8.0.24`. -pub fn (conn &Connection) get_server_info() string { - return unsafe { C.mysql_get_server_info(conn.conn).vstring() } -} - -// get_server_version - returns an integer, representing the MySQL server -// version. The value has the format `XYYZZ` where `X` is the major version, -// `YY` is the release level (or minor version), and `ZZ` is the sub-version -// within the release level. For example, `8.0.24` is returned as `80024`. -pub fn (conn &Connection) get_server_version() u64 { - return C.mysql_get_server_version(conn.conn) -} - -// dump_debug_info - instructs the server to write debugging information -// to the error log. The connected user must have the `SUPER` privilege. -pub fn (mut conn Connection) dump_debug_info() !bool { - if C.mysql_dump_debug_info(conn.conn) != 0 { - return error_with_code(get_error_msg(conn.conn), get_errno(conn.conn)) - } - return true -} - -// get_client_info - returns client version information as a string. -pub fn get_client_info() string { - return unsafe { C.mysql_get_client_info().vstring() } -} - -// get_client_version - returns the client version information as an integer. -pub fn get_client_version() u64 { - return C.mysql_get_client_version() -} - -// debug - does a `DBUG_PUSH` with the given string. -// `debug()` uses the Fred Fish debug library. -// To use this function, you must compile the client library to support debugging. -// See https://dev.mysql.com/doc/c-api/8.0/en/mysql-debug.html -pub fn debug(debug string) { - C.mysql_debug(debug.str) -} diff --git a/vlib/mysql/orm.v b/vlib/mysql/orm.v deleted file mode 100644 index 92ca2993ab..0000000000 --- a/vlib/mysql/orm.v +++ /dev/null @@ -1,376 +0,0 @@ -module mysql - -import orm -import time - -type Prims = f32 | f64 | i16 | i64 | i8 | int | string | u16 | u32 | u64 | u8 - -// sql expr - -pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive { - query := orm.orm_select_gen(config, '`', false, '?', 0, where) - mut ret := [][]orm.Primitive{} - mut stmt := db.init_stmt(query) - stmt.prepare()! - - mysql_stmt_binder(mut stmt, where)! - mysql_stmt_binder(mut stmt, data)! - - if data.data.len > 0 || where.data.len > 0 { - stmt.bind_params()! - } - - mut status := stmt.execute()! - num_fields := stmt.get_field_count() - metadata := stmt.gen_metadata() - fields := stmt.fetch_fields(metadata) - mut dataptr := []&u8{} - - for i in 0 .. num_fields { - f := unsafe { fields[i] } - match unsafe { FieldType(f.@type) } { - .type_tiny { - dataptr << unsafe { malloc(1) } - } - .type_short { - dataptr << unsafe { malloc(2) } - } - .type_long { - dataptr << unsafe { malloc(4) } - } - .type_longlong { - dataptr << unsafe { malloc(8) } - } - .type_float { - dataptr << unsafe { malloc(4) } - } - .type_double { - dataptr << unsafe { malloc(8) } - } - .type_time, .type_date, .type_datetime, .type_time2, .type_datetime2 { - dataptr << unsafe { malloc(sizeof(C.MYSQL_TIME)) } - } - .type_string, .type_blob { - dataptr << unsafe { malloc(512) } - } - .type_var_string { - dataptr << unsafe { malloc(2) } - } - else { - return error('\'${unsafe { FieldType(f.@type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new') - } - } - } - - lens := []u32{len: int(num_fields), init: 0} - stmt.bind_res(fields, dataptr, lens, num_fields) - - mut row := 0 - mut types := config.types.clone() - mut field_types := []FieldType{} - if config.is_count { - types = [orm.type_idx['u64']] - } - - for i, mut mysql_bind in stmt.res { - f := unsafe { fields[i] } - field_types << unsafe { FieldType(f.@type) } - match types[i] { - orm.type_string { - mysql_bind.buffer_type = C.MYSQL_TYPE_BLOB - mysql_bind.buffer_length = FieldType.type_blob.get_len() - } - orm.time { - match unsafe { FieldType(f.@type) } { - .type_long { - mysql_bind.buffer_type = C.MYSQL_TYPE_LONG - } - .type_time, .type_date, .type_datetime { - mysql_bind.buffer_type = C.MYSQL_TYPE_BLOB - mysql_bind.buffer_length = FieldType.type_blob.get_len() - } - .type_string, .type_blob {} - else { - return error('Unknown type ${f.@type}') - } - } - } - else {} - } - } - - stmt.bind_result_buffer()! - stmt.store_result()! - for { - status = stmt.fetch_stmt()! - - if status == 1 || status == 100 { - break - } - row++ - - data_list := buffer_to_primitive(dataptr, types, field_types)! - ret << data_list - } - - stmt.close()! - - return ret -} - -// sql stmt - -pub fn (db Connection) insert(table string, data orm.QueryData) ! { - mut converted_primitive_array := db.factory_orm_primitive_converted_from_sql(table, - data)! - - converted_primitive_data := orm.QueryData{ - fields: data.fields - data: converted_primitive_array - types: [] - kinds: [] - is_and: [] - } - - query, converted_data := orm.orm_stmt_gen(.default, table, '`', .insert, false, '?', - 1, converted_primitive_data, orm.QueryData{}) - mysql_stmt_worker(db, query, converted_data, orm.QueryData{})! -} - -pub fn (db Connection) update(table string, data orm.QueryData, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.default, table, '`', .update, false, '?', 1, data, where) - mysql_stmt_worker(db, query, data, where)! -} - -pub fn (db Connection) delete(table string, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.default, table, '`', .delete, false, '?', 1, orm.QueryData{}, - where) - mysql_stmt_worker(db, query, orm.QueryData{}, where)! -} - -pub fn (db Connection) last_id() int { - query := 'SELECT last_insert_id();' - id := db.query(query) or { return 0 } - - return orm.Primitive(id.rows()[0].vals[0].int()) -} - -// table -pub fn (db Connection) create(table string, fields []orm.TableField) ! { - query := orm.orm_table_gen(table, '`', true, 0, fields, mysql_type_from_v, false) or { - return err - } - mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -pub fn (db Connection) drop(table string) ! { - query := 'DROP TABLE `${table}`;' - mysql_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -fn mysql_stmt_worker(db Connection, query string, data orm.QueryData, where orm.QueryData) ! { - mut stmt := db.init_stmt(query) - stmt.prepare()! - mysql_stmt_binder(mut stmt, data)! - mysql_stmt_binder(mut stmt, where)! - if data.data.len > 0 || where.data.len > 0 { - stmt.bind_params()! - } - stmt.execute()! - stmt.close()! -} - -fn mysql_stmt_binder(mut stmt Stmt, d orm.QueryData) ! { - for data in d.data { - stmt_binder_match(mut stmt, data) - } -} - -fn stmt_binder_match(mut stmt Stmt, data orm.Primitive) { - match data { - bool { - stmt.bind_bool(&data) - } - i8 { - stmt.bind_i8(&data) - } - i16 { - stmt.bind_i16(&data) - } - int { - stmt.bind_int(&data) - } - i64 { - stmt.bind_i64(&data) - } - u8 { - stmt.bind_u8(&data) - } - u16 { - stmt.bind_u16(&data) - } - u32 { - stmt.bind_u32(&data) - } - u64 { - stmt.bind_u64(&data) - } - f32 { - stmt.bind_f32(unsafe { &f32(&data) }) - } - f64 { - stmt.bind_f64(unsafe { &f64(&data) }) - } - string { - stmt.bind_text(data) - } - time.Time { - unix := int(data.unix) - stmt_binder_match(mut stmt, unix) - } - orm.InfixType { - stmt_binder_match(mut stmt, data.right) - } - } -} - -fn buffer_to_primitive(data_list []&u8, types []int, field_types []FieldType) ![]orm.Primitive { - mut res := []orm.Primitive{} - - for i, data in data_list { - mut primitive := orm.Primitive(0) - match types[i] { - orm.type_idx['i8'] { - primitive = *(unsafe { &i8(data) }) - } - orm.type_idx['i16'] { - primitive = *(unsafe { &i16(data) }) - } - orm.type_idx['int'], orm.serial { - primitive = *(unsafe { &int(data) }) - } - orm.type_idx['i64'] { - primitive = *(unsafe { &i64(data) }) - } - orm.type_idx['u8'] { - primitive = *(unsafe { &u8(data) }) - } - orm.type_idx['u16'] { - primitive = *(unsafe { &u16(data) }) - } - orm.type_idx['u32'] { - primitive = *(unsafe { &u32(data) }) - } - orm.type_idx['u64'] { - primitive = *(unsafe { &u64(data) }) - } - orm.type_idx['f32'] { - primitive = *(unsafe { &f32(data) }) - } - orm.type_idx['f64'] { - primitive = *(unsafe { &f64(data) }) - } - orm.type_idx['bool'] { - primitive = *(unsafe { &bool(data) }) - } - orm.type_string { - primitive = unsafe { cstring_to_vstring(&char(data)) } - } - orm.time { - match field_types[i] { - .type_long { - timestamp := *(unsafe { &int(data) }) - primitive = time.unix(timestamp) - } - .type_datetime { - string_time := unsafe { cstring_to_vstring(&char(data)) } - primitive = time.parse(string_time)! - } - else {} - } - } - else { - return error('Unknown type ${types[i]}') - } - } - res << primitive - } - - return res -} - -fn mysql_type_from_v(typ int) !string { - str := match typ { - orm.type_idx['i8'], orm.type_idx['u8'] { - 'TINYINT' - } - orm.type_idx['i16'], orm.type_idx['u16'] { - 'SMALLINT' - } - orm.type_idx['int'], orm.type_idx['u32'], orm.time { - 'INT' - } - orm.type_idx['i64'], orm.type_idx['u64'] { - 'BIGINT' - } - orm.type_idx['f32'] { - 'FLOAT' - } - orm.type_idx['f64'] { - 'DOUBLE' - } - orm.type_string { - 'TEXT' - } - orm.serial { - 'SERIAL' - } - orm.type_idx['bool'] { - 'BOOLEAN' - } - else { - '' - } - } - if str == '' { - return error('Unknown type ${typ}') - } - return str -} - -fn (db Connection) factory_orm_primitive_converted_from_sql(table string, data orm.QueryData) ![]orm.Primitive { - mut map_val := db.get_table_data_type_map(table)! - - // adapt v type to sql time - mut converted_data := []orm.Primitive{} - for i, field in data.fields { - match data.data[i].type_name() { - 'time.Time' { - if map_val[field] == 'datetime' { - converted_data << orm.Primitive((data.data[i] as time.Time).str()) - } else { - converted_data << data.data[i] - } - } - else { - converted_data << data.data[i] - } - } - } - return converted_data -} - -fn (db Connection) get_table_data_type_map(table string) !map[string]string { - data_type_querys := "SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${table}'" - mut map_val := map[string]string{} - - results := db.query(data_type_querys)! - db.use_result() - - for row in results.rows() { - map_val[row.vals[0]] = row.vals[1] - } - - unsafe { results.free() } - return map_val -} diff --git a/vlib/mysql/result.v b/vlib/mysql/result.v deleted file mode 100644 index 0969c75c20..0000000000 --- a/vlib/mysql/result.v +++ /dev/null @@ -1,153 +0,0 @@ -module mysql - -pub struct Result { - result &C.MYSQL_RES = unsafe { nil } -} - -pub struct Row { -pub mut: - vals []string -} - -pub struct Field { - name string - org_name string - table string - org_table string - db string - catalog string - def string - length int - max_length int - name_length u32 - org_name_length u32 - table_length u32 - org_table_length u32 - db_length u32 - catalog_length u32 - def_length u32 - flags u32 - decimals u32 - charsetnr u32 - type_ FieldType -} - -// fetch_row - fetches the next row from a result. -pub fn (r Result) fetch_row() &&u8 { - return C.mysql_fetch_row(r.result) -} - -// n_rows - returns the number of rows from a result. -pub fn (r Result) n_rows() u64 { - return C.mysql_num_rows(r.result) -} - -// n_fields - returns the number of columns from a result. -pub fn (r Result) n_fields() int { - return C.mysql_num_fields(r.result) -} - -// rows - returns array of rows, each containing an array of values, -// one for each column. -pub fn (r Result) rows() []Row { - mut rows := []Row{} - nr_cols := r.n_fields() - for rr := r.fetch_row(); rr; rr = r.fetch_row() { - mut row := Row{} - for i in 0 .. nr_cols { - if unsafe { rr[i] == 0 } { - row.vals << '' - } else { - row.vals << mystring(unsafe { &u8(rr[i]) }) - } - } - rows << row - } - return rows -} - -// maps - returns an array of maps, each containing a set of -// field name: field value pairs. -pub fn (r Result) maps() []map[string]string { - mut array_map := []map[string]string{} - rows := r.rows() - fields := r.fields() - for i in 0 .. rows.len { - mut map_val := map[string]string{} - for j in 0 .. fields.len { - map_val[fields[j].name] = rows[i].vals[j] - } - array_map << map_val - } - return array_map -} - -// fields - returns an array of fields/columns. -// The definitions apply primarily for columns of results, -// such as those produced by `SELECT` statements. -pub fn (r Result) fields() []Field { - mut fields := []Field{} - nr_cols := r.n_fields() - orig_fields := C.mysql_fetch_fields(r.result) - for i in 0 .. nr_cols { - unsafe { - fields << Field{ - name: mystring(orig_fields[i].name) - org_name: mystring(orig_fields[i].org_name) - table: mystring(orig_fields[i].table) - org_table: mystring(orig_fields[i].org_table) - db: mystring(orig_fields[i].db) - catalog: mystring(orig_fields[i].catalog) - def: resolve_nil_str(orig_fields[i].def) - length: orig_fields.length - max_length: orig_fields.max_length - name_length: orig_fields.name_length - org_name_length: orig_fields.org_name_length - table_length: orig_fields.table_length - org_table_length: orig_fields.org_table_length - db_length: orig_fields.db_length - catalog_length: orig_fields.catalog_length - def_length: orig_fields.def_length - flags: orig_fields.flags - decimals: orig_fields.decimals - charsetnr: orig_fields.charsetnr - type_: FieldType(orig_fields.@type) - } - } - } - return fields -} - -// str - serializes the field -pub fn (f Field) str() string { - return ' -{ - name: "${f.name}" - org_name: "${f.org_name}" - table: "${f.table}" - org_table: "${f.org_table}" - db: "${f.db}" - catalog: "${f.catalog}" - def: "${f.def}" - length: ${f.length} - max_length: ${f.max_length} - name_length: ${f.name_length} - org_name_length: ${f.org_name_length} - table_length: ${f.table_length} - org_table_length: ${f.org_table_length} - db_length: ${f.db_length} - catalog_length: ${f.catalog_length} - def_length: ${f.def_length} - flags: ${f.flags} - decimals: ${f.decimals} - charsetnr: ${f.charsetnr} - type: ${f.type_.str()} -} -' -} - -// free - frees the memory used by a result -[unsafe] -pub fn (r &Result) free() { - C.mysql_free_result(r.result) -} diff --git a/vlib/mysql/stmt.c.v b/vlib/mysql/stmt.c.v deleted file mode 100644 index 1306acbeca..0000000000 --- a/vlib/mysql/stmt.c.v +++ /dev/null @@ -1,237 +0,0 @@ -module mysql - -[typedef] -struct C.MYSQL_STMT { - mysql &C.MYSQL - stmt_id u32 -} - -[typedef] -struct C.MYSQL_BIND { -mut: - buffer_type int - buffer voidptr - buffer_length u32 - length &u32 -} - -const ( - mysql_type_decimal = C.MYSQL_TYPE_DECIMAL - mysql_type_tiny = C.MYSQL_TYPE_TINY - mysql_type_short = C.MYSQL_TYPE_SHORT - mysql_type_long = C.MYSQL_TYPE_LONG - mysql_type_float = C.MYSQL_TYPE_FLOAT - mysql_type_double = C.MYSQL_TYPE_DOUBLE - mysql_type_null = C.MYSQL_TYPE_NULL - mysql_type_timestamp = C.MYSQL_TYPE_TIMESTAMP - mysql_type_longlong = C.MYSQL_TYPE_LONGLONG - mysql_type_int24 = C.MYSQL_TYPE_INT24 - mysql_type_date = C.MYSQL_TYPE_DATE - mysql_type_time = C.MYSQL_TYPE_TIME - mysql_type_datetime = C.MYSQL_TYPE_DATETIME - mysql_type_year = C.MYSQL_TYPE_YEAR - mysql_type_varchar = C.MYSQL_TYPE_VARCHAR - mysql_type_bit = C.MYSQL_TYPE_BIT - mysql_type_timestamp22 = C.MYSQL_TYPE_TIMESTAMP - mysql_type_json = C.MYSQL_TYPE_JSON - mysql_type_newdecimal = C.MYSQL_TYPE_NEWDECIMAL - mysql_type_enum = C.MYSQL_TYPE_ENUM - mysql_type_set = C.MYSQL_TYPE_SET - mysql_type_tiny_blob = C.MYSQL_TYPE_TINY_BLOB - mysql_type_medium_blob = C.MYSQL_TYPE_MEDIUM_BLOB - mysql_type_long_blob = C.MYSQL_TYPE_LONG_BLOB - mysql_type_blob = C.MYSQL_TYPE_BLOB - mysql_type_var_string = C.MYSQL_TYPE_VAR_STRING - mysql_type_string = C.MYSQL_TYPE_STRING - mysql_type_geometry = C.MYSQL_TYPE_GEOMETRY - mysql_no_data = C.MYSQL_NO_DATA -) - -fn C.mysql_stmt_init(&C.MYSQL) &C.MYSQL_STMT -fn C.mysql_stmt_prepare(&C.MYSQL_STMT, &char, u32) int -fn C.mysql_stmt_bind_param(&C.MYSQL_STMT, &C.MYSQL_BIND) bool -fn C.mysql_stmt_execute(&C.MYSQL_STMT) int -fn C.mysql_stmt_close(&C.MYSQL_STMT) bool -fn C.mysql_stmt_free_result(&C.MYSQL_STMT) bool -fn C.mysql_stmt_error(&C.MYSQL_STMT) &char -fn C.mysql_stmt_result_metadata(&C.MYSQL_STMT) &C.MYSQL_RES - -fn C.mysql_stmt_field_count(&C.MYSQL_STMT) u16 -fn C.mysql_stmt_bind_result(&C.MYSQL_STMT, &C.MYSQL_BIND) bool -fn C.mysql_stmt_fetch(&C.MYSQL_STMT) int -fn C.mysql_stmt_next_result(&C.MYSQL_STMT) int -fn C.mysql_stmt_store_result(&C.MYSQL_STMT) int - -struct Stmt { - stmt &C.MYSQL_STMT = &C.MYSQL_STMT(0) - query string -mut: - binds []C.MYSQL_BIND - res []C.MYSQL_BIND -} - -pub fn (db Connection) init_stmt(query string) Stmt { - return Stmt{ - stmt: C.mysql_stmt_init(db.conn) - query: query - binds: []C.MYSQL_BIND{} - } -} - -pub fn (stmt Stmt) prepare() ! { - res := C.mysql_stmt_prepare(stmt.stmt, stmt.query.str, stmt.query.len) - if res != 0 && stmt.get_error_msg() != '' { - return stmt.error(res) - } -} - -pub fn (stmt Stmt) bind_params() ! { - res := C.mysql_stmt_bind_param(stmt.stmt, unsafe { &C.MYSQL_BIND(stmt.binds.data) }) - if res && stmt.get_error_msg() != '' { - return stmt.error(1) - } -} - -pub fn (stmt Stmt) execute() !int { - res := C.mysql_stmt_execute(stmt.stmt) - if res != 0 && stmt.get_error_msg() != '' { - return stmt.error(res) - } - return res -} - -pub fn (stmt Stmt) next() !int { - res := C.mysql_stmt_next_result(stmt.stmt) - if res > 0 && stmt.get_error_msg() != '' { - return stmt.error(res) - } - return res -} - -pub fn (stmt Stmt) gen_metadata() &C.MYSQL_RES { - return C.mysql_stmt_result_metadata(stmt.stmt) -} - -pub fn (stmt Stmt) fetch_fields(res &C.MYSQL_RES) &C.MYSQL_FIELD { - return C.mysql_fetch_fields(res) -} - -pub fn (stmt Stmt) fetch_stmt() !int { - res := C.mysql_stmt_fetch(stmt.stmt) - if res !in [0, 100] && stmt.get_error_msg() != '' { - return stmt.error(res) - } - return res -} - -pub fn (stmt Stmt) close() ! { - if !C.mysql_stmt_close(stmt.stmt) && stmt.get_error_msg() != '' { - return stmt.error(1) - } - if !C.mysql_stmt_free_result(stmt.stmt) && stmt.get_error_msg() != '' { - return stmt.error(1) - } -} - -fn (stmt Stmt) get_error_msg() string { - return unsafe { cstring_to_vstring(&char(C.mysql_stmt_error(stmt.stmt))) } -} - -pub fn (stmt Stmt) error(code int) IError { - msg := stmt.get_error_msg() - return &SQLError{ - msg: '${msg} (${code}) (${stmt.query})' - code: code - } -} - -fn (stmt Stmt) get_field_count() u16 { - return C.mysql_stmt_field_count(stmt.stmt) -} - -pub fn (mut stmt Stmt) bind_bool(b &bool) { - stmt.bind(mysql.mysql_type_tiny, b, 0) -} - -pub fn (mut stmt Stmt) bind_byte(b &byte) { - stmt.bind(mysql.mysql_type_tiny, b, 0) -} - -pub fn (mut stmt Stmt) bind_u8(b &u8) { - stmt.bind(mysql.mysql_type_tiny, b, 0) -} - -pub fn (mut stmt Stmt) bind_i8(b &i8) { - stmt.bind(mysql.mysql_type_tiny, b, 0) -} - -pub fn (mut stmt Stmt) bind_i16(b &i16) { - stmt.bind(mysql.mysql_type_short, b, 0) -} - -pub fn (mut stmt Stmt) bind_u16(b &u16) { - stmt.bind(mysql.mysql_type_short, b, 0) -} - -pub fn (mut stmt Stmt) bind_int(b &int) { - stmt.bind(mysql.mysql_type_long, b, 0) -} - -pub fn (mut stmt Stmt) bind_u32(b &u32) { - stmt.bind(mysql.mysql_type_long, b, 0) -} - -pub fn (mut stmt Stmt) bind_i64(b &i64) { - stmt.bind(mysql.mysql_type_longlong, b, 0) -} - -pub fn (mut stmt Stmt) bind_u64(b &u64) { - stmt.bind(mysql.mysql_type_longlong, b, 0) -} - -pub fn (mut stmt Stmt) bind_f32(b &f32) { - stmt.bind(mysql.mysql_type_float, b, 0) -} - -pub fn (mut stmt Stmt) bind_f64(b &f64) { - stmt.bind(mysql.mysql_type_double, b, 0) -} - -pub fn (mut stmt Stmt) bind_text(b string) { - stmt.bind(mysql.mysql_type_string, b.str, u32(b.len)) -} - -pub fn (mut stmt Stmt) bind(typ int, buffer voidptr, buf_len u32) { - stmt.binds << C.MYSQL_BIND{ - buffer_type: typ - buffer: buffer - buffer_length: buf_len - length: 0 - } -} - -pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&u8, lens []u32, num_fields int) { - for i in 0 .. num_fields { - len := unsafe { FieldType(fields[i].@type).get_len() } - stmt.res << C.MYSQL_BIND{ - buffer_type: unsafe { fields[i].@type } - buffer: dataptr[i] - length: &lens[i] - buffer_length: len - } - } -} - -pub fn (mut stmt Stmt) bind_result_buffer() ! { - res := C.mysql_stmt_bind_result(stmt.stmt, unsafe { &C.MYSQL_BIND(stmt.res.data) }) - if res && stmt.get_error_msg() != '' { - return stmt.error(1) - } -} - -pub fn (mut stmt Stmt) store_result() ! { - res := C.mysql_stmt_store_result(stmt.stmt) - if res != 0 && stmt.get_error_msg() != '' { - return stmt.error(res) - } -} diff --git a/vlib/mysql/utils.v b/vlib/mysql/utils.v deleted file mode 100644 index d35554c805..0000000000 --- a/vlib/mysql/utils.v +++ /dev/null @@ -1,26 +0,0 @@ -module mysql - -// get_error_msg - returns error message from MySQL instance. -fn get_error_msg(conn &C.MYSQL) string { - return unsafe { C.mysql_error(conn).vstring() } -} - -// get_errno - returns error number from MySQL instance. -fn get_errno(conn &C.MYSQL) int { - return C.mysql_errno(conn) -} - -// resolve_nil_str - returns an empty string if passed value is a nil pointer. -fn resolve_nil_str(ptr &u8) string { - if isnil(ptr) { - return '' - } - return unsafe { ptr.vstring() } -} - -[inline] -fn mystring(b &u8) string { - unsafe { - return b.vstring() - } -} diff --git a/vlib/mysql/z_deprecated.v b/vlib/mysql/z_deprecated.v deleted file mode 100644 index 888a601317..0000000000 --- a/vlib/mysql/z_deprecated.v +++ /dev/null @@ -1,3 +0,0 @@ -[deprecated: 'import db.mysql instead'] -[deprecated_after: '2023-02-01'] -module mysql diff --git a/vlib/pg/README.md b/vlib/pg/README.md deleted file mode 100644 index 91d35d535d..0000000000 --- a/vlib/pg/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Description: - -The `pg` module has been moved to `db.pg`. -Update your code to do: `import db.pg` instead. diff --git a/vlib/pg/compatibility.h b/vlib/pg/compatibility.h deleted file mode 100644 index 3d82f22111..0000000000 --- a/vlib/pg/compatibility.h +++ /dev/null @@ -1,16 +0,0 @@ - -#if !defined(PG_VERSION_NUM) -#error VERROR_MESSAGE PG_VERSION_NUM is not defined. Please install the development headers for PostgreSQL, they are usually in a package named libpq-dev -#endif - -#if PG_VERSION_NUM < 100000 - #define CONNECTION_CHECK_WRITABLE 9 -#endif - -#if PG_VERSION_NUM < 100000 - #define CONNECTION_CONSUME 10 -#endif - -#if PG_VERSION_NUM < 120000 - #define CONNECTION_GSS_STARTUP 11 -#endif diff --git a/vlib/pg/oid.v b/vlib/pg/oid.v deleted file mode 100644 index 2f8004d888..0000000000 --- a/vlib/pg/oid.v +++ /dev/null @@ -1,171 +0,0 @@ -module pg - -pub enum Oid { - t_bool = 16 - t_bytea = 17 - t_char = 18 - t_name = 19 - t_int8 = 20 - t_int2 = 21 - t_int2vector = 22 - t_int4 = 23 - t_regproc = 24 - t_text = 25 - t_oid = 26 - t_tid = 27 - t_xid = 28 - t_cid = 29 - t_vector = 30 - t_pg_ddl_command = 32 - t_pg_type = 71 - t_pg_attribute = 75 - t_pg_proc = 81 - t_pg_class = 83 - t_json = 114 - t_xml = 142 - t__xml = 143 - t_pg_node_tree = 194 - t__json = 199 - t_smgr = 210 - t_index_am_handler = 325 - t_point = 600 - t_lseg = 601 - t_path = 602 - t_box = 603 - t_polygon = 604 - t_line = 628 - t__line = 629 - t_cidr = 650 - t__cidr = 651 - t_float4 = 700 - t_float8 = 701 - t_abstime = 702 - t_reltime = 703 - t_tinterval = 704 - t_unknown = 705 - t_circle = 718 - t__circle = 719 - t_money = 790 - t__money = 791 - t_macaddr = 829 - t_inet = 869 - t__bool = 1000 - t__bytea = 1001 - t__char = 1002 - t__name = 1003 - t__int2 = 1005 - t__int2vector = 1006 - t__int4 = 1007 - t__regproc = 1008 - t__text = 1009 - t__tid = 1010 - t__xid = 1011 - t__cid = 1012 - t__vector = 1013 - t__bpchar = 1014 - t__varchar = 1015 - t__int8 = 1016 - t__point = 1017 - t__lseg = 1018 - t__path = 1019 - t__box = 1020 - t__float4 = 1021 - t__float8 = 1022 - t__abstime = 1023 - t__reltime = 1024 - t__tinterval = 1025 - t__polygon = 1027 - t__ = 1028 - t_aclitem = 1033 - t__aclitem = 1034 - t__macaddr = 1040 - t__inet = 1041 - t_bpchar = 1042 - t_varchar = 1043 - t_date = 1082 - t_time = 1083 - t_timestamp = 1114 - t__timestamp = 1115 - t__date = 1182 - t__time = 1183 - t_timestamptz = 1184 - t__timestamptz = 1185 - t_interval = 1186 - t__interval = 1187 - t__numeric = 1231 - t_pg_database = 1248 - t__cstring = 1263 - t_timetz = 1266 - t__timetz = 1270 - t_bit = 1560 - t__bit = 1561 - t_varbit = 1562 - t__varbit = 1563 - t_numeric = 1700 - t_refcursor = 1790 - t__refcursor = 2201 - t_regprocedure = 2202 - t_regoper = 2203 - t_regoperator = 2204 - t_regclass = 2205 - t_regtype = 2206 - t__regprocedure = 2207 - t__regoper = 2208 - t__regoperator = 2209 - t__regclass = 2210 - t__regtype = 2211 - t_record = 2249 - t_cstring = 2275 - t_any = 2276 - t_anyarray = 2277 - t_v = 2278 - t_trigger = 2279 - t_language_handler = 2280 - t_internal = 2281 - t_opaque = 2282 - t_anyelement = 2283 - t__record = 2287 - t_anynonarray = 2776 - t_pg_authid = 2842 - t_pg_auth_members = 2843 - t__txid_snapshot = 2949 - t_uuid = 2950 - t__uuid = 2951 - t_txid_snapshot = 2970 - t_fdw_handler = 3115 - t_pg_lsn = 3220 - t__pg_lsn = 3221 - t_tsm_handler = 3310 - t_anyenum = 3500 - t_tsvector = 3614 - t_tsquery = 3615 - t_gtsvector = 3642 - t__tsvector = 3643 - t__gtsvector = 3644 - t__tsquery = 3645 - t_regconfig = 3734 - t__regconfig = 3735 - t_regdictionary = 3769 - t__regdictionary = 3770 - t_jsonb = 3802 - t__jsonb = 3807 - t_anyrange = 3831 - t_event_trigger = 3838 - t_int4range = 3904 - t__int4range = 3905 - t_numrange = 3906 - t__numrange = 3907 - t_tsrange = 3908 - t__tsrange = 3909 - t_tstzrange = 3910 - t__tstzrange = 3911 - t_daterange = 3912 - t__daterange = 3913 - t_int8range = 3926 - t__int8range = 3927 - t_pg_shseclabel = 4066 - t_regnamespace = 4089 - t__regnamespace = 4090 - t_regrole = 4096 - t__regrole = 4097 -} diff --git a/vlib/pg/orm.v b/vlib/pg/orm.v deleted file mode 100644 index c58ffd552f..0000000000 --- a/vlib/pg/orm.v +++ /dev/null @@ -1,292 +0,0 @@ -module pg - -import orm -import time -import net.conv - -// sql expr - -pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive { - query := orm.orm_select_gen(config, '"', true, '$', 1, where) - - res := pg_stmt_worker(db, query, where, data)! - - mut ret := [][]orm.Primitive{} - - if config.is_count { - } - - for row in res { - mut row_data := []orm.Primitive{} - for i, val in row.vals { - field := str_to_primitive(val, config.types[i])! - row_data << field - } - ret << row_data - } - - return ret -} - -// sql stmt - -pub fn (db DB) insert(table string, data orm.QueryData) ! { - query, converted_data := orm.orm_stmt_gen(.default, table, '"', .insert, true, '$', - 1, data, orm.QueryData{}) - pg_stmt_worker(db, query, converted_data, orm.QueryData{})! -} - -pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.default, table, '"', .update, true, '$', 1, data, where) - pg_stmt_worker(db, query, data, where)! -} - -pub fn (db DB) delete(table string, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.default, table, '"', .delete, true, '$', 1, orm.QueryData{}, - where) - pg_stmt_worker(db, query, orm.QueryData{}, where)! -} - -pub fn (db DB) last_id() int { - query := 'SELECT LASTVAL();' - - return db.q_int(query) or { 0 } -} - -// table - -pub fn (db DB) create(table string, fields []orm.TableField) ! { - query := orm.orm_table_gen(table, '"', true, 0, fields, pg_type_from_v, false) or { return err } - pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -pub fn (db DB) drop(table string) ! { - query := 'DROP TABLE "${table}";' - pg_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -// utils - -fn pg_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ![]Row { - mut param_types := []u32{} - mut param_vals := []&char{} - mut param_lens := []int{} - mut param_formats := []int{} - - pg_stmt_binder(mut param_types, mut param_vals, mut param_lens, mut param_formats, - data) - pg_stmt_binder(mut param_types, mut param_vals, mut param_lens, mut param_formats, - where) - - res := C.PQexecParams(db.conn, &char(query.str), param_vals.len, param_types.data, - param_vals.data, param_lens.data, param_formats.data, 0) // here, the last 0 means require text results, 1 - binary results - return db.handle_error_or_result(res, 'orm_stmt_worker') -} - -fn pg_stmt_binder(mut types []u32, mut vals []&char, mut lens []int, mut formats []int, d orm.QueryData) { - for data in d.data { - pg_stmt_match(mut types, mut vals, mut lens, mut formats, data) - } -} - -fn pg_stmt_match(mut types []u32, mut vals []&char, mut lens []int, mut formats []int, data orm.Primitive) { - match data { - bool { - types << u32(Oid.t_bool) - vals << &char(&data) - lens << int(sizeof(bool)) - formats << 1 - } - u8 { - types << u32(Oid.t_char) - vals << &char(&data) - lens << int(sizeof(u8)) - formats << 1 - } - u16 { - types << u32(Oid.t_int2) - num := conv.hton16(data) - vals << &char(&num) - lens << int(sizeof(u16)) - formats << 1 - } - u32 { - types << u32(Oid.t_int4) - num := conv.hton32(data) - vals << &char(&num) - lens << int(sizeof(u32)) - formats << 1 - } - u64 { - types << u32(Oid.t_int8) - num := conv.hton64(data) - vals << &char(&num) - lens << int(sizeof(u64)) - formats << 1 - } - i8 { - types << u32(Oid.t_char) - vals << &char(&data) - lens << int(sizeof(i8)) - formats << 1 - } - i16 { - types << u32(Oid.t_int2) - num := conv.hton16(u16(data)) - vals << &char(&num) - lens << int(sizeof(i16)) - formats << 1 - } - int { - types << u32(Oid.t_int4) - num := conv.hton32(u32(data)) - vals << &char(&num) - lens << int(sizeof(int)) - formats << 1 - } - i64 { - types << u32(Oid.t_int8) - num := conv.hton64(u64(data)) - vals << &char(&num) - lens << int(sizeof(i64)) - formats << 1 - } - f32 { - types << u32(Oid.t_float4) - vals << &char(&data) - lens << int(sizeof(f32)) - formats << 1 - } - f64 { - types << u32(Oid.t_float8) - vals << &char(&data) - lens << int(sizeof(f64)) - formats << 1 - } - string { - // If paramTypes is NULL, or any particular element in the array is zero, - // the server infers a data type for the parameter symbol in the same way - // it would do for an untyped literal string. - types << u32(0) - vals << &char(data.str) - lens << data.len - formats << 0 - } - time.Time { - datetime := data.format_ss() - types << u32(0) - vals << &char(datetime.str) - lens << datetime.len - formats << 0 - } - orm.InfixType { - pg_stmt_match(mut types, mut vals, mut lens, mut formats, data.right) - } - } -} - -fn pg_type_from_v(typ int) !string { - str := match typ { - orm.type_idx['i8'], orm.type_idx['i16'], orm.type_idx['u8'], orm.type_idx['u16'] { - 'SMALLINT' - } - orm.type_idx['bool'] { - 'BOOLEAN' - } - orm.type_idx['int'], orm.type_idx['u32'] { - 'INT' - } - orm.time { - 'TIMESTAMP' - } - orm.type_idx['i64'], orm.type_idx['u64'] { - 'BIGINT' - } - orm.float[0] { - 'REAL' - } - orm.float[1] { - 'DOUBLE PRECISION' - } - orm.type_string { - 'TEXT' - } - orm.serial { - 'SERIAL' - } - else { - '' - } - } - if str == '' { - return error('Unknown type ${typ}') - } - return str -} - -fn str_to_primitive(str string, typ int) !orm.Primitive { - match typ { - // bool - orm.type_idx['bool'] { - return orm.Primitive(str == 't') - } - // i8 - orm.type_idx['i8'] { - return orm.Primitive(str.i8()) - } - // i16 - orm.type_idx['i16'] { - return orm.Primitive(str.i16()) - } - // int - orm.type_idx['int'] { - return orm.Primitive(str.int()) - } - // i64 - orm.type_idx['i64'] { - return orm.Primitive(str.i64()) - } - // u8 - orm.type_idx['u8'] { - data := str.i8() - return orm.Primitive(*unsafe { &u8(&data) }) - } - // u16 - orm.type_idx['u16'] { - data := str.i16() - return orm.Primitive(*unsafe { &u16(&data) }) - } - // u32 - orm.type_idx['u32'] { - data := str.int() - return orm.Primitive(*unsafe { &u32(&data) }) - } - // u64 - orm.type_idx['u64'] { - data := str.i64() - return orm.Primitive(*unsafe { &u64(&data) }) - } - // f32 - orm.type_idx['f32'] { - return orm.Primitive(str.f32()) - } - // f64 - orm.type_idx['f64'] { - return orm.Primitive(str.f64()) - } - orm.type_string { - return orm.Primitive(str) - } - orm.time { - if str.contains_any(' /:-') { - date_time_str := time.parse(str)! - return orm.Primitive(date_time_str) - } - - timestamp := str.int() - return orm.Primitive(time.unix(timestamp)) - } - else {} - } - return error('Unknown field type ${typ}') -} diff --git a/vlib/pg/pg.v b/vlib/pg/pg.v deleted file mode 100644 index b46902ba2f..0000000000 --- a/vlib/pg/pg.v +++ /dev/null @@ -1,347 +0,0 @@ -module pg - -import io - -$if $pkgconfig('libpq') { - #pkgconfig --cflags --libs libpq -} $else { - #flag -lpq - #flag linux -I/usr/include/postgresql - - #flag darwin -I/opt/local/include/postgresql11 - #flag darwin -L/opt/local/lib/postgresql11 - - #flag darwin -I/usr/local/opt/libpq/include - #flag darwin -L/usr/local/opt/libpq/lib - - #flag darwin -I/opt/homebrew/include - #flag darwin -L/opt/homebrew/lib - - #flag darwin -I/opt/homebrew/opt/libpq/include - #flag darwin -L/opt/homebrew/opt/libpq/lib - - #flag windows -I @VEXEROOT/thirdparty/pg/include - #flag windows -L @VEXEROOT/thirdparty/pg/win64 -} - -// PostgreSQL Source Code -// https://doxygen.postgresql.org/libpq-fe_8h.html -#include - -// for PG_VERSION_NUM, which is defined everywhere at least since PG 9.5 -#include - -// for orm -#include - -#include "@VMODROOT/vlib/pg/compatibility.h" - -pub struct DB { -mut: - conn voidptr = unsafe { nil } -} - -pub struct Row { -pub mut: - vals []string -} - -pub struct Config { -pub: - host string = 'localhost' - port int = 5432 - user string - password string - dbname string -} - -// - -struct C.pg_result {} - -struct C.pg_conn {} - -[typedef] -pub struct C.PGresult {} - -[typedef] -pub struct C.PGconn {} - -pub enum ConnStatusType { - ok = C.CONNECTION_OK - bad = C.CONNECTION_BAD - // Non-blocking mode only below here - // The existence of these should never be relied upon - they should only be used for user feedback or similar purposes. - started = C.CONNECTION_STARTED // Waiting for connection to be made. - made = C.CONNECTION_MADE // Connection OK; waiting to send. - awaiting_response = C.CONNECTION_AWAITING_RESPONSE // Waiting for a response from the postmaster. - auth_ok = C.CONNECTION_AUTH_OK // Received authentication; waiting for backend startup. - setenv = C.CONNECTION_SETENV // Negotiating environment. - ssl_startup = C.CONNECTION_SSL_STARTUP // Negotiating SSL. - needed = C.CONNECTION_NEEDED // Internal state: connect() needed . Available in PG 8 - check_writable = C.CONNECTION_CHECK_WRITABLE // Check if we could make a writable connection. Available since PG 10 - consume = C.CONNECTION_CONSUME // Wait for any pending message and consume them. Available since PG 10 - gss_startup = C.CONNECTION_GSS_STARTUP // Negotiating GSSAPI; available since PG 12 -} - -[typedef] -pub enum ExecStatusType { - empty_query = C.PGRES_EMPTY_QUERY // empty query string was executed - command_ok = C.PGRES_COMMAND_OK // a query command that doesn't return anything was executed properly by the backend - tuples_ok = C.PGRES_TUPLES_OK // a query command that returns tuples was executed properly by the backend, PGresult contains the result tuples - copy_out = C.PGRES_COPY_OUT // Copy Out data transfer in progress - copy_in = C.PGRES_COPY_IN // Copy In data transfer in progress - bad_response = C.PGRES_BAD_RESPONSE // an unexpected response was recv'd from the backend - nonfatal_error = C.PGRES_NONFATAL_ERROR // notice or warning message - fatal_error = C.PGRES_FATAL_ERROR // query failed - copy_both = C.PGRES_COPY_BOTH // Copy In/Out data transfer in progress - single_tuple = C.PGRES_SINGLE_TUPLE // single tuple from larger resultset -} - -// - -fn C.PQconnectdb(const_conninfo &char) &C.PGconn - -fn C.PQstatus(const_conn &C.PGconn) int - -fn C.PQerrorMessage(const_conn &C.PGconn) &char - -fn C.PQexec(res &C.PGconn, const_query &char) &C.PGresult - -// - -fn C.PQgetvalue(const_res &C.PGresult, int, int) &char - -fn C.PQresultStatus(const_res &C.PGresult) int - -fn C.PQntuples(const_res &C.PGresult) int - -fn C.PQnfields(const_res &C.PGresult) int - -// Params: -// const Oid *paramTypes -// const char *const *paramValues -// const int *paramLengths -// const int *paramFormats -fn C.PQexecParams(conn &C.PGconn, const_command &char, nParams int, const_paramTypes &int, const_paramValues &char, const_paramLengths &int, const_paramFormats &int, resultFormat int) &C.PGresult - -fn C.PQputCopyData(conn &C.PGconn, const_buffer &char, nbytes int) int - -fn C.PQputCopyEnd(conn &C.PGconn, const_errmsg &char) int - -fn C.PQgetCopyData(conn &C.PGconn, buffer &&char, async int) int - -// cleanup - -fn C.PQclear(res &C.PGresult) - -fn C.PQfreemem(ptr voidptr) - -fn C.PQfinish(conn &C.PGconn) - -// connect makes a new connection to the database server using -// the parameters from the `Config` structure, returning -// a connection error when something goes wrong -pub fn connect(config Config) !DB { - conninfo := 'host=${config.host} port=${config.port} user=${config.user} dbname=${config.dbname} password=${config.password}' - conn := C.PQconnectdb(&char(conninfo.str)) - if conn == 0 { - return error('libpq memory allocation error') - } - status := unsafe { ConnStatusType(C.PQstatus(conn)) } - if status != .ok { - // We force the construction of a new string as the - // error message will be freed by the next `PQfinish` - // call - c_error_msg := unsafe { C.PQerrorMessage(conn).vstring() } - error_msg := '${c_error_msg}' - C.PQfinish(conn) - return error('Connection to a PG database failed: ${error_msg}') - } - return DB{ - conn: conn - } -} - -fn res_to_rows(res voidptr) []Row { - nr_rows := C.PQntuples(res) - nr_cols := C.PQnfields(res) - - mut rows := []Row{} - for i in 0 .. nr_rows { - mut row := Row{} - for j in 0 .. nr_cols { - val := C.PQgetvalue(res, i, j) - sval := unsafe { val.vstring() } - row.vals << sval - } - rows << row - } - - C.PQclear(res) - return rows -} - -// close frees the underlying resource allocated by the database connection -pub fn (db DB) close() { - C.PQfinish(db.conn) -} - -// q_int submit a command to the database server and -// returns an the first field in the first tuple -// converted to an int. If no row is found or on -// command failure, an error is returned -pub fn (db DB) q_int(query string) !int { - rows := db.exec(query)! - if rows.len == 0 { - return error('q_int "${query}" not found') - } - row := rows[0] - if row.vals.len == 0 { - return 0 - } - val := row.vals[0] - return val.int() -} - -// q_string submit a command to the database server and -// returns an the first field in the first tuple -// as a string. If no row is found or on -// command failure, an error is returned -pub fn (db DB) q_string(query string) !string { - rows := db.exec(query)! - if rows.len == 0 { - return error('q_string "${query}" not found') - } - row := rows[0] - if row.vals.len == 0 { - return '' - } - val := row.vals[0] - return val -} - -// q_strings submit a command to the database server and -// returns the resulting row set. Alias of `exec` -pub fn (db DB) q_strings(query string) ![]Row { - return db.exec(query) -} - -// exec submit a command to the database server and wait -// for the result, returning an error on failure and a -// row set on success -pub fn (db DB) exec(query string) ![]Row { - res := C.PQexec(db.conn, &char(query.str)) - return db.handle_error_or_result(res, 'exec') -} - -fn rows_first_or_empty(rows []Row) !Row { - if rows.len == 0 { - return error('no row') - } - return rows[0] -} - -pub fn (db DB) exec_one(query string) !Row { - res := C.PQexec(db.conn, &char(query.str)) - e := unsafe { C.PQerrorMessage(db.conn).vstring() } - if e != '' { - return error('pg exec error: "${e}"') - } - row := rows_first_or_empty(res_to_rows(res))! - return row -} - -// exec_param_many executes a query with the provided parameters -pub fn (db DB) exec_param_many(query string, params []string) ![]Row { - unsafe { - mut param_vals := []&char{len: params.len} - for i in 0 .. params.len { - param_vals[i] = &char(params[i].str) - } - - res := C.PQexecParams(db.conn, &char(query.str), params.len, 0, param_vals.data, - 0, 0, 0) - return db.handle_error_or_result(res, 'exec_param_many') - } -} - -pub fn (db DB) exec_param2(query string, param string, param2 string) ![]Row { - return db.exec_param_many(query, [param, param2]) -} - -pub fn (db DB) exec_param(query string, param string) ![]Row { - return db.exec_param_many(query, [param]) -} - -fn (db DB) handle_error_or_result(res voidptr, elabel string) ![]Row { - e := unsafe { C.PQerrorMessage(db.conn).vstring() } - if e != '' { - C.PQclear(res) - return error('pg ${elabel} error:\n${e}') - } - return res_to_rows(res) -} - -// copy_expert execute COPY commands -// https://www.postgresql.org/docs/9.5/libpq-copy.html -pub fn (db DB) copy_expert(query string, mut file io.ReaderWriter) !int { - mut res := C.PQexec(db.conn, &char(query.str)) - status := unsafe { ExecStatusType(C.PQresultStatus(res)) } - defer { - C.PQclear(res) - } - - e := unsafe { C.PQerrorMessage(db.conn).vstring() } - if e != '' { - return error('pg copy error:\n${e}') - } - - if status == .copy_in { - mut buf := []u8{len: 4 * 1024} - for { - n := file.read(mut buf) or { - msg := 'pg copy error: Failed to read from input' - C.PQputCopyEnd(db.conn, &char(msg.str)) - return err - } - if n <= 0 { - break - } - - code := C.PQputCopyData(db.conn, buf.data, n) - if code == -1 { - return error('pg copy error: Failed to send data, code=${code}') - } - } - - code := C.PQputCopyEnd(db.conn, &char(0)) - - if code != 1 { - return error('pg copy error: Failed to finish copy command, code: ${code}') - } - } else if status == .copy_out { - for { - address := &char(0) - n_bytes := C.PQgetCopyData(db.conn, &address, 0) - if n_bytes > 0 { - mut local_buf := []u8{len: n_bytes} - unsafe { C.memcpy(&u8(local_buf.data), address, n_bytes) } - file.write(local_buf) or { - C.PQfreemem(address) - return err - } - } else if n_bytes == -1 { - break - } else if n_bytes == -2 { - // consult PQerrorMessage for the reason - return error('pg copy error: read error') - } - if address != 0 { - C.PQfreemem(address) - } - } - } - - return 0 -} diff --git a/vlib/pg/z_deprecated.v b/vlib/pg/z_deprecated.v deleted file mode 100644 index 594326d6a6..0000000000 --- a/vlib/pg/z_deprecated.v +++ /dev/null @@ -1,3 +0,0 @@ -[deprecated: 'import db.pg instead'] -[deprecated_after: '2023-02-01'] -module pg diff --git a/vlib/sqlite/README.md b/vlib/sqlite/README.md deleted file mode 100644 index f6b35963a0..0000000000 --- a/vlib/sqlite/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## Description - -The `sqlite` module has been moved to `db.sqlite`. -Update your code to do: `import db.sqlite` instead. diff --git a/vlib/sqlite/orm.v b/vlib/sqlite/orm.v deleted file mode 100644 index 6f8e114097..0000000000 --- a/vlib/sqlite/orm.v +++ /dev/null @@ -1,179 +0,0 @@ -module sqlite - -import orm -import time - -// sql expr - -pub fn (db DB) @select(config orm.SelectConfig, data orm.QueryData, where orm.QueryData) ![][]orm.Primitive { - // 1. Create query and bind necessary data - query := orm.orm_select_gen(config, '`', true, '?', 1, where) - $if trace_sqlite ? { - eprintln('> @select query: "${query}"') - } - stmt := db.new_init_stmt(query)! - defer { - stmt.finalize() - } - mut c := 1 - sqlite_stmt_binder(stmt, where, query, mut c)! - sqlite_stmt_binder(stmt, data, query, mut c)! - - mut ret := [][]orm.Primitive{} - - if config.is_count { - // 2. Get count of returned values & add it to ret array - step := stmt.step() - if step !in [sqlite_row, sqlite_ok, sqlite_done] { - return db.error_message(step, query) - } - count := stmt.sqlite_select_column(0, 8)! - ret << [count] - return ret - } - for { - // 2. Parse returned values - step := stmt.step() - if step == sqlite_done { - break - } - if step != sqlite_ok && step != sqlite_row { - break - } - mut row := []orm.Primitive{} - for i, typ in config.types { - primitive := stmt.sqlite_select_column(i, typ)! - row << primitive - } - ret << row - } - return ret -} - -// sql stmt - -pub fn (db DB) insert(table string, data orm.QueryData) ! { - query, converted_data := orm.orm_stmt_gen(.sqlite, table, '`', .insert, true, '?', - 1, data, orm.QueryData{}) - sqlite_stmt_worker(db, query, converted_data, orm.QueryData{})! -} - -pub fn (db DB) update(table string, data orm.QueryData, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.sqlite, table, '`', .update, true, '?', 1, data, where) - sqlite_stmt_worker(db, query, data, where)! -} - -pub fn (db DB) delete(table string, where orm.QueryData) ! { - query, _ := orm.orm_stmt_gen(.sqlite, table, '`', .delete, true, '?', 1, orm.QueryData{}, - where) - sqlite_stmt_worker(db, query, orm.QueryData{}, where)! -} - -pub fn (db DB) last_id() int { - query := 'SELECT last_insert_rowid();' - - return db.q_int(query) -} - -// table -pub fn (db DB) create(table string, fields []orm.TableField) ! { - query := orm.orm_table_gen(table, '`', true, 0, fields, sqlite_type_from_v, false) or { - return err - } - sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -pub fn (db DB) drop(table string) ! { - query := 'DROP TABLE `${table}`;' - sqlite_stmt_worker(db, query, orm.QueryData{}, orm.QueryData{})! -} - -// helper - -// Executes query and bind prepared statement data directly -fn sqlite_stmt_worker(db DB, query string, data orm.QueryData, where orm.QueryData) ! { - $if trace_sqlite ? { - eprintln('> sqlite_stmt_worker query: "${query}"') - } - stmt := db.new_init_stmt(query)! - defer { - stmt.finalize() - } - mut c := 1 - sqlite_stmt_binder(stmt, data, query, mut c)! - sqlite_stmt_binder(stmt, where, query, mut c)! - stmt.orm_step(query)! -} - -// Binds all values of d in the prepared statement -fn sqlite_stmt_binder(stmt Stmt, d orm.QueryData, query string, mut c &int) ! { - for data in d.data { - err := bind(stmt, c, data) - - if err != 0 { - return stmt.db.error_message(err, query) - } - c++ - } -} - -// Universal bind function -fn bind(stmt Stmt, c &int, data orm.Primitive) int { - mut err := 0 - match data { - i8, i16, int, u8, u16, u32, bool { - err = stmt.bind_int(c, int(data)) - } - i64, u64 { - err = stmt.bind_i64(c, i64(data)) - } - f32, f64 { - err = stmt.bind_f64(c, unsafe { *(&f64(&data)) }) - } - string { - err = stmt.bind_text(c, data) - } - time.Time { - err = stmt.bind_int(c, int(data.unix)) - } - orm.InfixType { - err = bind(stmt, c, data.right) - } - } - return err -} - -// Selects column in result and converts it to an orm.Primitive -fn (stmt Stmt) sqlite_select_column(idx int, typ int) !orm.Primitive { - mut primitive := orm.Primitive(0) - - if typ in orm.nums || typ == -1 { - primitive = stmt.get_int(idx) - } else if typ in orm.num64 { - primitive = stmt.get_i64(idx) - } else if typ in orm.float { - primitive = stmt.get_f64(idx) - } else if typ == orm.type_string { - primitive = stmt.get_text(idx).clone() - } else if typ == orm.time { - d := stmt.get_int(idx) - primitive = time.unix(d) - } else { - return error('Unknown type ${typ}') - } - - return primitive -} - -// Convert type int to sql type string -fn sqlite_type_from_v(typ int) !string { - return if typ in orm.nums || typ < 0 || typ in orm.num64 || typ == orm.time { - 'INTEGER' - } else if typ in orm.float { - 'REAL' - } else if typ == orm.type_string { - 'TEXT' - } else { - error('Unknown type ${typ}') - } -} diff --git a/vlib/sqlite/result_code.v b/vlib/sqlite/result_code.v deleted file mode 100644 index f793d283ed..0000000000 --- a/vlib/sqlite/result_code.v +++ /dev/null @@ -1,118 +0,0 @@ -module sqlite - -// Result represents Sqlite Result and Error Codes -// see https://www.sqlite.org/rescode.html -pub enum Result { - ok = 0 - error = 1 - internal = 2 - perm = 3 - abort = 4 - busy = 5 - locked = 6 - nomem = 7 - readonly = 8 - interrupt = 9 - ioerr = 10 - corrupt = 11 - notfound = 12 - full = 13 - cantopen = 14 - protocol = 15 - empty = 16 - schema = 17 - toobig = 18 - constraint = 19 - mismatch = 20 - misuse = 21 - nolfs = 22 - auth = 23 - format = 24 - range = 25 - notadb = 26 - notice = 27 - warning = 28 - row = 100 - done = 101 - ok_load_permanently = 256 - error_missing_collseq = 257 - busy_recovery = 261 - locked_sharedcache = 262 - readonly_recovery = 264 - ioerr_read = 266 - corrupt_vtab = 267 - cantopen_notempdir = 270 - constraint_check = 275 - notice_recover_wal = 283 - warning_autoindex = 284 - error_retry = 513 - abort_rollback = 516 - busy_snapshot = 517 - locked_vtab = 518 - readonly_cantlock = 520 - ioerr_short_read = 522 - corrupt_sequence = 523 - cantopen_isdir = 526 - constraint_commithook = 531 - notice_recover_rollback = 539 - error_snapshot = 769 - busy_timeout = 773 - readonly_rollback = 776 - ioerr_write = 778 - corrupt_index = 779 - cantopen_fullpath = 782 - constraint_foreignkey = 787 - readonly_dbmoved = 1032 - ioerr_fsync = 1034 - cantopen_convpath = 1038 - constraint_function = 1043 - readonly_cantinit = 1288 - ioerr_dir_fsync = 1290 - cantopen_dirtywal = 1294 - constraint_notnull = 1299 - readonly_directory = 1544 - ioerr_truncate = 1546 - cantopen_symlink = 1550 - constraint_primarykey = 1555 - ioerr_fstat = 1802 - constraint_trigger = 1811 - ioerr_unlock = 2058 - constraint_unique = 2067 - ioerr_rdlock = 2314 - constraint_vtab = 2323 - ioerr_delete = 2570 - constraint_rowid = 2579 - ioerr_blocked = 2826 - constraint_pinned = 2835 - ioerr_nomem = 3082 - ioerr_access = 3338 - ioerr_checkreservedlock = 3594 - ioerr_lock = 3850 - ioerr_close = 4106 - ioerr_dir_close = 4362 - ioerr_shmopen = 4618 - ioerr_shmsize = 4874 - ioerr_shmlock = 5130 - ioerr_shmmap = 5386 - ioerr_seek = 5642 - ioerr_delete_noent = 5898 - ioerr_mmap = 6154 - ioerr_gettemppath = 6410 - ioerr_convpath = 6666 - ioerr_vnode = 6922 - ioerr_auth = 7178 - ioerr_begin_atomic = 7434 - ioerr_commit_atomic = 7690 - ioerr_rollback_atomic = 7946 - ioerr_data = 8202 -} - -// is_error checks if it is an error code. -pub fn (r Result) is_error() bool { - return r !in [.ok, .row, .done] -} - -// is_error checks if `code` is an error code. -pub fn is_error(code int) bool { - return unsafe { Result(code).is_error() } -} diff --git a/vlib/sqlite/sqlite.v b/vlib/sqlite/sqlite.v deleted file mode 100644 index 664957ef8d..0000000000 --- a/vlib/sqlite/sqlite.v +++ /dev/null @@ -1,342 +0,0 @@ -module sqlite - -$if freebsd || openbsd { - #flag -I/usr/local/include - #flag -L/usr/local/lib -} -$if windows { - #flag windows -I@VEXEROOT/thirdparty/sqlite - #flag windows -L@VEXEROOT/thirdparty/sqlite - #flag windows @VEXEROOT/thirdparty/sqlite/sqlite3.o -} $else { - #flag -lsqlite3 -} - -#include "sqlite3.h" - -// https://www.sqlite.org/rescode.html -pub const ( - sqlite_ok = 0 - sqlite_error = 1 - sqlite_row = 100 - sqlite_done = 101 - sqlite_cantopen = 14 - sqlite_ioerr_read = 266 - sqlite_ioerr_short_read = 522 - sqlite_ioerr_write = 778 - sqlite_ioerr_fsync = 1034 - sqlite_ioerr_fstat = 1802 - sqlite_ioerr_delete = 2570 - - sqlite_open_main_db = 0x00000100 - sqlite_open_temp_db = 0x00000200 - sqlite_open_transient_db = 0x00000400 - sqlite_open_main_journal = 0x00000800 - sqlite_open_temp_journal = 0x00001000 - sqlite_open_subjournal = 0x00002000 - sqlite_open_super_journal = 0x00004000 - sqlite_open_wal = 0x00080000 -) - -pub enum SyncMode { - off - normal - full -} - -pub enum JournalMode { - off - delete - truncate - persist - memory -} - -pub struct C.sqlite3 { -} - -pub struct C.sqlite3_stmt { -} - -[heap] -pub struct Stmt { - stmt &C.sqlite3_stmt = unsafe { nil } - db &DB = unsafe { nil } -} - -pub struct SQLError { - MessageError -} - -// -[heap] -pub struct DB { -pub mut: - is_open bool -mut: - conn &C.sqlite3 = unsafe { nil } -} - -pub fn (db &DB) str() string { - return 'sqlite.DB{ conn: ' + ptr_str(db.conn) + ' }' -} - -pub struct Row { -pub mut: - vals []string -} - -// -fn C.sqlite3_open(&char, &&C.sqlite3) int - -fn C.sqlite3_close(&C.sqlite3) int - -fn C.sqlite3_busy_timeout(db &C.sqlite3, ms int) int - -fn C.sqlite3_last_insert_rowid(&C.sqlite3) i64 - -// -fn C.sqlite3_prepare_v2(&C.sqlite3, &char, int, &&C.sqlite3_stmt, &&char) int - -fn C.sqlite3_step(&C.sqlite3_stmt) int - -fn C.sqlite3_finalize(&C.sqlite3_stmt) int - -// -fn C.sqlite3_column_name(&C.sqlite3_stmt, int) &char - -fn C.sqlite3_column_text(&C.sqlite3_stmt, int) &u8 - -fn C.sqlite3_column_int(&C.sqlite3_stmt, int) int - -fn C.sqlite3_column_int64(&C.sqlite3_stmt, int) i64 - -fn C.sqlite3_column_double(&C.sqlite3_stmt, int) f64 - -fn C.sqlite3_column_count(&C.sqlite3_stmt) int - -// -fn C.sqlite3_errstr(int) &char - -fn C.sqlite3_errmsg(&C.sqlite3) &char - -fn C.sqlite3_free(voidptr) - -fn C.sqlite3_changes(&C.sqlite3) int - -// connect Opens the connection with a database. -pub fn connect(path string) !DB { - db := &C.sqlite3(unsafe { nil }) - code := C.sqlite3_open(&char(path.str), &db) - if code != 0 { - return &SQLError{ - msg: unsafe { cstring_to_vstring(&char(C.sqlite3_errstr(code))) } - code: code - } - } - return DB{ - conn: db - is_open: true - } -} - -// close Closes the DB. -// TODO: For all functions, determine whether the connection is -// closed first, and determine what to do if it is -pub fn (mut db DB) close() !bool { - code := C.sqlite3_close(db.conn) - if code == 0 { - db.is_open = false - } else { - return &SQLError{ - msg: unsafe { cstring_to_vstring(&char(C.sqlite3_errstr(code))) } - code: code - } - } - return true // successfully closed -} - -// Only for V ORM -fn get_int_from_stmt(stmt &C.sqlite3_stmt) int { - x := C.sqlite3_step(stmt) - if x != C.SQLITE_OK && x != C.SQLITE_DONE { - C.puts(C.sqlite3_errstr(x)) - } - - res := C.sqlite3_column_int(stmt, 0) - C.sqlite3_finalize(stmt) - return res -} - -// last_insert_rowid returns last inserted rowid -// https://www.sqlite.org/c3ref/last_insert_rowid.html -pub fn (db &DB) last_insert_rowid() i64 { - return C.sqlite3_last_insert_rowid(db.conn) -} - -// get_affected_rows_count returns `sqlite changes()` meaning amount of rows affected by most recent sql query -pub fn (db &DB) get_affected_rows_count() int { - return C.sqlite3_changes(db.conn) -} - -// Returns a single cell with value int. -pub fn (db &DB) q_int(query string) int { - stmt := &C.sqlite3_stmt(unsafe { nil }) - defer { - C.sqlite3_finalize(stmt) - } - C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - C.sqlite3_step(stmt) - - res := C.sqlite3_column_int(stmt, 0) - return res -} - -// Returns a single cell with value string. -pub fn (db &DB) q_string(query string) string { - stmt := &C.sqlite3_stmt(unsafe { nil }) - defer { - C.sqlite3_finalize(stmt) - } - C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - C.sqlite3_step(stmt) - - val := unsafe { &u8(C.sqlite3_column_text(stmt, 0)) } - return if val != &u8(0) { unsafe { tos_clone(val) } } else { '' } -} - -// Execute the query on db, return an array of all the results, alongside any result code. -// Result codes: https://www.sqlite.org/rescode.html -[manualfree] -pub fn (db &DB) exec(query string) ([]Row, int) { - stmt := &C.sqlite3_stmt(unsafe { nil }) - defer { - C.sqlite3_finalize(stmt) - } - C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - nr_cols := C.sqlite3_column_count(stmt) - mut res := 0 - mut rows := []Row{} - for { - res = C.sqlite3_step(stmt) - // Result Code SQLITE_ROW; Another row is available - if res != 100 { - // C.puts(C.sqlite3_errstr(res)) - break - } - mut row := Row{} - for i in 0 .. nr_cols { - val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) } - if val == &u8(0) { - row.vals << '' - } else { - row.vals << unsafe { tos_clone(val) } - } - } - rows << row - } - return rows, res -} - -// Execute a query, handle error code -// Return the first row from the resulting table -[manualfree] -pub fn (db &DB) exec_one(query string) !Row { - rows, code := db.exec(query) - defer { - unsafe { rows.free() } - } - if rows.len == 0 { - return &SQLError{ - msg: 'No rows' - code: code - } - } else if code != 101 { - return &SQLError{ - msg: unsafe { cstring_to_vstring(&char(C.sqlite3_errstr(code))) } - code: code - } - } - res := rows[0] - return res -} - -[manualfree] -pub fn (db &DB) error_message(code int, query string) IError { - errmsg := unsafe { cstring_to_vstring(&char(C.sqlite3_errmsg(db.conn))) } - msg := '${errmsg} (${code}) (${query})' - unsafe { errmsg.free() } - return SQLError{ - msg: msg - code: code - } -} - -// Execute a query returning only the result code. -// In case you don't expect any row results, but still want a result code. -// e.g. INSERT INTO ... VALUES (...) -pub fn (db &DB) exec_none(query string) int { - stmt := &C.sqlite3_stmt(unsafe { nil }) - C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - code := C.sqlite3_step(stmt) - C.sqlite3_finalize(stmt) - return code -} - -/* -TODO -pub fn (db &DB) exec_param(query string, param string) []Row { -} -*/ - -// Issue a "create table if not exists" command to the db. -// Creates table named 'table_name', with columns generated from 'columns' array. -// Default columns type will be TEXT. -pub fn (db &DB) create_table(table_name string, columns []string) { - db.exec('create table if not exists ${table_name} (' + columns.join(',\n') + ')') -} - -// Set a busy timeout in milliseconds. -// Sleeps for a specified amount of time when a table is locked. The handler -// will sleep multiple times until at least "ms" milliseconds of sleeping have accumulated. -// (see https://www.sqlite.org/c3ref/busy_timeout.html) -pub fn (db &DB) busy_timeout(ms int) int { - return C.sqlite3_busy_timeout(db.conn, ms) -} - -// Sets disk synchronization mode, -// which controls how aggressively SQLite will write data to physical storage. -// off: No syncs at all. (fastest) -// normal: Sync after each sequence of critical disk operations. -// full: Sync after each critical disk operation (slowest). -pub fn (db &DB) synchronization_mode(sync_mode SyncMode) { - if sync_mode == .off { - db.exec('pragma synchronous = OFF;') - } else if sync_mode == .full { - db.exec('pragma synchronous = FULL;') - } else { - db.exec('pragma synchronous = NORMAL;') - } -} - -// Controls how the journal file is stored and processed. -// off: No journal record is kept. (fastest) -// memory: Journal record is held in memory, rather than on disk. -// delete: At the conclusion of a transaction, journal file is deleted. -// truncate: Journal file is truncated to a length of zero bytes. -// persist: Journal file is left in place, but the header is overwritten to indicate journal is no longer valid. -pub fn (db &DB) journal_mode(journal_mode JournalMode) { - if journal_mode == .off { - db.exec('pragma journal_mode = OFF;') - } else if journal_mode == .delete { - db.exec('pragma journal_mode = DELETE;') - } else if journal_mode == .truncate { - db.exec('pragma journal_mode = TRUNCATE;') - } else if journal_mode == .persist { - db.exec('pragma journal_mode = PERSIST;') - } else if journal_mode == .memory { - db.exec('pragma journal_mode = MEMORY;') - } else { - db.exec('pragma journal_mode = MEMORY;') - } -} diff --git a/vlib/sqlite/stmt.v b/vlib/sqlite/stmt.v deleted file mode 100644 index 74ebc3be82..0000000000 --- a/vlib/sqlite/stmt.v +++ /dev/null @@ -1,78 +0,0 @@ -module sqlite - -fn C.sqlite3_bind_double(&C.sqlite3_stmt, int, f64) int -fn C.sqlite3_bind_int(&C.sqlite3_stmt, int, int) int -fn C.sqlite3_bind_int64(&C.sqlite3_stmt, int, i64) int -fn C.sqlite3_bind_text(&C.sqlite3_stmt, int, &char, int, voidptr) int - -// Only for V ORM -fn (db &DB) init_stmt(query string) (&C.sqlite3_stmt, int) { - // println('init_stmt("$query")') - stmt := &C.sqlite3_stmt(0) - err := C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0) - return stmt, err -} - -fn (db &DB) new_init_stmt(query string) !Stmt { - stmt, err := db.init_stmt(query) - if err != sqlite_ok { - return db.error_message(err, query) - } - return Stmt{stmt, db} -} - -fn (stmt &Stmt) bind_int(idx int, v int) int { - return C.sqlite3_bind_int(stmt.stmt, idx, v) -} - -fn (stmt &Stmt) bind_i64(idx int, v i64) int { - return C.sqlite3_bind_int64(stmt.stmt, idx, v) -} - -fn (stmt &Stmt) bind_f64(idx int, v f64) int { - return C.sqlite3_bind_double(stmt.stmt, idx, v) -} - -fn (stmt &Stmt) bind_text(idx int, s string) int { - return C.sqlite3_bind_text(stmt.stmt, idx, voidptr(s.str), s.len, 0) -} - -fn (stmt &Stmt) get_int(idx int) int { - return C.sqlite3_column_int(stmt.stmt, idx) -} - -fn (stmt &Stmt) get_i64(idx int) i64 { - return C.sqlite3_column_int64(stmt.stmt, idx) -} - -fn (stmt &Stmt) get_f64(idx int) f64 { - return C.sqlite3_column_double(stmt.stmt, idx) -} - -fn (stmt &Stmt) get_text(idx int) string { - b := &char(C.sqlite3_column_text(stmt.stmt, idx)) - - if b == &char(0) { - return '' - } - return unsafe { b.vstring() } -} - -fn (stmt &Stmt) get_count() int { - return C.sqlite3_column_count(stmt.stmt) -} - -fn (stmt &Stmt) step() int { - return C.sqlite3_step(stmt.stmt) -} - -fn (stmt &Stmt) orm_step(query string) ! { - res := stmt.step() - if res != sqlite_ok && res != sqlite_done && res != sqlite_row { - return stmt.db.error_message(res, query) - } -} - -fn (stmt &Stmt) finalize() { - C.sqlite3_finalize(stmt.stmt) -} diff --git a/vlib/sqlite/vfs_lowlevel.v b/vlib/sqlite/vfs_lowlevel.v deleted file mode 100644 index 3a0b512f2c..0000000000 --- a/vlib/sqlite/vfs_lowlevel.v +++ /dev/null @@ -1,166 +0,0 @@ -module sqlite - -type Sig1 = fn (&C.sqlite3_file, &i64) int // https://github.com/vlang/v/issues/16291 - -type Sig2 = fn (&Sqlite3_file, &int) int // https://github.com/vlang/v/issues/16291 - -pub type Sqlite3_file = C.sqlite3_file - -// https://www.sqlite.org/c3ref/file.html -pub struct C.sqlite3_file { -pub mut: - pMethods &C.sqlite3_io_methods // Methods for an open file -} - -// https://www.sqlite.org/c3ref/io_methods.html -[heap] -pub struct C.sqlite3_io_methods { -mut: - // version 1 and later fields - iVersion int - - xClose fn (&Sqlite3_file) int - xRead fn (&Sqlite3_file, voidptr, int, i64) int - xWrite fn (&Sqlite3_file, voidptr, int, i64) int - xTruncate fn (&Sqlite3_file, i64) int - xSync fn (&Sqlite3_file, int) int - xFileSize Sig1 - xLock fn (&Sqlite3_file, int) int - xUnlock fn (&Sqlite3_file, int) int - xCheckReservedLock Sig2 - xFileControl fn (&Sqlite3_file, int, voidptr) int - xSectorSize fn (&Sqlite3_file) int - xDeviceCharacteristics fn (&Sqlite3_file) int - // version 2 and later fields - xShmMap fn (&Sqlite3_file, int, int, int, &voidptr) int - xShmLock fn (&Sqlite3_file, int, int, int) int - xShmBarrier fn (&Sqlite3_file) - xShmUnmap fn (&Sqlite3_file, int) int - // version 3 and later fields - xFetch fn (&Sqlite3_file, i64, int, &voidptr) int - xUnfetch fn (&Sqlite3_file, i64, voidptr) int -} - -pub type Sqlite3_io_methods = C.sqlite3_io_methods - -// https://www.sqlite.org/c3ref/vfs.html -type Fn_sqlite3_syscall_ptr = fn () - -pub type Sqlite3_vfs = C.sqlite3_vfs - -[heap] -pub struct C.sqlite3_vfs { -pub mut: - // version 1 and later fields - iVersion int // Structure version number (currently 3) - szOsFile int // Size of subclassed sqlite3_file - mxPathname int // Maximum file pathname length - pNext &Sqlite3_vfs // Next registered VFS - zName &char // Name of this virtual file system - pAppData voidptr // Pointer to application-specific data - - xOpen fn (&Sqlite3_vfs, &char, &Sqlite3_file, int, &int) int - xDelete fn (&Sqlite3_vfs, &char, int) int - - xAccess fn (&Sqlite3_vfs, &char, int, &int) int - xFullPathname fn (&Sqlite3_vfs, &char, int, &char) int - xDlOpen fn (&Sqlite3_vfs, &char) voidptr - xDlError fn (&Sqlite3_vfs, int, &char) - xDlSym fn (&Sqlite3_vfs, voidptr, &char) voidptr // to fn accepting void and returning - xDlClose fn (&Sqlite3_vfs, voidptr) - xRandomness fn (&Sqlite3_vfs, int, &char) int - xSleep fn (&Sqlite3_vfs, int) int - xCurrentTime fn (&Sqlite3_vfs, &f64) int - xGetLastError fn (&Sqlite3_vfs, int, &char) int - // version two and later only fields - xCurrentTimeInt64 fn (&Sqlite3_vfs, &i64) int - // version three and later only fields - xSetSystemCall fn (&Sqlite3_vfs, &char, Fn_sqlite3_syscall_ptr) int - xGetSystemCall fn (&Sqlite3_vfs, &char) Fn_sqlite3_syscall_ptr - xNextSystemCall fn (&Sqlite3_vfs, &char) &char -} - -// https://www.sqlite.org/c3ref/vfs_find.html -fn C.sqlite3_vfs_find(&char) &C.sqlite3_vfs -fn C.sqlite3_vfs_register(&C.sqlite3_vfs, int) int -fn C.sqlite3_vfs_unregister(&C.sqlite3_vfs) int - -// get_vfs Requests sqlite to return instance of VFS with given name. -// when such vfs is not known, `none` is returned -pub fn get_vfs(name string) !&Sqlite3_vfs { - res := C.sqlite3_vfs_find(name.str) - if res != unsafe { nil } { - return res - } - return error('sqlite3_vfs_find returned 0') -} - -// get_default_vfs Asks sqlite for default VFS instance -pub fn get_default_vfs() !&Sqlite3_vfs { - res := C.sqlite3_vfs_find(unsafe { nil }) - if res != unsafe { nil } { - return res - } - return error('sqlite3_vfs_find(0) returned 0') -} - -// register_as_nondefault Asks sqlite to register VFS passed in receiver argument as the known VFS. -// more info about VFS: https://www.sqlite.org/c3ref/vfs.html -// 'not TODOs' to prevent corruption: https://sqlite.org/howtocorrupt.html -// example VFS: https://www.sqlite.org/src/doc/trunk/src/test_demovfs.c -pub fn (mut v Sqlite3_vfs) register_as_nondefault() ! { - res := C.sqlite3_vfs_register(v, 0) - if sqlite_ok != res { - return error('sqlite3_vfs_register returned ${res}') - } -} - -// unregister Requests sqlite to stop using VFS as passed in receiver argument -pub fn (mut v Sqlite3_vfs) unregister() ! { - res := C.sqlite3_vfs_unregister(v) - if sqlite_ok != res { - return error('sqlite3_vfs_unregister returned ${res}') - } -} - -// https://www.sqlite.org/c3ref/open.html -fn C.sqlite3_open_v2(&char, &&C.sqlite3, int, &char) int - -// https://www.sqlite.org/c3ref/c_open_autoproxy.html -pub enum OpenModeFlag { - readonly = 0x00000001 - readwrite = 0x00000002 - create = 0x00000004 - uri = 0x00000040 - memory = 0x00000080 - nomutex = 0x00008000 - fullmutex = 0x00010000 - sharedcache = 0x00020000 - privatecache = 0x00040000 - exrescode = 0x02000000 - nofollow = 0x01000000 -} - -// connect_full Opens connection to sqlite database. It gives more control than `open`. -// Flags give control over readonly and create decisions. Specific VFS can be chosen. -pub fn connect_full(path string, mode_flags []OpenModeFlag, vfs_name string) !DB { - db := &C.sqlite3(unsafe { nil }) - - mut flags := 0 - - for flag in mode_flags { - flags = flags | int(flag) - } - - code := C.sqlite3_open_v2(&char(path.str), &db, flags, vfs_name.str) - if code != 0 { - return &SQLError{ - msg: unsafe { cstring_to_vstring(&char(C.sqlite3_errstr(code))) } - code: code - } - } - return DB{ - conn: db - is_open: true - } -} diff --git a/vlib/sqlite/z_deprecated.v b/vlib/sqlite/z_deprecated.v deleted file mode 100644 index c44e64b8c8..0000000000 --- a/vlib/sqlite/z_deprecated.v +++ /dev/null @@ -1,7 +0,0 @@ -[deprecated: 'import db.sqlite instead'] -[deprecated_after: '2023-02-01'] -module sqlite - -import db.sqlite - -const use_sqlite_ok = sqlite.sqlite_ok