@@ -448,194 +448,124 @@ exqlite_prepare(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
448448}
449449
450450static ERL_NIF_TERM
451- bind (ErlNifEnv * env , const ERL_NIF_TERM arg , sqlite3_stmt * statement , int index )
451+ raise_badarg (ErlNifEnv * env , ERL_NIF_TERM term )
452452{
453- int rc ;
454- int the_int ;
455- ErlNifSInt64 the_long_int ;
456- double the_double ;
457- char the_atom [MAX_ATOM_LENGTH + 1 ];
458- ErlNifBinary the_blob ;
459- int arity ;
460- const ERL_NIF_TERM * tuple ;
461-
462- if (enif_get_int64 (env , arg , & the_long_int )) {
463- rc = sqlite3_bind_int64 (statement , index , the_long_int );
464- if (rc == SQLITE_OK ) {
465- return make_atom (env , "ok" );
466- }
467-
468- return enif_raise_exception (
469- env ,
470- make_bind_error (
471- env ,
472- make_message (env , "Failed to bind argument as 64 bit integer" ),
473- arg ));
474- }
453+ ERL_NIF_TERM badarg = enif_make_tuple2 (env , make_atom (env , "badarg" ), term );
454+ return enif_raise_exception (env , badarg );
455+ }
475456
476- if (enif_get_int (env , arg , & the_int )) {
477- rc = sqlite3_bind_int (statement , index , the_int );
478- if (rc == SQLITE_OK ) {
479- return make_atom (env , "ok" );
480- }
457+ static ERL_NIF_TERM
458+ exqlite_reset (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
459+ {
460+ statement_t * statement ;
461+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
462+ return raise_badarg (env , argv [0 ]);
481463
482- return enif_raise_exception (
483- env ,
484- make_bind_error (
485- env ,
486- make_message (env , "Failed to bind argument as integer" ),
487- arg ));
488- }
464+ sqlite3_reset (statement -> statement );
465+ return make_atom (env , "ok" );
466+ }
489467
490- if (enif_get_double (env , arg , & the_double )) {
491- rc = sqlite3_bind_double (statement , index , the_double );
492- if (rc == SQLITE_OK ) {
493- return make_atom (env , "ok" );
494- }
468+ static ERL_NIF_TERM
469+ exqlite_bind_parameter_count (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
470+ {
495471
496- return enif_raise_exception (
497- env ,
498- make_bind_error (
499- env ,
500- make_message (env , "Failed to bind argument as double" ),
501- arg ));
502- }
472+ statement_t * statement ;
473+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
474+ return raise_badarg (env , argv [0 ]);
503475
504- if (enif_get_atom (env , arg , the_atom , sizeof (the_atom ), ERL_NIF_LATIN1 )) {
505- if (0 == strcmp ("undefined" , the_atom ) || 0 == strcmp ("nil" , the_atom )) {
506- rc = sqlite3_bind_null (statement , index );
507- if (rc == SQLITE_OK ) {
508- return make_atom (env , "ok" );
509- }
476+ int bind_parameter_count = sqlite3_bind_parameter_count (statement -> statement );
477+ return enif_make_int (env , bind_parameter_count );
478+ }
510479
511- return enif_raise_exception (
512- env ,
513- make_bind_error (
514- env ,
515- make_message (env , "Failed to bind argument as null" ),
516- arg ));
517- }
480+ static ERL_NIF_TERM
481+ exqlite_bind_text (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
482+ {
483+ statement_t * statement ;
484+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
485+ return raise_badarg (env , argv [0 ]);
518486
519- rc = sqlite3_bind_text (statement , index , the_atom , strlen (the_atom ), SQLITE_TRANSIENT );
520- if (rc == SQLITE_OK ) {
521- return make_atom (env , "ok" );
522- }
487+ unsigned int idx ;
488+ if (!enif_get_uint (env , argv [1 ], & idx ))
489+ return raise_badarg (env , argv [1 ]);
523490
524- return enif_raise_exception (
525- env ,
526- make_bind_error (
527- env ,
528- make_message (env , "Failed to bind argument as text" ),
529- arg ));
530- }
491+ ErlNifBinary text ;
492+ if (!enif_inspect_binary (env , argv [2 ], & text ))
493+ return raise_badarg (env , argv [2 ]);
531494
532- if (enif_inspect_iolist_as_binary (env , arg , & the_blob )) {
533- rc = sqlite3_bind_text (statement , index , (char * )the_blob .data , the_blob .size , SQLITE_TRANSIENT );
534- if (rc == SQLITE_OK ) {
535- return make_atom (env , "ok" );
536- }
495+ int rc = sqlite3_bind_text (statement -> statement , idx , (char * )text .data , text .size , SQLITE_TRANSIENT );
496+ return enif_make_int (env , rc );
497+ }
537498
538- return enif_raise_exception (
539- env ,
540- make_bind_error (
541- env ,
542- make_message (env , "Failed to bind argument as text" ),
543- arg ));
544- }
499+ static ERL_NIF_TERM
500+ exqlite_bind_blob (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
501+ {
502+ statement_t * statement ;
503+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
504+ return raise_badarg (env , argv [0 ]);
545505
546- if (enif_get_tuple (env , arg , & arity , & tuple )) {
547- if (arity != 2 ) {
548- return enif_raise_exception (
549- env ,
550- make_bind_error (
551- env ,
552- make_message (env , "Failed to bind argument as blob" ),
553- arg ));
554- }
506+ unsigned int idx ;
507+ if (!enif_get_uint (env , argv [1 ], & idx ))
508+ return raise_badarg (env , argv [1 ]);
555509
556- if (enif_get_atom (env , tuple [0 ], the_atom , sizeof (the_atom ), ERL_NIF_LATIN1 )) {
557- if (0 == strcmp ("blob" , the_atom )) {
558- if (enif_inspect_iolist_as_binary (env , tuple [1 ], & the_blob )) {
559- rc = sqlite3_bind_blob (statement , index , the_blob .data , the_blob .size , SQLITE_TRANSIENT );
560- if (rc == SQLITE_OK ) {
561- return make_atom (env , "ok" );
562- }
563-
564- return enif_raise_exception (
565- env ,
566- make_bind_error (
567- env ,
568- make_message (env , "Failed to bind argument as blob" ),
569- arg ));
570- }
571- }
572- }
573- }
510+ ErlNifBinary blob ;
511+ if (!enif_inspect_binary (env , argv [2 ], & blob ))
512+ return raise_badarg (env , argv [2 ]);
574513
575- return enif_raise_exception (
576- env ,
577- make_bind_error (
578- env ,
579- make_message (env , "Failed to bind argument" ),
580- arg ));
514+ int rc = sqlite3_bind_blob (statement -> statement , idx , (char * )blob .data , blob .size , SQLITE_TRANSIENT );
515+ return enif_make_int (env , rc );
581516}
582517
583- ///
584- /// @brief Binds arguments to the sql statement
585- ///
586518static ERL_NIF_TERM
587- exqlite_bind (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
519+ exqlite_bind_integer (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
588520{
589- assert (env );
521+ statement_t * statement ;
522+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
523+ return raise_badarg (env , argv [0 ]);
590524
591- unsigned int parameter_count = 0 ;
592- unsigned int argument_list_length = 0 ;
593- connection_t * conn = NULL ;
594- statement_t * statement = NULL ;
595- ERL_NIF_TERM list ;
596- ERL_NIF_TERM head ;
597- ERL_NIF_TERM tail ;
525+ unsigned int idx ;
526+ if (!enif_get_uint (env , argv [1 ], & idx ))
527+ return raise_badarg (env , argv [1 ]);
598528
599- if (argc != 3 ) {
600- return enif_make_badarg (env );
601- }
602-
603- if (!enif_get_resource (env , argv [0 ], connection_type , (void * * )& conn )) {
604- return make_error_tuple (env , "invalid_connection" );
605- }
606-
607- if (!enif_get_resource (env , argv [1 ], statement_type , (void * * )& statement )) {
608- return make_error_tuple (env , "invalid_statement" );
609- }
529+ ErlNifSInt64 i ;
530+ if (!enif_get_int64 (env , argv [2 ], & i ))
531+ return raise_badarg (env , argv [2 ]);
610532
611- if (! enif_get_list_length ( env , argv [ 2 ], & argument_list_length )) {
612- return make_error_tuple (env , "bad_argument_list" );
613- }
533+ int rc = sqlite3_bind_int64 ( statement -> statement , idx , i );
534+ return enif_make_int (env , rc );
535+ }
614536
615- parameter_count = (unsigned int )sqlite3_bind_parameter_count (statement -> statement );
616- if (parameter_count != argument_list_length ) {
617- return make_error_tuple (env , "arguments_wrong_length" );
618- }
537+ static ERL_NIF_TERM
538+ exqlite_bind_float (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
539+ {
540+ statement_t * statement ;
541+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
542+ return raise_badarg (env , argv [0 ]);
619543
620- sqlite3_reset (statement -> statement );
544+ unsigned int idx ;
545+ if (!enif_get_uint (env , argv [1 ], & idx ))
546+ return raise_badarg (env , argv [1 ]);
621547
622- list = argv [2 ];
623- for (unsigned int i = 0 ; i < argument_list_length ; i ++ ) {
624- enif_get_list_cell (env , list , & head , & tail );
625- ERL_NIF_TERM result = bind (env , head , statement -> statement , i + 1 );
548+ double f ;
549+ if (!enif_get_double (env , argv [2 ], & f ))
550+ return raise_badarg (env , argv [2 ]);
626551
627- // We are going to ignore this, we have to pass it.
628- ERL_NIF_TERM reason ;
552+ int rc = sqlite3_bind_double (statement -> statement , idx , f );
553+ return enif_make_int (env , rc );
554+ }
629555
630- // Bind will set an exception if anything happens during that phase.
631- if (enif_has_pending_exception (env , & reason )) {
632- return make_error_tuple (env , "failed_to_bind_argument" );
633- }
556+ static ERL_NIF_TERM
557+ exqlite_bind_null (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
558+ {
559+ statement_t * statement ;
560+ if (!enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement ))
561+ return raise_badarg (env , argv [0 ]);
634562
635- list = tail ;
636- }
563+ unsigned int idx ;
564+ if (!enif_get_uint (env , argv [1 ], & idx ))
565+ return raise_badarg (env , argv [1 ]);
637566
638- return make_atom (env , "ok" );
567+ int rc = sqlite3_bind_null (statement -> statement , idx );
568+ return enif_make_int (env , rc );
639569}
640570
641571static ERL_NIF_TERM
@@ -1272,6 +1202,38 @@ exqlite_interrupt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
12721202 return make_atom (env , "ok" );
12731203}
12741204
1205+ static ERL_NIF_TERM
1206+ exqlite_errmsg (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
1207+ {
1208+ connection_t * conn ;
1209+ statement_t * statement ;
1210+ const char * msg ;
1211+
1212+ if (enif_get_resource (env , argv [0 ], connection_type , (void * * )& conn )) {
1213+ msg = sqlite3_errmsg (conn -> db );
1214+ } else if (enif_get_resource (env , argv [0 ], statement_type , (void * * )& statement )) {
1215+ msg = sqlite3_errmsg (sqlite3_db_handle (statement -> statement ));
1216+ } else {
1217+ return raise_badarg (env , argv [0 ]);
1218+ }
1219+
1220+ if (!msg )
1221+ return make_atom (env , "nil" );
1222+
1223+ return make_binary (env , msg , strlen (msg ));
1224+ }
1225+
1226+ static ERL_NIF_TERM
1227+ exqlite_errstr (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
1228+ {
1229+ int rc ;
1230+ if (!enif_get_int (env , argv [0 ], & rc ))
1231+ return raise_badarg (env , argv [0 ]);
1232+
1233+ const char * msg = sqlite3_errstr (rc );
1234+ return make_binary (env , msg , strlen (msg ));
1235+ }
1236+
12751237//
12761238// Most of our nif functions are going to be IO bounded
12771239//
@@ -1282,7 +1244,13 @@ static ErlNifFunc nif_funcs[] = {
12821244 {"execute" , 2 , exqlite_execute , ERL_NIF_DIRTY_JOB_IO_BOUND },
12831245 {"changes" , 1 , exqlite_changes , ERL_NIF_DIRTY_JOB_IO_BOUND },
12841246 {"prepare" , 2 , exqlite_prepare , ERL_NIF_DIRTY_JOB_IO_BOUND },
1285- {"bind" , 3 , exqlite_bind , ERL_NIF_DIRTY_JOB_IO_BOUND },
1247+ {"reset" , 1 , exqlite_reset , ERL_NIF_DIRTY_JOB_CPU_BOUND },
1248+ {"bind_parameter_count" , 1 , exqlite_bind_parameter_count },
1249+ {"bind_text" , 3 , exqlite_bind_text },
1250+ {"bind_blob" , 3 , exqlite_bind_blob },
1251+ {"bind_integer" , 3 , exqlite_bind_integer },
1252+ {"bind_float" , 3 , exqlite_bind_float },
1253+ {"bind_null" , 2 , exqlite_bind_null },
12861254 {"step" , 2 , exqlite_step , ERL_NIF_DIRTY_JOB_IO_BOUND },
12871255 {"multi_step" , 3 , exqlite_multi_step , ERL_NIF_DIRTY_JOB_IO_BOUND },
12881256 {"columns" , 2 , exqlite_columns , ERL_NIF_DIRTY_JOB_IO_BOUND },
@@ -1295,6 +1263,8 @@ static ErlNifFunc nif_funcs[] = {
12951263 {"set_update_hook" , 2 , exqlite_set_update_hook , ERL_NIF_DIRTY_JOB_IO_BOUND },
12961264 {"set_log_hook" , 1 , exqlite_set_log_hook , ERL_NIF_DIRTY_JOB_IO_BOUND },
12971265 {"interrupt" , 1 , exqlite_interrupt , ERL_NIF_DIRTY_JOB_IO_BOUND },
1266+ {"errmsg" , 1 , exqlite_errmsg },
1267+ {"errstr" , 1 , exqlite_errstr },
12981268};
12991269
13001270ERL_NIF_INIT (Elixir .Exqlite .Sqlite3NIF , nif_funcs , on_load , NULL , NULL , on_unload )
0 commit comments