@@ -158,6 +158,16 @@ inline void THROW_ERR_SQLITE_ERROR(Isolate* isolate, int errcode) {
158158 }
159159}
160160
161+ inline MaybeLocal<Value> NullableSQLiteStringToValue (Isolate* isolate,
162+ const char * str) {
163+ if (str == nullptr ) {
164+ return Null (isolate);
165+ }
166+
167+ return String::NewFromUtf8 (isolate, str, NewStringType::kInternalized )
168+ .As <Value>();
169+ }
170+
161171class BackupJob : public ThreadPoolWork {
162172 public:
163173 explicit BackupJob (Environment* env,
@@ -1897,6 +1907,72 @@ void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
18971907 args.GetReturnValue ().Set (result);
18981908}
18991909
1910+ void StatementSync::Columns (const FunctionCallbackInfo<Value>& args) {
1911+ StatementSync* stmt;
1912+ ASSIGN_OR_RETURN_UNWRAP (&stmt, args.This ());
1913+ Environment* env = Environment::GetCurrent (args);
1914+ THROW_AND_RETURN_ON_BAD_STATE (
1915+ env, stmt->IsFinalized (), " statement has been finalized" );
1916+ int num_cols = sqlite3_column_count (stmt->statement_ );
1917+ Isolate* isolate = env->isolate ();
1918+ LocalVector<Value> cols (isolate);
1919+ LocalVector<Name> col_keys (isolate,
1920+ {env->column_string (),
1921+ env->database_string (),
1922+ env->name_string (),
1923+ env->table_string (),
1924+ env->type_string ()});
1925+ Local<Value> value;
1926+
1927+ cols.reserve (num_cols);
1928+ for (int i = 0 ; i < num_cols; ++i) {
1929+ LocalVector<Value> col_values (isolate);
1930+ col_values.reserve (col_keys.size ());
1931+
1932+ if (!NullableSQLiteStringToValue (
1933+ isolate, sqlite3_column_origin_name (stmt->statement_ , i))
1934+ .ToLocal (&value)) {
1935+ return ;
1936+ }
1937+ col_values.emplace_back (value);
1938+
1939+ if (!NullableSQLiteStringToValue (
1940+ isolate, sqlite3_column_database_name (stmt->statement_ , i))
1941+ .ToLocal (&value)) {
1942+ return ;
1943+ }
1944+ col_values.emplace_back (value);
1945+
1946+ if (!stmt->ColumnNameToName (i).ToLocal (&value)) {
1947+ return ;
1948+ }
1949+ col_values.emplace_back (value);
1950+
1951+ if (!NullableSQLiteStringToValue (
1952+ isolate, sqlite3_column_table_name (stmt->statement_ , i))
1953+ .ToLocal (&value)) {
1954+ return ;
1955+ }
1956+ col_values.emplace_back (value);
1957+
1958+ if (!NullableSQLiteStringToValue (
1959+ isolate, sqlite3_column_decltype (stmt->statement_ , i))
1960+ .ToLocal (&value)) {
1961+ return ;
1962+ }
1963+ col_values.emplace_back (value);
1964+
1965+ Local<Object> column = Object::New (isolate,
1966+ Null (isolate),
1967+ col_keys.data (),
1968+ col_values.data (),
1969+ col_keys.size ());
1970+ cols.emplace_back (column);
1971+ }
1972+
1973+ args.GetReturnValue ().Set (Array::New (isolate, cols.data (), cols.size ()));
1974+ }
1975+
19001976void StatementSync::SourceSQLGetter (const FunctionCallbackInfo<Value>& args) {
19011977 StatementSync* stmt;
19021978 ASSIGN_OR_RETURN_UNWRAP (&stmt, args.This ());
@@ -2002,6 +2078,8 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
20022078 SetProtoMethod (isolate, tmpl, " all" , StatementSync::All);
20032079 SetProtoMethod (isolate, tmpl, " get" , StatementSync::Get);
20042080 SetProtoMethod (isolate, tmpl, " run" , StatementSync::Run);
2081+ SetProtoMethodNoSideEffect (
2082+ isolate, tmpl, " columns" , StatementSync::Columns);
20052083 SetSideEffectFreeGetter (isolate,
20062084 tmpl,
20072085 FIXED_ONE_BYTE_STRING (isolate, " sourceSQL" ),
0 commit comments