Warning, /sdk/codevis/thirdparty/soci/docs/utilities.md is written in an unsupported language. File is not indexed.
0001 # Utilities 0002 0003 SOCI provides a portable abstraction for selection of database queries. 0004 0005 ## DDL 0006 0007 SOCI supports some basic methods to construct portable DDL queries. That is, instead of writing explicit SQL statement for creating or modifying tables, it is possible to use dedicated SOCI functions, which prepare appropriate DDL statements behind the scenes, thus enabling the user application to create basic database structures in a way that is portable across different database servers. Note that the actual support for these functions depends on the actual backend implementation. 0008 0009 It is possible to create a new table in a single statement: 0010 0011 ```cpp 0012 sql.create_table("t1").column("i", soci::dt_integer).column("j", soci::dt_integer); 0013 ``` 0014 0015 Above, table "t1" will be created with two columns ("i", "j") of type integer. 0016 0017 It is also possible to build similar statements piece by piece, which is useful if the table structure is computed dynamically: 0018 0019 ```cpp 0020 { 0021 soci::ddl_type ddl = sql.create_table("t2"); 0022 ddl.column("i", soci::dt_integer); 0023 ddl.column("j", soci::dt_integer); 0024 ddl.column("k", soci::dt_integer)("not null"); 0025 ddl.primary_key("t2_pk", "j"); 0026 } 0027 ``` 0028 0029 The actual statement is executed at the end of above block, when the ddl object goes out of scope. The "not null" constraint was added to the definition of column "k" explicitly and in fact any piece of SQL can be inserted this way - with the obvious caveat of having limited portability (the "not null" piece seems to be universaly portable). 0030 0031 Columns can be added to and dropped from already existing tables as well: 0032 0033 ```cpp 0034 sql.add_column("t1", "k", soci::dt_integer); 0035 // or with constraint: 0036 //sql.add_column("t1", "k", soci::dt_integer)("not null"); 0037 0038 sql.drop_column("t1", "i"); 0039 ``` 0040 0041 If needed, precision and scale can be defined with additional integer arguments to functions that create columns: 0042 0043 ```cpp 0044 sql.add_column("t1", "s", soci::dt_string, precision); 0045 sql.add_column("t1", "d", soci::dt_double, precision, scale); 0046 ``` 0047 0048 Tables with foreign keys to each other can be also created: 0049 0050 ```cpp 0051 { 0052 soci::ddl_type ddl = sql.create_table("t3"); 0053 ddl.column("x", soci::dt_integer); 0054 ddl.column("y", soci::dt_integer); 0055 ddl.foreign_key("t3_fk", "x", "t2", "j"); 0056 } 0057 ``` 0058 0059 Tables can be dropped, too: 0060 0061 ```cpp 0062 sql.drop_table("t1"); 0063 sql.drop_table("t3"); 0064 sql.drop_table("t2"); 0065 ``` 0066 0067 Note that due to the differences in the set of types that are actually supported on the target database server, the type mappings, as well as precision and scales, might be different, even in the way that makes them impossible to portably recover with metadata queries. 0068 0069 In the category of portability utilities, the following functions are also available: 0070 0071 ```cpp 0072 sql.empty_blob() 0073 ``` 0074 0075 the above call returns the string containing expression that represents an empty BLOB value in the given target backend. This expression can be used as part of a bigger SQL statement, for example: 0076 0077 ```cpp 0078 sql << "insert into my_table (x) values (" + sql.empty_blob() + ")"; 0079 ``` 0080 0081 and: 0082 0083 ```cpp 0084 sql.nvl() 0085 ``` 0086 0087 the above call returns the string containing the name of the SQL function that implements the NVL or COALESCE operation in the given target backend, for example: 0088 0089 ```cpp 0090 sql << "select name, " + sql.nvl() + "(phone, \'UNKNOWN\') from phone_book"; 0091 ``` 0092 0093 Note: `empty_blob` and `nvl` are implemented in Oracle, PostgreSQL and SQLite3 backends; for other backends their behaviour is as for PostgreSQL. 0094 0095 ## DML 0096 0097 Only two related functions are currently available in this category: 0098 `get_dummy_from_clause()` can be used to construct select statements that don't 0099 operate on any table in a portable way, as while some databases allow simply 0100 omitting the from clause in this case, others -- e.g. Oracle -- still require 0101 providing some syntactically valid from clause even if it is not used. To use 0102 this function, simply append the result of this function to the statement: 0103 0104 ```cpp 0105 double databasePi; 0106 session << ("select 4*atan(1)" + session.get_dummy_from_clause()), 0107 into(databasePi); 0108 ``` 0109 0110 If just the name of the dummy table is needed, and not the full clause, you can 0111 use `get_dummy_from_table()` to obtain it. 0112 0113 Notice that both functions require the session to be connected as their result 0114 depends on the database it is connected to. 0115 0116 ## Database Metadata 0117 0118 It is possible to portably query the database server to obtain basic metadata information. 0119 0120 In order to get the list of table names in the current schema: 0121 0122 ```cpp 0123 std::vector<std::string> names(100); 0124 sql.get_table_names(), into(names); 0125 ``` 0126 0127 alternatively: 0128 0129 ```cpp 0130 std::string name; 0131 soci::statement st = (sql.prepare_table_names(), into(name)); 0132 0133 st.execute(); 0134 while (st.fetch()) 0135 { 0136 // ... 0137 } 0138 ``` 0139 0140 Similarly, to get the description of all columns in the given table: 0141 0142 ```cpp 0143 soci::column_info ci; 0144 soci::statement st = (sql.prepare_column_descriptions(table_name), into(ci)); 0145 0146 st.execute(); 0147 while (st.fetch()) 0148 { 0149 // ci fields describe each column in turn 0150 } 0151 ```