@@ -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,
@@ -1918,6 +1928,72 @@ void StatementSync::Run(const FunctionCallbackInfo<Value>& args) {
19181928 args.GetReturnValue ().Set (result);
19191929}
19201930
1931+ void StatementSync::Columns (const FunctionCallbackInfo<Value>& args) {
1932+ StatementSync* stmt;
1933+ ASSIGN_OR_RETURN_UNWRAP (&stmt, args.This ());
1934+ Environment* env = Environment::GetCurrent (args);
1935+ THROW_AND_RETURN_ON_BAD_STATE (
1936+ env, stmt->IsFinalized (), " statement has been finalized" );
1937+ int num_cols = sqlite3_column_count (stmt->statement_ );
1938+ Isolate* isolate = env->isolate ();
1939+ LocalVector<Value> cols (isolate);
1940+ LocalVector<Name> col_keys (isolate,
1941+ {env->column_string (),
1942+ env->database_string (),
1943+ env->name_string (),
1944+ env->table_string (),
1945+ env->type_string ()});
1946+ Local<Value> value;
1947+
1948+ cols.reserve (num_cols);
1949+ for (int i = 0 ; i < num_cols; ++i) {
1950+ LocalVector<Value> col_values (isolate);
1951+ col_values.reserve (col_keys.size ());
1952+
1953+ if (!NullableSQLiteStringToValue (
1954+ isolate, sqlite3_column_origin_name (stmt->statement_ , i))
1955+ .ToLocal (&value)) {
1956+ return ;
1957+ }
1958+ col_values.emplace_back (value);
1959+
1960+ if (!NullableSQLiteStringToValue (
1961+ isolate, sqlite3_column_database_name (stmt->statement_ , i))
1962+ .ToLocal (&value)) {
1963+ return ;
1964+ }
1965+ col_values.emplace_back (value);
1966+
1967+ if (!stmt->ColumnNameToName (i).ToLocal (&value)) {
1968+ return ;
1969+ }
1970+ col_values.emplace_back (value);
1971+
1972+ if (!NullableSQLiteStringToValue (
1973+ isolate, sqlite3_column_table_name (stmt->statement_ , i))
1974+ .ToLocal (&value)) {
1975+ return ;
1976+ }
1977+ col_values.emplace_back (value);
1978+
1979+ if (!NullableSQLiteStringToValue (
1980+ isolate, sqlite3_column_decltype (stmt->statement_ , i))
1981+ .ToLocal (&value)) {
1982+ return ;
1983+ }
1984+ col_values.emplace_back (value);
1985+
1986+ Local<Object> column = Object::New (isolate,
1987+ Null (isolate),
1988+ col_keys.data (),
1989+ col_values.data (),
1990+ col_keys.size ());
1991+ cols.emplace_back (column);
1992+ }
1993+
1994+ args.GetReturnValue ().Set (Array::New (isolate, cols.data (), cols.size ()));
1995+ }
1996+
19211997void StatementSync::SourceSQLGetter (const FunctionCallbackInfo<Value>& args) {
19221998 StatementSync* stmt;
19231999 ASSIGN_OR_RETURN_UNWRAP (&stmt, args.This ());
@@ -2040,6 +2116,8 @@ Local<FunctionTemplate> StatementSync::GetConstructorTemplate(
20402116 SetProtoMethod (isolate, tmpl, " all" , StatementSync::All);
20412117 SetProtoMethod (isolate, tmpl, " get" , StatementSync::Get);
20422118 SetProtoMethod (isolate, tmpl, " run" , StatementSync::Run);
2119+ SetProtoMethodNoSideEffect (
2120+ isolate, tmpl, " columns" , StatementSync::Columns);
20432121 SetSideEffectFreeGetter (isolate,
20442122 tmpl,
20452123 FIXED_ONE_BYTE_STRING (isolate, " sourceSQL" ),
0 commit comments