Author Topic: GNOME-DB  (Read 19317 times)

JRS

  • Guest
GNOME-DB
« on: December 06, 2010, 09:06:17 PM »
I was introduced to the GNOME-DB project when I added database access to the GNOME Planner. (project manger software) It's what ODBC is to Windows. I had asked Peter if he thought I could use his GTK-Server interpretive CALL interface with GNOME-DB. His response was NO because ScriptBasic couldn't pass a pointer to it's variables. Armando added a VARPTR() function to the gtk-server.so ScriptBasic extension module which is used with the SQLite3 demo post in the iCALL thread. I would like to initiate a ScriptBasic, BaCon and BCX code challenge to show the following C example running under each of the Basic offerings. This will give the users of each Basic a common interface to MySQL, SQLite and PostgreSQL (with support for data binding to Gtk widgets.)

GObject Introspection (GNOME script engine plug-in interface)
Quote
It makes sense to build many kinds of applications using (at least) two different levels and languages. Those being C+GObject, and a managed (GC'd) runtime. C is good for graphics, multimedia, and lower level systems work. However, writing complex software is difficult and error-prone without garbage collection. A managed runtime such as Vala, JavaScript, Python, Java, Lua, .NET, Scheme etc. makes a lot of sense for non-fast-path application logic such as configuration, layout, dialogs, etc.


 

Code: [Select]
#include <libgda.h>
#include <libgda-ui/libgda-ui.h>

int
main (int argc, char *argv[])
{
        gtk_init (&argc, &argv);
        gdaui_init ();

        /* create a login dialog window to let the user select a data source (or declare a new one)
         * and specify a username and password if necessary
         */
        GtkWidget *window, *login;
        window = gtk_dialog_new_with_buttons ("Select the Data Source to connect to",
                                              NULL,
                                              0,
                                              GTK_STOCK_CANCEL,
                                              GTK_RESPONSE_NONE,
                                              GTK_STOCK_OK,
                                              GTK_RESPONSE_OK,
                                              NULL);

        /* Create the login widget */
        login = gdaui_login_new (NULL);
        gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (window))),
                            login, TRUE, TRUE, 0);
        gtk_widget_show (login);

        if (gtk_dialog_run (GTK_DIALOG (window)) != GTK_RESPONSE_OK) {
                g_print ("Cancelled!\n");
                exit (0);
        }

        /* open the connection */
        const GdaDsnInfo *dsninfo;
        GdaConnection *cnc;
        GError *error;

        dsninfo = gdaui_login_get_connection_information (GDAUI_LOGIN (login));
        cnc = gda_connection_open_from_string (dsninfo->provider,
                                               dsninfo->cnc_string,
                                               dsninfo->auth_string,
                                               GDA_CONNECTION_OPTIONS_NONE, &error);

        gtk_widget_destroy (window);

        if (!cnc) {
                g_print ("Could not open connection: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
        }

        /* execute a SELECT statement; here the easiest API is used */
        GdaDataModel *data_model;
        data_model = gda_execute_select_command (cnc, "SELECT * FROM customers", &error);
        if (!data_model) {
                g_print ("Could not execute the SQL command: %s\n",
                         error && error->message ? error->message : "No detail");
                /* close the connection */
                g_object_unref (cnc);
                exit (1);
        }
        
        /* Create a main window and show the data model in a grid */
        GtkWidget *grid;
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
        grid = gdaui_grid_new (data_model);
        /*g_object_set (G_OBJECT (grid), "info-flags",
          GDAUI_DATA_PROXY_INFO_CURRENT_ROW | GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS, NULL);*/
        g_object_unref (data_model);
        gtk_container_add (GTK_CONTAINER (window), grid);
        gtk_widget_show_all (window);

        gtk_main();

        g_object_unref (cnc);

        return 0;
}

cc -Wall -o sample sample.c `pkg-config --cflags --libs libgda-ui-4.0`

GTK Script? (back to the future)
« Last Edit: December 07, 2010, 12:50:33 AM by JRS »

JRS

  • Guest
Re: GNOME-DB
« Reply #1 on: December 07, 2010, 02:33:38 AM »
To get the ball rolling I thought I would post my almost completed definitions before starting on the actual meat of the program.

Code: [Select]
' GNOME-DB GRID

' INTERFACE
DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

' GTK2
DLL("gtk_server_require libgtk-x11-2.0.so")
DLL("gtk_server_require libgdk-x11-2.0.so")
DLL("gtk_server_require libglib-2.0.so")
DLL("gtk_server_require libgobject-2.0.so")
DLL("gtk_server_require libatk-1.0.so")
DLL("gtk_server_require libpango-1.0.so")
DLL("gtk_server_require libgdk_pixbuf_xlib-2.0.so")

' GDA4
DLL("gtk_server_require libgda-4.0.so")
DLL("gtk_server_require libgda-ui-4.0.so")

' DECLARE
DLL("gtk_server_define gtk_init NONE NONE 2 NULL NULL")
' gtk_dialog_new_with_buttons
' gdaui_login_new
DLL("gtk_server_define gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")
' gtk_dialog_get_content_area
DLL("gtk_server_define gtk_widget_show NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_dialog_run NONE INT 1 WIDGET")
' gdaui_login_get_connection_information
' gda_connection_open_from_string
DLL("gtk_server_define gtk_widget_destroy NONE NONE 1 WIDGET")
' gda_execute_select_command
DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_window_new delete-event WIDGET 1 INT")
' gdaui_grid_new
DLL("gtk_server_define gtk_container_add NONE NONE 2 WIDGET WIDGET")
DLL("gtk_server_define gtk_widget_show_all NONE NONE 1 WIDGET")

Quote from: THIN AIR
hint: Get crackin', Son!!!

Escape from .hell with GTK-Server direct API interface.
« Last Edit: December 07, 2010, 03:41:23 AM by JRS »

AIR

  • Guest
Re: GNOME-DB
« Reply #2 on: December 07, 2010, 10:47:31 AM »
Quote from: JRS
Escape from .hell with GTK-Server direct API interface.

Pfffft!


Code: [Select]
$execon "-Os sample.c $(pkg-config --libs --cflags libgda-ui-4.0)"
$exestrip
$nomain

It doesn't get any simpler!  ;D

This demonstrates how MBC/UBX/ConsoleBC/LinuxBC can leverage already debugged C code, and use it without having to go through the pain of a complete re-write. :P

Found a C function on the net you could use, but don't want to convert to BCX syntax?  Then don't, just use it as-is either between $ccode tags or like I did above.

BTW, I added the following to the sample.c source file so that the window (not the dialog) shows AND exits properly:
Code: [Select]
        //~ ADDED BY AIR
        //~ ****************************************************************************
        g_object_set(G_OBJECT(window),"width-request",400,"height-request",200,NULL);
        g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
        //~ ****************************************************************************

JRS

  • Guest
Re: GNOME-DB
« Reply #3 on: December 07, 2010, 12:02:46 PM »
Thanks for your BCX code challenge submission. Doesn't get much easier then that.  ;D

JRS

  • Guest
Re: GNOME-DB
« Reply #4 on: December 07, 2010, 01:29:37 PM »
Here is another GDA example that might be more of a challenge.

Code: [Select]
#include <libgda/libgda.h>
#include <libgda/sql-parser/gda-sql-parser.h>

GdaConnection *open_connection (void);
void display_products_contents (GdaConnection *cnc);
void create_table (GdaConnection *cnc);
void insert_data (GdaConnection *cnc);
void update_data (GdaConnection *cnc);
void delete_data (GdaConnection *cnc);

void run_sql_non_select (GdaConnection *cnc, const gchar *sql);

int
main (int argc, char *argv[])
{
        gda_init ();

        GdaConnection *cnc;

/* open connections */
cnc = open_connection ();
create_table (cnc);

insert_data (cnc);
display_products_contents (cnc);

update_data (cnc);
display_products_contents (cnc);

delete_data (cnc);
display_products_contents (cnc);

        gda_connection_close (cnc);

        return 0;
}

/*
 * Open a connection to the example.db file
 */
GdaConnection *
open_connection ()
{
        GdaConnection *cnc;
        GError *error = NULL;
GdaSqlParser *parser;

/* open connection */
        cnc = gda_connection_open_from_string ("SQLite", "DB_DIR=.;DB_NAME=example_db", NULL,
       GDA_CONNECTION_OPTIONS_NONE,
       &error);
        if (!cnc) {
                g_print ("Could not open connection to SQLite database in example_db.db file: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
        }

/* create an SQL parser */
parser = gda_connection_create_parser (cnc);
if (!parser) /* @cnc doe snot provide its own parser => use default one */
parser = gda_sql_parser_new ();
/* attach the parser object to the connection */
g_object_set_data_full (G_OBJECT (cnc), "parser", parser, g_object_unref);

        return cnc;
}

/*
 * Create a "products" table
 */
void
create_table (GdaConnection *cnc)
{
run_sql_non_select (cnc, "DROP table IF EXISTS products");
        run_sql_non_select (cnc, "CREATE table products (ref string not null primary key, "
                            "name string not null, price real)");
}

/*
 * Insert some data
 *
 * Even though it is possible to use SQL text which includes the values to insert into the
 * table, it's better to use variables (place holders), or as is done here, convenience functions
 * to avoid SQL injection problems.
 */
void
insert_data (GdaConnection *cnc)
{
typedef struct {
gchar *ref;
gchar *name;

gboolean price_is_null;
gfloat price;
} RowData;
RowData data [] = {
{"p1", "chair", FALSE, 2.0},
{"p2", "table", FALSE, 5.0},
{"p3", "glass", FALSE, 1.1},
{"p1000", "???", TRUE, 0.},
{"p1001", "???", TRUE, 0.},
};
gint i;

gboolean res;
GError *error = NULL;
GValue *v1, *v2, *v3;

for (i = 0; i < sizeof (data) / sizeof (RowData); i++) {
v1 = gda_value_new_from_string (data[i].ref, G_TYPE_STRING);
v2 = gda_value_new_from_string (data[i].name, G_TYPE_STRING);
if (data[i].price_is_null)
v3 = NULL;
else {
v3 = gda_value_new (G_TYPE_FLOAT);
g_value_set_float (v3, data[i].price);
}

res = gda_insert_row_into_table (cnc, "products", &error, "ref", v1, "name", v2, "price", v3, NULL);

if (!res) {
g_error ("Could not INSERT data into the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v1);
gda_value_free (v2);
if (v3)
gda_value_free (v3);
}
}

/*
 * Update some data
 */
void
update_data (GdaConnection *cnc)
{
gboolean res;
GError *error = NULL;
GValue *v1, *v2, *v3;

/* update data where ref is 'p1000' */
v1 = gda_value_new_from_string ("p1000", G_TYPE_STRING);
v2 = gda_value_new_from_string ("flowers", G_TYPE_STRING);
v3 = gda_value_new (G_TYPE_FLOAT);
g_value_set_float (v3, 1.99);

res = gda_update_row_in_table (cnc, "products", "ref", v1, &error, "name", v2, "price", v3, NULL);

if (!res) {
g_error ("Could not UPDATE data in the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v1);
gda_value_free (v2);
gda_value_free (v3);
}

/*
 * Delete some data
 */
void
delete_data (GdaConnection *cnc)
{
gboolean res;
GError *error = NULL;
GValue *v;

/* delete data where name is 'table' */
v = gda_value_new_from_string ("table", G_TYPE_STRING);
res = gda_delete_row_from_table (cnc, "products", "name", v, &error);
if (!res) {
g_error ("Could not DELETE data from the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v);

/* delete data where price is NULL */
res = gda_delete_row_from_table (cnc, "products", "price", NULL, &error);
if (!res) {
g_error ("Could not DELETE data from the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
}

/*
 * display the contents of the 'products' table
 */
void
display_products_contents (GdaConnection *cnc)
{
GdaDataModel *data_model;
GdaSqlParser *parser;
GdaStatement *stmt;
gchar *sql = "SELECT ref, name, price FROM products";
GError *error = NULL;

parser = g_object_get_data (G_OBJECT (cnc), "parser");
stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
data_model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
g_object_unref (stmt);
        if (!data_model)
                g_error ("Could not get the contents of the 'products' table: %s\n",
                         error && error->message ? error->message : "No detail");
gda_data_model_dump (data_model, stdout);
g_object_unref (data_model);
}

/*
 * run a non SELECT command and stops if an error occurs
 */
void
run_sql_non_select (GdaConnection *cnc, const gchar *sql)
{
        GdaStatement *stmt;
        GError *error = NULL;
        gint nrows;
const gchar *remain;
GdaSqlParser *parser;

parser = g_object_get_data (G_OBJECT (cnc), "parser");
stmt = gda_sql_parser_parse_string (parser, sql, &remain, &error);
if (remain)
g_print ("REMAINS: %s\n", remain);

        nrows = gda_connection_statement_execute_non_select (cnc, stmt, NULL, NULL, &error);
        if (nrows == -1)
                g_error ("NON SELECT error: %s\n", error && error->message ? error->message : "no detail");
g_object_unref (stmt);
}

AIR

  • Guest
Re: GNOME-DB
« Reply #5 on: December 07, 2010, 04:03:31 PM »
It you want to be able to run this, in MBC change (will be updated in next release):
Code: [Select]
  IF NOT Use_Wx OR NOT Use_WxC and Use_Keypress THEN
    FPRINT FP3,"#include <term.h>"
  END IF

to
Code: [Select]
  IF Use_Keypress THEN
    FPRINT FP3,"#include <term.h>"
  END IF

demo2.bas
Code: [Select]
$execon "$(pkg-config --libs --cflags libgda-4.0)"
$exestrip
$nomain

#include "sample2.c"


function main (argc as integer, argv as PCHAR PTR)
  gda_init()

  raw cnc as GdaConnection ptr

'/* open connections */
cnc = open_connection()
create_table(cnc)

insert_data(cnc)
display_products_contents(cnc)

update_data(cnc)
display_products_contents(cnc)

delete_data(cnc)
display_products_contents(cnc)

  gda_connection_close(cnc)
   
end function

sample2.c
Code: [Select]
#include <libgda/libgda.h>
#include <libgda/sql-parser/gda-sql-parser.h>

GdaConnection *open_connection (void);
void display_products_contents (GdaConnection *cnc);
void create_table (GdaConnection *cnc);
void insert_data (GdaConnection *cnc);
void update_data (GdaConnection *cnc);
void delete_data (GdaConnection *cnc);

void run_sql_non_select (GdaConnection *cnc, const gchar *sql);


/*
 * Open a connection to the example.db file
 */
GdaConnection *
open_connection ()
{
        GdaConnection *cnc;
        GError *error = NULL;
GdaSqlParser *parser;

/* open connection */
        cnc = gda_connection_open_from_string ("SQLite", "DB_DIR=.;DB_NAME=example_db", NULL,
       GDA_CONNECTION_OPTIONS_NONE,
       &error);
        if (!cnc) {
                g_print ("Could not open connection to SQLite database in example_db.db file: %s\n",
                         error && error->message ? error->message : "No detail");
                exit (1);
        }

/* create an SQL parser */
parser = gda_connection_create_parser (cnc);
if (!parser) /* @cnc doe snot provide its own parser => use default one */
parser = gda_sql_parser_new ();
/* attach the parser object to the connection */
g_object_set_data_full (G_OBJECT (cnc), "parser", parser, g_object_unref);

        return cnc;
}

/*
 * Create a "products" table
 */
void
create_table (GdaConnection *cnc)
{
run_sql_non_select (cnc, "DROP table IF EXISTS products");
        run_sql_non_select (cnc, "CREATE table products (ref string not null primary key, "
                            "name string not null, price real)");
}

/*
 * Insert some data
 *
 * Even though it is possible to use SQL text which includes the values to insert into the
 * table, it's better to use variables (place holders), or as is done here, convenience functions
 * to avoid SQL injection problems.
 */
void
insert_data (GdaConnection *cnc)
{
typedef struct {
gchar *ref;
gchar *name;

gboolean price_is_null;
gfloat price;
} RowData;
RowData data [] = {
{"p1", "chair", FALSE, 2.0},
{"p2", "table", FALSE, 5.0},
{"p3", "glass", FALSE, 1.1},
{"p1000", "???", TRUE, 0.},
{"p1001", "???", TRUE, 0.},
};
gint i;

gboolean res;
GError *error = NULL;
GValue *v1, *v2, *v3;

for (i = 0; i < sizeof (data) / sizeof (RowData); i++) {
v1 = gda_value_new_from_string (data[i].ref, G_TYPE_STRING);
v2 = gda_value_new_from_string (data[i].name, G_TYPE_STRING);
if (data[i].price_is_null)
v3 = NULL;
else {
v3 = gda_value_new (G_TYPE_FLOAT);
g_value_set_float (v3, data[i].price);
}

res = gda_insert_row_into_table (cnc, "products", &error, "ref", v1, "name", v2, "price", v3, NULL);

if (!res) {
g_error ("Could not INSERT data into the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v1);
gda_value_free (v2);
if (v3)
gda_value_free (v3);
}
}

/*
 * Update some data
 */
void
update_data (GdaConnection *cnc)
{
gboolean res;
GError *error = NULL;
GValue *v1, *v2, *v3;

/* update data where ref is 'p1000' */
v1 = gda_value_new_from_string ("p1000", G_TYPE_STRING);
v2 = gda_value_new_from_string ("flowers", G_TYPE_STRING);
v3 = gda_value_new (G_TYPE_FLOAT);
g_value_set_float (v3, 1.99);

res = gda_update_row_in_table (cnc, "products", "ref", v1, &error, "name", v2, "price", v3, NULL);

if (!res) {
g_error ("Could not UPDATE data in the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v1);
gda_value_free (v2);
gda_value_free (v3);
}

/*
 * Delete some data
 */
void
delete_data (GdaConnection *cnc)
{
gboolean res;
GError *error = NULL;
GValue *v;

/* delete data where name is 'table' */
v = gda_value_new_from_string ("table", G_TYPE_STRING);
res = gda_delete_row_from_table (cnc, "products", "name", v, &error);
if (!res) {
g_error ("Could not DELETE data from the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
gda_value_free (v);

/* delete data where price is NULL */
res = gda_delete_row_from_table (cnc, "products", "price", NULL, &error);
if (!res) {
g_error ("Could not DELETE data from the 'products' table: %s\n",
error && error->message ? error->message : "No detail");
}
}

/*
 * display the contents of the 'products' table
 */
void
display_products_contents (GdaConnection *cnc)
{
GdaDataModel *data_model;
GdaSqlParser *parser;
GdaStatement *stmt;
gchar *sql = "SELECT ref, name, price FROM products";
GError *error = NULL;

parser = (GdaSqlParser*)g_object_get_data (G_OBJECT (cnc), "parser");
stmt = gda_sql_parser_parse_string (parser, sql, NULL, NULL);
data_model = gda_connection_statement_execute_select (cnc, stmt, NULL, &error);
g_object_unref (stmt);
        if (!data_model)
                g_error ("Could not get the contents of the 'products' table: %s\n",
                         error && error->message ? error->message : "No detail");
gda_data_model_dump (data_model, stdout);
g_object_unref (data_model);
}

/*
 * run a non SELECT command and stops if an error occurs
 */
void
run_sql_non_select (GdaConnection *cnc, const gchar *sql)
{
        GdaStatement *stmt;
        GError *error = NULL;
        gint nrows;
const gchar *remain;
GdaSqlParser *parser;

parser = (GdaSqlParser*)g_object_get_data (G_OBJECT (cnc), "parser");
stmt = gda_sql_parser_parse_string (parser, sql, &remain, &error);
if (remain)
g_print ("REMAINS: %s\n", remain);

        nrows = gda_connection_statement_execute_non_select (cnc, stmt, NULL, NULL, &error);
        if (nrows == -1)
                g_error ("NON SELECT error: %s\n", error && error->message ? error->message : "no detail");
g_object_unref (stmt);
}

OUTPUT
Code: [Select]
ref   │ name  │ price   
──────┼───────┼─────────
p1    │ chair │ 2.000000
p2    │ table │ 5.000000
p3    │ glass │ 1.100000
p1000 │ ???   │ NULL   
p1001 │ ???   │ NULL   
(5 rows)
ref   │ name    │ price   
──────┼─────────┼─────────
p1    │ chair   │ 2.000000
p2    │ table   │ 5.000000
p3    │ glass   │ 1.100000
p1000 │ flowers │ 1.990000
p1001 │ ???     │ NULL   
(5 rows)
ref   │ name    │ price   
──────┼─────────┼─────────
p1    │ chair   │ 2.000000
p3    │ glass   │ 1.100000
p1000 │ flowers │ 1.990000
(3 rows)

Yes, you can "#include" a .c file.... ;D

MBC (and it's brethren) allow you to use as much or as little of pre-existing C code as you want.  A real time saver, if you ask me!


A.

JRS

  • Guest
Re: GNOME-DB
« Reply #6 on: December 07, 2010, 05:14:17 PM »
This is the kind of stuff I had hoped would fall off the shelf doing these code challenges. The problem with many of these cool open source projects is that no one is promoting the project and the advantages they bring to the table. Thanks again Armando! You and folks like you is the reason Basic continues to prosper.

« Last Edit: December 07, 2010, 05:54:36 PM by JRS »

JRS

  • Guest
Re: GNOME-DB
« Reply #7 on: December 07, 2010, 08:03:16 PM »
Quote from: JRS
Escape from .hell with GTK-Server direct API interface.

Pfffft!


I guess that idea never made it off the runway.  :(

JRS

  • Guest
Re: GNOME-DB
« Reply #8 on: December 08, 2010, 10:43:02 AM »
I haven't given up on the first code challenge and got side tracked with planning for my next challenge. (Rlib)

I should be testing my code today and hope to post something this evening. (real life tasks getting in the way again  ;) )

« Last Edit: December 08, 2010, 02:02:23 PM by JRS »

JRS

  • Guest
Re: GNOME-DB
« Reply #9 on: December 08, 2010, 10:15:50 PM »
Quote
MBC (and it's brethren) allow you to use as much or as little of pre-existing C code as you want.  A real time saver, if you ask me!

While I agree that it's convenient to plug-in tested C code in your BCX Basic programs with an #include, I haven't learned anything about the API or the resources it provides. I'm finding it enjoyable and informative to be able to script interfaces with simple definitions and see how they work interactively.  


AIR

  • Guest
Re: GNOME-DB
« Reply #10 on: December 09, 2010, 09:24:57 AM »
If you study the C code, you will learn..... ;D  You're going to need to, if you want to be able to enhance scriptbasic directly going forward.

After dealing with having to translate C headers to Basic back when I was using Hotbasic, I'm personally not interested in going back.  I didn't start to understand C until I actually started using it (all I learned from header translation is that a long in C is a long in Hotbasic, and other similar stuff).

JRS

  • Guest
Re: GNOME-DB
« Reply #11 on: December 09, 2010, 10:13:21 AM »
Quote
all I learned from header translation is that a long in C is a long in Hotbasic, and other similar stuff

I can tell you in just a few minutes after looking at the API if it worth my time interfacing with it. C isn't too far off from Basic so I'm not totally in the woods. It's the casting and indirection references that become confusing at times. With enough patients and willingness to dig, C isn't that scary to an old Basic programmer like me.

I should be more clear with my intentions of using GTK-Server with SB. Most Basic programmers would rather code in Basic rather then worry if their code will translate correctly to C. I think PowerBASIC has made a good living believing in this concept. SB is a scripting language (acts like and interpreter and compiler as well) If I can extend the language with scripted interfaces to the OS and it's shared libraries without having to code in C, all the better. The advantage I see is I can define only the functions I need for my script and ignore everything else. If I see that the interface I scripted is useful to a broader audience, I will consider creating a SB extension module in C, wrapping the complexity and presenting it to SB programmers in a seamless extension to the language. I think the MYSQL/PSQL/ODBC common function access methods to each DB is the way to go. I will add the SQLite3 interface using the same functions in SB and populate associative arrays with the FetchHash() function from the statements returned from sqlite3_step().

BASIC is all about maximizing functionally with as little code and complexity as possible. My goal at the SB level is to require only the minimal information needed and do the real work  under the covers. (extension modules and API scripting)

« Last Edit: December 09, 2010, 01:51:56 PM by JRS »

JRS

  • Guest
Re: GNOME-DB
« Reply #12 on: December 09, 2010, 07:27:32 PM »
Code: [Select]
$execon "-Os sample.c $(pkg-config --libs --cflags libgda-ui-4.0)"
$exestrip
$nomain

If the above is all you need to know to run this code challenge then no need to read any further.

I'm not there yet but pretty close I think. I have a couple issues I thought I would poll the forum and see if one of the Gtk experts can help me through this. Not sure why my stock buttons aren't showing the images. I'm happy to see that I got as far as communicating with GDA with the login. I picked this example for a couple reasons. (1) Peter said it couldn't be done in SB. (2) This was a stress test for SB and GTK-Server to see if I could script a complex interface. (DB, data aware widgets, ...) Your comments and help are appreciated.



Code: [Select]
' GNOME-DB GRID

' INTERFACE
DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

' GTK2  (may not be needed under Linux)
DLL("gtk_server_require libgtk-x11-2.0.so")
DLL("gtk_server_require libgdk-x11-2.0.so")
DLL("gtk_server_require libglib-2.0.so")
DLL("gtk_server_require libgobject-2.0.so")
DLL("gtk_server_require libatk-1.0.so")
DLL("gtk_server_require libpango-1.0.so")
DLL("gtk_server_require libgdk_pixbuf_xlib-2.0.so")

' GDA4
DLL("gtk_server_require libgda-4.0.so")
DLL("gtk_server_require libgda-ui-4.0.so")

' DECLARE
DLL("gtk_server_define gtk_init NONE NONE 2 NULL NULL")
DLL("gtk_server_define gtk_dialog_new_with_buttons NONE WIDGET 8 STRING NULL NULL STRING STRING STRING STRING NULL")
DLL("gtk_server_define gdaui_login_new NONE WIDGET 1 STRING")
DLL("gtk_server_define gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")
DLL("gtk_server_define gtk_dialog_get_content_area NONE WIDGET 1 WIDGET")
DLL("gtk_server_define gtk_widget_show NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_dialog_run NONE INT 1 WIDGET")
DLL("gtk_server_define gdaui_login_get_connection_information NONE PTR_WIDGET 1 WIDGET")
DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 5 STRING STRING STRING INT PTR_LONG")
DLL("gtk_server_define gtk_widget_destroy NONE NONE 1 WIDGET")
DLL("gtk_server_define gda_execute_select_command NONE WIDGET 3 WIDGET STRING PTR_LONG")
DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_window_new delete-event WIDGET 1 INT")
DLL("gtk_server_define gdaui_grid_new NONE WIDGET 1 WIDGET")
DLL("gtk_server_define gtk_container_add NONE NONE 2 WIDGET WIDGET")
DLL("gtk_server_define gtk_widget_show_all NONE NONE 1 WIDGET")

CONST GTK_STOCK_CANCEL = "gtk-cancel"
CONST GTK_STOCK_OK = "gtk-ok"
CONST GTK_RESPONSE_NONE = -1
CONST GTK_RESPONSE_OK = -5
CONST GDA_CONNECTION_OPTIONS_NONE = 0
CONST GTK_WINDOW_TOPLEVEL = 0

' MAIN

DLL("gtk_init 0 0")
DLL("gdaui_init")

window = DLL("gtk_dialog_new_with_buttons \"Select the Data Source to connect to\" NULL 0 GTK_STOCK_CANCEL GTK_RESPONSE_NONE GTK_STOCK_OK GTK_RESPONSE_OK NULL")

login = DLL("gdaui_login_new NULL")
DLL("gtk_box_pack_start " & DLL("gtk_dialog_get_content_area " & window) & " " &  login & " TRUE TRUE 0")
DLL("gtk_widget_show " & login)

IF DLL("gtk_dialog_run " & window) <> GTK_RESPONSE_OK THEN
  PRINT "Cancelled!\n"
  END
END IF

dsninfo = DLL("gdaui_login_get_connection_information " & login)

cnc = DLL("gda_connection_open_from_string " & dsninfo_provider & " " & dsninfo_cnc_string & " " & dsninfo_auth_string & " " & GDA_CONNECTION_OPTIONS_NONE & " " & VARPTR(gdaerr))
SPLIT result BY " " TO ok,gdamsg

DLL("gtk_widget_destroy" & window)

IF NOT(cnc) THEN
  PRINT "Could not open connection: \n",gdamsg,"\n"
  END
END IF

data_model = DLL("gda_execute_select_command " & cnc & " SELECT * FROM customers " & VARPTR(gdaerr))
SPLIT result BY " " TO ok,gdamsg

IF NOT(data_model) THEN
  PRINT "Could not execute the SQL command: \n",gdamsg,"\n"
  DLL("g_object_unref " & cnc)
  END
END IF

window = DLL("gtk_window_new GTK_WINDOW_TOPLEVEL")
grid = DLL("gdaui_grid_new " & data_model)

DLL("g_object_unref " & data_model)
DLL("gtk_container_add " & window & " " & grid)
DLL("gtk_widget_show_all " & window)

' EVENT

' gtk_main();


' END

DLL("g_object_unref " & cnc)

Console Output

jrs@Laptop:~/SB/test$ scriba gda.sb
Trying to load plugins in /usr/local/lib/libgda-4.0/plugins...
Loading file /usr/local/lib/libgda-4.0/plugins/libgda-ui-plugins.so...
  - loaded filesel (File selection entry): Entry
  - loaded cird (Entry to hold an IPv4 network specification): Entry
  - loaded text (Multiline text entry): Entry
  - loaded picture (Picture entry): Entry Cell
  - loaded picture_as_string (Picture entry for data stored as a string): Entry Cell
Cancelled!  After clicking OK
jrs@Laptop:~/SB/test$

JRS

  • Guest
Re: GNOME-DB
« Reply #13 on: December 09, 2010, 08:00:04 PM »
I found out that I didn't need to require the GTK2 section of libraries under Linux. (must only be needed under Windows)

Code: [Select]
' GNOME-DB GRID

' INTERFACE
DECLARE SUB DLL ALIAS "_gtk" LIB "gtk-server"
DECLARE SUB VARPTR ALIAS "varptr" LIB "gtk-server"

' GDA4
DLL("gtk_server_require libgda-4.0.so")
DLL("gtk_server_require libgda-ui-4.0.so")

' DECLARE
DLL("gtk_server_define gtk_init NONE NONE 2 NULL NULL")
DLL("gtk_server_define gtk_dialog_new_with_buttons NONE WIDGET 8 STRING NULL NULL STRING STRING STRING STRING NULL")
DLL("gtk_server_define gdaui_login_new NONE WIDGET 1 STRING")
DLL("gtk_server_define gtk_box_pack_start NONE NONE 5 WIDGET WIDGET BOOL BOOL INT")
DLL("gtk_server_define gtk_dialog_get_content_area NONE WIDGET 1 WIDGET")
DLL("gtk_server_define gtk_widget_show NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_dialog_run NONE INT 1 WIDGET")
DLL("gtk_server_define gdaui_login_get_connection_information NONE PTR_WIDGET 1 WIDGET")
DLL("gtk_server_define gda_connection_open_from_string NONE WIDGET 5 STRING STRING STRING INT PTR_LONG")
DLL("gtk_server_define gtk_widget_destroy NONE NONE 1 WIDGET")
DLL("gtk_server_define gda_execute_select_command NONE WIDGET 3 WIDGET STRING PTR_LONG")
DLL("gtk_server_define g_object_unref NONE NONE 1 WIDGET")
DLL("gtk_server_define gtk_window_new delete-event WIDGET 1 INT")
DLL("gtk_server_define gdaui_grid_new NONE WIDGET 1 WIDGET")
DLL("gtk_server_define gtk_container_add NONE NONE 2 WIDGET WIDGET")
DLL("gtk_server_define gtk_widget_show_all NONE NONE 1 WIDGET")

CONST GTK_STOCK_CANCEL = "gtk-cancel"
CONST GTK_STOCK_OK = "gtk-ok"
CONST GTK_RESPONSE_NONE = -1
CONST GTK_RESPONSE_OK = -5
CONST GDA_CONNECTION_OPTIONS_NONE = 0
CONST GTK_WINDOW_TOPLEVEL = 0

' MAIN

And a couple more visuals. (clicking on the Data Sources... button)




AIR

  • Guest
Re: GNOME-DB
« Reply #14 on: December 09, 2010, 08:04:49 PM »
Quote
If the above is all you need to know to run this code challenge then no need to read any further.

Fine, I'll let you figure it out then....