[DEVELOPMENT ENVIRONMENT]

* NEW: The structure of databases is now stored in the *.connection files.
  It will be used for an automatic database initialization feature.

[WEBSITE MAKER]
* NEW: Update for 3.6.2.

[WIKI CGI SCRIPT]
* BUG: Fix the display of page without headers.
* NEW: Indexes are now displayed on two or more columns.

[INTERPRETER]
* NEW: New GB.AllocZero() API for allocating memory and filling it with 
  zeros.

[GB.DB.MYSQL]
* OPT: Cache metadata queries during 30 secondes to speed up things.

[GB.FORM]
* NEW: MenuButton displays a focus rectangle now.

[GB.GUI.BASE]
* BUG: ProgressBar now raises native control events.


git-svn-id: svn://localhost/gambas/trunk@6652 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Benoît Minisini 2014-11-16 21:40:47 +00:00
parent cda2eda390
commit dd41b47ef3
17 changed files with 649 additions and 497 deletions

View file

@ -14,7 +14,7 @@ Sub InitVar()
'DIM aDev AS String[] = ["92", "91", "90", "51"]
$cVar["OLD_VERSION"] = "2.24.0"
$cVar["DEV_VERSION"] = "3.6.1"
$cVar["DEV_VERSION"] = "3.6.2"
InitAuthor

View file

@ -41,10 +41,10 @@
<div align="center"><img id="logo" src="logo.png"/></div>
<div>
<a class="download-orange" target="_blank" href="http://sourceforge.net/projects/gambas/files/gambas3/gambas3-3.6.1.tar.bz2/download">
{Download}&nbsp;<b>Gambas&nbsp;3.6.1</b>
<a class="download-orange" target="_blank" href="http://sourceforge.net/projects/gambas/files/gambas3/gambas3-3.6.2.tar.bz2/download">
{Download}&nbsp;<b>Gambas&nbsp;3.6.2</b>
</a>
<div class="release-notes" align="center"><a href="http://gambaswiki.org/wiki/doc/release/3.6.1?w&amp;l=$(LANG)">{Release Notes}</a></div>
<div class="release-notes" align="center"><a href="http://gambaswiki.org/wiki/doc/release/3.6.2?w&amp;l=$(LANG)">{Release Notes}</a></div>
</div>
<div style="display:inline-table;">

View file

@ -158,7 +158,6 @@ TABLE.example TH {
}*/
.header {
background: white; /*#DFC1A7; /*#CF6706;*/
left: 0;
top: 0;
width: 100%;
@ -166,17 +165,6 @@ TABLE.example TH {
z-index: 10;
}
.header-v {
background: white;
/*padding: 2px 0px;*/
left: 0;
top: 0;
width: 100%;
position: fixed;
z-index: 10;
height: 1.2em;
}
.header-inside {
max-width: 800px;
margin: 0 auto;
@ -184,6 +172,17 @@ TABLE.example TH {
border-bottom-left-radius: 32px;
border-bottom-right-radius: 32px;
padding: 2px 16px 4px;
box-shadow: 0 0 8px gray;
}
.header-inside-v {
max-width: 800px;
margin: 0 auto;
background: #E8E8E8;
border-bottom-left-radius: 32px;
border-bottom-right-radius: 32px;
padding: 2px 16px 4px;
box-shadow: 0 0 8px gray;
}
.header-bar {
@ -204,11 +203,6 @@ TABLE.example TH {
color: gray;
}
.label-login {
display: inline-block;
margin-left: 0.5em;
}
.page {
padding: 4px 8px;
max-width: 800px;
@ -364,7 +358,7 @@ TABLE.index TD {
DIV.index {
display: inline-block;
font-size: 85%;
padding: 8px 32px 8px 0;
padding: 0;
margin-top: 0.75em;
}
@ -470,19 +464,25 @@ DIV.syntax > P:first-child {
position: static;
background: white; /*#DFC1A7;*/
color: gray;
border: #D8D8D8 solid 8px;
border: #DF6B00 solid 8px;
border-radius: 32px;
padding: 16px;
box-shadow: 0 0 8px #D8D8D8;
box-shadow: 0 0 8px gray;
width: 20em;
margin: 16px;
}
.label-login {
display: inline-block;
margin-left: 0.5em;
width: 8em;
height: 1.5em;
}
#user {
width: 12em;
}
#ok {
margin-top: 8px;
width: 8em;
@ -503,8 +503,7 @@ DIV.syntax > P:first-child {
.login {
position: fixed;
top: 32px;
right: 32px;
z-index: 100;
left: 32px;
margin: 0px;
}
.hide-if-compact {

View file

@ -21,14 +21,13 @@ TABLE.table>TBODY>TR>TH,TABLE.error>TBODY>TR>TH{border-top:solid #D8D8D8 1px;bor
TABLE.desc{border:solid #D8D8D8 2px;border-collapse:collapse;padding:0px;margin-top:0.75em;border-spacing:0;empty-cells:show;}
TABLE.desc>TBODY>TR>TD{border:none;padding:6px 12px;}
TABLE.desc>TBODY>TR>TH{text-align:left;border:none;padding:6px 12px;}
.header{background:white;left:0;top:0;width:100%;position:fixed;z-index:10;}
.header-v{background:white;left:0;top:0;width:100%;position:fixed;z-index:10;height:1.2em;}
.header-inside{max-width:800px;margin:0 auto;background:#E8E8E8;border-bottom-left-radius:32px;border-bottom-right-radius:32px;padding:2px 16px 4px;}
.header{left:0;top:0;width:100%;position:fixed;z-index:10;}
.header-inside{max-width:800px;margin:0 auto;background:#E8E8E8;border-bottom-left-radius:32px;border-bottom-right-radius:32px;padding:2px 16px 4px;box-shadow:0 0 8px gray;}
.header-inside-v{max-width:800px;margin:0 auto;background:#E8E8E8;border-bottom-left-radius:32px;border-bottom-right-radius:32px;padding:2px 16px 4px;box-shadow:0 0 8px gray;}
.header-bar{}
.title{display:inline-block;color:gray;}
.title A:hover{color:black;}
.title-v{font-size:75%;color:gray;}
.label-login{display:inline-block;margin-left:0.5em;}
.page{padding:4px 8px;max-width:800px;margin:0 auto;position:relative;top:2.5em;}
.page-edit{position:absolute;top:2.5em;bottom:0;left:0;right:0;}
.unknown{color:red;margin-top:8px;}
@ -50,7 +49,7 @@ DIV.example,DIV.seealso{display:inline-block;border:none;padding:0px;}
TEXTAREA{font-family:monospace;}
TABLE.index{border:none;padding:0px;margin-top:0.75em;}
TABLE.index TD{border:none;padding:1px 6px;vertical-align:baseline;}
DIV.index{display:inline-block;font-size:85%;padding:8px 32px 8px 0;margin-top:0.75em;}
DIV.index{display:inline-block;font-size:85%;padding:0;margin-top:0.75em;}
DIV.syntax{display:inline-block;border:solid #D8D8D8 2px;padding:4px 8px;font-family:monospace;white-space:pre-wrap;}
DIV.syntax>P:last-child{margin-bottom:-0.75em;}
DIV.since{display:inline-block;background:#FF8080;color:white;font-weight:bold;border:solid 1px red;padding:1px 6px;text-transform:uppercase;font-size:80%;}
@ -68,13 +67,14 @@ P:first-child,UL:first-child,OL:first-child,TABLE:first-child{margin-top:0;}
H1:first-child{margin-top:0;}
DIV.table:first-child{margin-top:0;}
DIV.syntax>P:first-child{margin-top:-0.75em;}
.login{position:static;background:white;color:gray;border:#D8D8D8 solid 8px;border-radius:32px;padding:16px;box-shadow:0 0 8px #D8D8D8;width:20em;margin:16px;}
.label-login{width:8em;height:1.5em;}
.login{position:static;background:white;color:gray;border:#DF6B00 solid 8px;border-radius:32px;padding:16px;box-shadow:0 0 8px gray;width:20em;margin:16px;}
.label-login{display:inline-block;margin-left:0.5em;width:8em;height:1.5em;}
#user{width:12em;}
#ok{margin-top:8px;width:8em;}
#register{width:8em;}
.hide-if-compact{display:none;}
.show-if-compact{display:inherit;}
@media(min-width:120em){.login{position:fixed;top:32px;right:32px;z-index:100;margin:0px;}
@media(min-width:120em){.login{position:fixed;top:32px;left:32px;margin:0px;}
.hide-if-compact{display:inherit;}
.show-if-compact{display:none;}
}

View file

@ -29,20 +29,22 @@ H1 { display: none; }
<%If Not Request.Exist("nh") Then%>
<div class="header-v">
<div class="header-inside">
<table border="0" cellpadding="0" cellspacing="0" style="position:fixed;">
<tr valign="top"><td><a href="<%_PrintParent()%>"><img src="<%/%>/up-gray.png" style="vertical-align:top;"></a>&nbsp;</td>
<td><div class="title-v"><%_PrintLink%></div></td></tr>
</table>
<div class="header">
<div class="header-inside-v">
<div class="header-bar">
<table border="0" cellpadding="0" cellspacing="0">
<tr valign="top"><td><a href="<%_PrintParent()%>"><img src="<%/%>/up-gray.png" style="vertical-align:top;"></a>&nbsp;</td>
<td><div class="title-v"><%_PrintLink%></div></td></tr>
</table>
</div>
</div>
</div>
<div class="page" style="padding-top:4px;top:1.2em;">
<div class="page" style="top:1.5em;">
<%Else%>
<div class="page" style="padding-top:4px;top:0;">
<div class="page" style="top:0;">
<%Endif%>
@ -159,12 +161,12 @@ H1 { display: none; }
<div align="center">
<div class="login"><div>
<%If Session.Id Then%>
<div class="label-login" align="left"><%= Main.UserName%></div>
<div id="user" class="label-login" align="left"><%= Main.UserName%></div>
<div class="command"><input type="submit" name="logout" value="<%= ("Logout")%>"></div>
<%Else%>
<div class="label-login" align="left"><%= ("Login")%>&nbsp;</div>
<div class="label-login" align="left"><%=("Login")%>&nbsp;</div>
<input type="text" name="login" id="login" maxlength="16">
<div class="label-login" align="left"><%= ("Password")%>&nbsp;</div>
<div class="label-login" align="left"><%=("Password")%>&nbsp;</div>
<input type="password" name="password" id="password" maxlength="16">
<div class="command"><input type="submit" id="ok" value="OK"></div>
<div class="command"><input type="submit" id="register" name="register" value="<%= ("Register")%>"></div>

View file

@ -62,7 +62,6 @@ Public Sub Command(sCommand As String) As String[]
Dim aArg As String[]
Dim sDir As String
Dim aResult As String[]
Dim I As Integer
Dim iPos As Integer
Dim sPath As String
Dim sLetter, sLast As String
@ -72,6 +71,8 @@ Public Sub Command(sCommand As String) As String[]
Dim hSym As CSymbolInfo
Dim sTitle As String
Dim sClass As String
Dim iStart As Integer
Dim I, J, K, N, NC As Integer
aArg = Split(sCommand, " ", Chr$(34))
sCommand = aArg[0]
@ -84,6 +85,13 @@ Public Sub Command(sCommand As String) As String[]
aResult = New String[]
aDir = New String[]
NC = 2
For I = 1 To aArg.Max
If aArg[I] Begins "col=" Then
Try NC = CInt(Mid$(aArg[I], 5))
Endif
Next
If IsDir(sDir) Then
For Each sDir In Dir(sDir, "*", gb.Directory)
@ -91,29 +99,38 @@ Public Sub Command(sCommand As String) As String[]
If Not Main.ExistPage(sPath) Then Continue
sTitle = Main.GetPageTitle(sPath)
If aArg.Count > 2 And If Comp(Left(sTitle, Len(aArg[2])), aArg[2], gb.Language + gb.IgnoreCase) = 0 Then sTitle = LTrim(Mid$(sTitle, Len(aArg[2]) + 1))
Do
sLetter = String.Left(sTitle)
If Len(sLetter) > 1 Then Break
If Not IsPunct(sLetter) Then Break
If Not sTitle Then Break
sTitle = String.Mid$(sTitle, 2)
Loop
If Not sTitle Then sTitle = " "
aDir.Add(sTitle & "\n[" & sPath & "]")
Next
If aDir.Count Then
aResult.Add("[[ index")
aResult.Add("==")
aResult.Add("<table class=\"no-border full\">")
aDir.Sort(gb.Natural + gb.IgnoreCase)
iStart = 0
For I = 0 To aDir.Max
If I Then aResult.Add("==")
iPos = InStr(aDir[I], "\n")
sLetter = String.UCase(String.Left(aDir[I]))
If sLetter <> sLast Then
aResult.Add("<div class=\"letter\">" & sLetter & "</div>")
If I Then GoSub MAKE_INDEX_LETTER
sLast = sLetter
iStart = I
Endif
aResult.Add("--")
aResult.Add(Mid$(aDir[I], iPos + 1) & "\\")
Next
GoSub MAKE_INDEX_LETTER
aResult.Add("]]")
aResult.Add("</table>")
Endif
@ -183,6 +200,31 @@ Public Sub Command(sCommand As String) As String[]
Endif
MAKE_INDEX_LETTER:
aResult.Add("<tr><td><div class=\"letter\">" & sLast & "&nbsp;</div></td>")
N = (I - iStart + NC - 1) \ NC
J = iStart
For K = 1 To NC
aResult.Add("<td width=\"" & CStr(100 \ NC) & "%\">")
For J = J To J + N - 1
If J >= I Then Break
iPos = InStr(aDir[J], "\n")
aResult.Add(Mid$(aDir[J], iPos + 1) & "\\")
Next
aResult.Add("</td>")
Next
aResult.Add("</tr>")
Return
End
Public Sub Enter(sClass As String) As String[]

View file

@ -230,6 +230,8 @@ Public Sub Reload() As Boolean
Inc Application.Busy
DB.Debug = True
$hConn.Open
$aCollations = Null
@ -291,7 +293,8 @@ Public Sub Reload() As Boolean
UpdateRequest
LoadList($sTable)
UpdateDefinition
DrawTitle
Me.Enabled = True
@ -439,6 +442,8 @@ Private Sub ReloadTable()
Dim cDescField As Collection
Dim cDescIndex As Collection
UpdateDefinition($sTable)
$aField.Clear
$cFieldName.Clear
$aIndexField.Clear
@ -1289,7 +1294,7 @@ Private Sub RemoveIndexFromTable(sTable As String)
End
Private Sub WriteTableDef(sName As String, sType As String, aPrimaryKey As String[], Optional bKill As Boolean)
Private Sub WriteTableInDatabase(sName As String, sType As String, aPrimaryKey As String[], Optional bKill As Boolean)
Dim hTable As Table
Dim hCField As CField
@ -1384,9 +1389,9 @@ Private Sub WriteTable(Optional sOldTable As String) As Boolean
sTemp = sOldTable 'MConnection.CopyTableData($hConn, sOldName)
Endif
'WriteTableDef(MConnection.GetTempTableName($hConn), $sType, aPrimaryKey, True)
'WriteTableInDatabase(MConnection.GetTempTableName($hConn), $sType, aPrimaryKey, True)
RemoveIndexFromTable(sOldTable)
WriteTableDef($sTable, $sType, aPrimaryKey)
WriteTableInDatabase($sTable, $sType, aPrimaryKey)
Else
@ -1394,8 +1399,8 @@ Private Sub WriteTable(Optional sOldTable As String) As Boolean
sTemp = MConnection.CopyTableData($hConn, $sTable)
Endif
WriteTableDef(MConnection.GetTempTableName($hConn), $sType, aPrimaryKey, True)
WriteTableDef($sTable, $sType, aPrimaryKey)
WriteTableInDatabase(MConnection.GetTempTableName($hConn), $sType, aPrimaryKey, True)
WriteTableInDatabase($sTable, $sType, aPrimaryKey)
Endif
@ -1615,6 +1620,7 @@ Public Sub btnKill_Click()
If CheckCurrent() Then Return
$hConn.Tables.Remove($sTable)
UpdateDefinition($sTable)
lvwTable.Remove("T" & $sTable)
datData.Reset
btnRequest_Click
@ -1872,21 +1878,62 @@ Public Sub btnAddQuery_Click()
End
Private Sub SaveTableDef()
Private Sub UpdateDefinition(Optional sTable As String)
Dim hConfig As Settings
Dim hSettings As Settings
Dim aDesc As String[]
Dim sDefaultValue As String
Dim hTable As Table
Dim hField As Field
Dim hIndex As Index
Dim sDesc As String
Dim aTable As String[]
For Each hTable In $hConn.Tables
hSettings = New Settings(Path, Trim(Mid$(Project.CONNECTION_MAGIC, 2)))
If Not sTable Then
hSettings.Clear("Definition")
aTable = New String[]
For Each hTable In $hConn.Tables
If hTable.System Then Continue
If hTable.Name Begins MConnection.METADATA_TABLE_PREFIX Then Continue
If sTable And If hTable.Name <> sTable Then Continue
aTable.Add(hTable.Name)
Next
Else
aTable = [sTable]
hSettings["Definition" &/ sTable] = ""
Endif
For Each sTable In aTable
If hTable.System Then Continue
If hTable.Name Begins MConnection.METADATA_TABLE_PREFIX Then Continue
hTable = $hConn.Tables[sTable]
aDesc = New String[]
aDesc.Add(hTable.Type)
aDesc.Add(hTable.PrimaryKey.Join())
For Each hField In hTable.Fields
sDefaultValue = hField.Default
If sDefaultValue Then sDefaultValue = Quote(sDefaultValue)
sDesc = hField.Name & "," & CStr(hField.Type) & "," & hField.Length
If sDefaultValue Or If hField.Collation Then
sDesc &= "," & sDefaultValue & "," & hField.Collation
Endif
aDesc.Add(sDesc)
Next
For Each hIndex In hTable.Indexes
If hIndex.Primary Then Continue
sDesc = "@" & hIndex.Name
If hIndex.Unique Then sDesc &= "!"
aDesc.Add(sDesc & "," & hIndex.Fields.Join())
Next
hSettings["Definition" &/ sTable] = aDesc.Join(";")
Next
hConfig = New Settings(Path, Trim(Mid$(Project.CONNECTION_MAGIC, 2)))
hSettings.Save
End

View file

@ -83,7 +83,7 @@ SearchString=True
[OpenFile]
Active=1
File[1]=".src/MMain.module:110.55"
File[1]=".src/MMain.module:336.45"
File[2]=".src/MServerPage.module:3.0"
File[3]=".src/CComponent.class:38.0"
File[4]="usage-gbs:12.0"

View file

@ -1,5 +1,5 @@
# Gambas Project File 3.0
# Compiled with Gambas 3.6.0
# Compiled with Gambas 3.6.90
Title=More controls for graphical components
Startup=FDocumentView
Version=3.6.90

View file

@ -370,7 +370,15 @@ Public Sub DrawingArea_Draw()
Else
Style.PaintButton(0, 0, Me.W, Me.H, $bPressed, iFlag, bFlat)
Endif
If bFlat And If Not $bPressed And If $hDrawingArea.HasFocus Then
Paint.AntiAlias = False
Paint.Rectangle(2, 2, Me.W - 4, Me.H - 4)
Paint.Background = Color.SelectedBackground
Paint.Stroke
Paint.AntiAlias = True
Endif
X = Desktop.Scale
If $hPicture Then

View file

@ -23,6 +23,7 @@ Private $hTimerPulse As Timer
Public Sub _new()
$hDrawingArea = New DrawingArea(Me) As "DrawingArea"
Me.Proxy = $hDrawingArea
End

View file

@ -27,6 +27,7 @@
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <mysql.h>
@ -48,7 +49,15 @@ static char _buffer[125];
static DB_DRIVER _driver;
/*static int _print_query = FALSE;*/
// Cached queries
#define CACHE(_db) ((GB_HASHTABLE)(_db)->data)
typedef
struct {
MYSQL_RES *res;
time_t timestamp;
}
CACHE_ENTRY;
/* internal function to quote a value stored as a string */
@ -460,8 +469,7 @@ static void check_connection(MYSQL *conn)
/* Internal function to run a query */
static int do_query(DB_DATABASE *db, const char *error, MYSQL_RES **pres,
const char *qtemp, int nsubst, ...)
static int do_query(DB_DATABASE *db, const char *error, MYSQL_RES **pres, const char *qtemp, int nsubst, ...)
{
MYSQL *conn = (MYSQL *)db->handle;
va_list args;
@ -508,6 +516,62 @@ static int do_query(DB_DATABASE *db, const char *error, MYSQL_RES **pres,
return ret;
}
static int do_query_cached(DB_DATABASE *db, const char *error, MYSQL_RES **pres, char *key, const char *qtemp, int nsubst, ...)
{
CACHE_ENTRY *entry;
int len_key;
bool added;
time_t t;
va_list args;
int i;
const char *query;
int ret;
if (nsubst)
{
va_start(args, nsubst);
if (nsubst > 3)
nsubst = 3;
for (i = 0; i < nsubst; i++)
query_param[i] = va_arg(args, char *);
query = DB.SubstString(qtemp, 0, query_get_param);
key = DB.SubstString(key, 0, query_get_param);
}
else
query = qtemp;
len_key = strlen(key);
added = GB.HashTable.Get(CACHE(db), key, len_key, POINTER(&entry));
if (added)
{
GB.AllocZero(POINTER(&entry), sizeof(CACHE_ENTRY));
GB.HashTable.Add(CACHE(db), key, len_key, entry);
}
t = time(NULL);
//fprintf(stderr, "-- do_query_cached: %s [ %p %ld ]\n", key, entry->res, entry->timestamp);
if (entry->res && (t - entry->timestamp) < 30)
{
mysql_data_seek(entry->res, 0);
*pres = entry->res;
return 0;
}
entry->timestamp = t;
if (entry->res)
mysql_free_result(entry->res);
ret = do_query(db, error, &entry->res, query, 0);
if (ret == 0)
*pres = entry->res;
return ret;
}
/* Internal function to return database version number as a XXYYZZ integer number*/
static int db_version(DB_DATABASE *db)
@ -551,6 +615,41 @@ static bool search_result(MYSQL_RES *res, const char *name, MYSQL_ROW *row)
return (i >= mysql_num_rows(res));
}
// Clear the query cache
static void free_cache(void *data)
{
GB.Free(&data);
}
static void clear_cache(DB_DATABASE *db)
{
GB.HashTable.Enum(CACHE(db), free_cache);
GB.HashTable.Free((GB_HASHTABLE *)&db->data);
}
static void remove_cache_entry(DB_DATABASE *db, char *key)
{
CACHE_ENTRY *entry;
if (GB.HashTable.Get(CACHE(db), key, -1, POINTER(&entry)))
return;
mysql_free_result(entry->res);
GB.Free(POINTER(&entry));
GB.HashTable.Remove((GB_HASHTABLE *)&db->data, key, -1);
}
static void clear_table_cache(DB_DATABASE *db, const char *table)
{
char key[strlen(table) + 5];
strcpy(key, "sts:"); strcat(key, table); remove_cache_entry(db, key);
strcpy(key, "sc:"); strcat(key, table); remove_cache_entry(db, key);
strcpy(key, "sfc:"); strcat(key, table); remove_cache_entry(db, key);
strcpy(key, "si:"); strcat(key, table); remove_cache_entry(db, key);
}
/*****************************************************************************
get_quote()
@ -660,12 +759,12 @@ static int open_database(DB_DESC *desc, DB_DATABASE *db)
return TRUE;
}
/* set dbversion */
db->handle = conn;
db->version = db_version(db);
set_character_set(db);
GB.HashTable.New(POINTER(&db->data), GB_COMP_BINARY);
/* flags: none at the moment */
return FALSE;
}
@ -685,6 +784,8 @@ static void close_database(DB_DATABASE *db)
{
MYSQL *conn = (MYSQL *)db->handle;
clear_cache(db);
if (conn)
mysql_close(conn);
}
@ -1282,8 +1383,7 @@ static int table_init(DB_DATABASE *db, const char *table, DB_INFO *info)
static int table_index(DB_DATABASE *db, const char *table, DB_INFO *info)
{
char *qindex =
"show index from `&1`";
char *qindex = "show index from `&1`";
MYSQL_RES *res;
MYSQL_ROW row;
@ -1291,7 +1391,7 @@ static int table_index(DB_DATABASE *db, const char *table, DB_INFO *info)
/* Index primaire */
if (do_query(db, "Unable to get primary index: &1", &res, qindex, 1, table))
if (do_query_cached(db, "Unable to get primary index: &1", &res, "si:&1", qindex, 1, table))
return TRUE;
for ( i = 0, n = 0; i < mysql_num_rows(res); i++ )
@ -1329,7 +1429,6 @@ static int table_index(DB_DATABASE *db, const char *table, DB_INFO *info)
}
}
mysql_free_result(res);
return FALSE;
}
@ -1367,17 +1466,11 @@ static void table_release(DB_DATABASE *db, DB_INFO *info)
static int table_exist(DB_DATABASE *db, const char *table)
{
MYSQL_RES *res;
int exist;
const char *query =
"show tables like '&1'";
if (do_query(db, "Unable to check table: &1", &res, query, 1, table))
if (do_query_cached(db, "Unable to check table: &1", &res, "st", "show tables", 0))
return FALSE;
exist = !search_result(res, table, NULL);
mysql_free_result(res);
return exist;
return !search_result(res, table, NULL);
}
@ -1401,25 +1494,21 @@ static int table_list(DB_DATABASE *db, char ***tables)
{
MYSQL_RES *res;
MYSQL_ROW row;
long i;
long rows;
int i;
int rows;
const char *query =
"show tables";
if (do_query(db, "Unable to get tables", &res, query, 0))
if (do_query_cached(db, "Unable to get tables", &res, "st", "show tables", 0))
return -1;
rows = mysql_num_rows(res);
GB.NewArray(tables, sizeof(char *), rows);
for (i = 0; i < rows; i++){
for (i = 0; i < rows; i++)
{
row = mysql_fetch_row(res);
(*tables)[i] = GB.NewZeroString(row[0]);
}
mysql_free_result(res);
return rows;
}
@ -1440,14 +1529,13 @@ static int table_list(DB_DATABASE *db, char ***tables)
static int table_primary_key(DB_DATABASE *db, const char *table, char ***primary)
{
const char *query =
"show index from `&1`";
const char *query = "show index from `&1`";
MYSQL_RES *res;
MYSQL_ROW row;
int i;
if (do_query(db, "Unable to get primary key: &1", &res, query, 1, table))
if (do_query_cached(db, "Unable to get primary key: &1", &res, "si:&1", query, 1, table))
return TRUE;
GB.NewArray(primary, sizeof(char *), 0);
@ -1459,8 +1547,6 @@ static int table_primary_key(DB_DATABASE *db, const char *table, char ***primary
*(char **)GB.Add(primary) = GB.NewZeroString(row[4]);
}
mysql_free_result(res);
return FALSE;
}
@ -1486,28 +1572,7 @@ static int database_is_system(DB_DATABASE *db, const char *name);
static int table_is_system(DB_DATABASE *db, const char *table)
{
MYSQL_RES *res;
MYSQL_ROW row;
int system;
if (do_query(db, "Unable to check database: &1", &res, "select database()", 0))
return FALSE;
if (mysql_num_rows(res) != 1 )
{
GB.Error("Unable to check database: More than one current database !?");
return FALSE;
}
/* (BM) Check that the current database is mysql */
/* (BM) All tables of 'mysql' database are system */
row = mysql_fetch_row(res);
system = database_is_system(db, row[0]);
mysql_free_result(res);
return system;
return db->flags.system;
}
@ -1528,8 +1593,7 @@ static char *table_type(DB_DATABASE *db, const char *table, const char *settype)
{
static char buffer[16];
const char *query =
"show table status like '&1'";
const char *query = "show table status like '&1'";
const char *update =
"alter table `&1` type = &2";
@ -1537,14 +1601,15 @@ static char *table_type(DB_DATABASE *db, const char *table, const char *settype)
MYSQL_RES *res;
MYSQL_ROW row;
if (settype){
if (do_query(db, "Cannot set table &1 to type &2", &res, update, 2, table, settype))
if (settype)
{
clear_table_cache(db, table);
if (do_query(db, "Cannot set table type: &1", &res, update, 2, table, settype))
return NULL;
}
if (do_query(db, "Invalid table: &1", &res, query, 1, table)){
if (do_query_cached(db, "Invalid table: &1", &res, "sts:&1", query, 1, table))
return NULL;
}
if (search_result(res, table, &row))
{
@ -1555,7 +1620,6 @@ static char *table_type(DB_DATABASE *db, const char *table, const char *settype)
if (!row[1]) return "VIEW"; // the table is a view
strcpy(buffer, row[1]);
mysql_free_result(res);
return buffer;
}
@ -1576,6 +1640,8 @@ static char *table_type(DB_DATABASE *db, const char *table, const char *settype)
static int table_delete(DB_DATABASE *db, const char *table)
{
clear_table_cache(db, table);
remove_cache_entry(db, "st");
return do_query(db, "Unable to delete table: &1", NULL, "drop table `&1`", 1, table);
}
@ -1684,7 +1750,6 @@ static int table_create(DB_DATABASE *db, const char *table, DB_FIELD *fields, ch
DB.Query.Add(" NOT NULL");
}
}
}
if (primary)
@ -1726,6 +1791,7 @@ static int table_create(DB_DATABASE *db, const char *table, DB_FIELD *fields, ch
DB.Query.Add(tabletype);
}
remove_cache_entry(db, "st");
/* printf("table_create syntax: %s\n", DB.Query.Get());*/
return do_query(db, "Cannot create table: &1", NULL, DB.Query.Get(), 0);
}
@ -1746,19 +1812,14 @@ static int table_create(DB_DATABASE *db, const char *table, DB_FIELD *fields, ch
static int field_exist(DB_DATABASE *db, const char *table, const char *field)
{
const char *query =
"show columns from `&1` like '&2'";
const char *query = "show columns from `&1`";
MYSQL_RES *res;
int exist;
if (do_query(db, "Unable to check field: &1", &res, query, 2, table, field))
if (do_query_cached(db, "Unable to check field: &1", &res, "sc:&1", query, 1, table))
return FALSE;
exist = !search_result(res, field, NULL);
mysql_free_result(res);
return exist;
return !search_result(res, field, NULL);
}
@ -1782,14 +1843,13 @@ static int field_exist(DB_DATABASE *db, const char *table, const char *field)
static int field_list(DB_DATABASE *db, const char *table, char ***fields)
{
const char *query =
"show columns from `&1`";
const char *query = "show columns from `&1`";
long i, n;
MYSQL_RES *res;
MYSQL_ROW row;
if (do_query(db, "Unable to get fields: &1", &res, query, 1, table))
if (do_query_cached(db, "Unable to get field: &1", &res, "sc:&1", query, 1, table))
return -1;
n = mysql_num_rows(res);
@ -1804,7 +1864,6 @@ static int field_list(DB_DATABASE *db, const char *table, char ***fields)
}
}
mysql_free_result(res);
return n;
}
@ -1827,7 +1886,7 @@ static int field_list(DB_DATABASE *db, const char *table, char ***fields)
static int field_info(DB_DATABASE *db, const char *table, const char *field, DB_FIELD *info)
{
const char *query = "show full columns from `&1` like '&2'";
const char *query = "show full columns from `&1`";
MYSQL_RES *res;
MYSQL_ROW row;
@ -1836,7 +1895,7 @@ static int field_info(DB_DATABASE *db, const char *table, const char *field, DB_
int type;
long len = 0;
if (do_query(db, "Unable to get field info: &1", &res, query, 2, table, field))
if (do_query_cached(db, "Unable to get field info: &1", &res, "sfc:&1", query, 1, table))
return TRUE;
if (search_result(res, field, &row))
@ -1889,7 +1948,6 @@ static int field_info(DB_DATABASE *db, const char *table, const char *field, DB_
else
info->collation = NULL;
mysql_free_result(res);
return FALSE;
}
@ -1909,14 +1967,13 @@ static int field_info(DB_DATABASE *db, const char *table, const char *field, DB_
static int index_exist(DB_DATABASE *db, const char *table, const char *index)
{
const char *query =
"show index from `&1`";
const char *query = "show index from `&1`";
MYSQL_RES *res;
MYSQL_ROW row;
int i, n;
if (do_query(db, "Unable to check index: &1", &res, query, 1, table))
if (do_query_cached(db, "Unable to check index: &1", &res, "si:&1", query, 1, table))
return FALSE;
for ( i = 0, n = 0; i < mysql_num_rows(res); i++ )
@ -1926,12 +1983,7 @@ static int index_exist(DB_DATABASE *db, const char *table, const char *index)
n++;
}
mysql_free_result(res);
if (n <= 0){
return FALSE;
}
return TRUE;
return (n > 0);
}
/*****************************************************************************
@ -1959,30 +2011,29 @@ static int index_list(DB_DATABASE *db, const char *table, char ***indexes)
MYSQL_ROW row;
long i, n, no_indexes;
if (do_query(db, "Unable to get indexes: &1", &res, query, 1, table))
if (do_query_cached(db, "Unable to get indexes: &1", &res, "si:&1", query, 1, table))
return -1;
for ( i = 0, no_indexes = 0; i < mysql_num_rows(res); i++ )
for (i = 0, no_indexes = 0; i < mysql_num_rows(res); i++ )
{
/* Count the number of 1st sequences in Seq_in_index to
give nmber of indexes. row[3] */
row = mysql_fetch_row(res);
if ( atoi(row[3]) == 1)
no_indexes++;
if (atoi(row[3]) == 1)
no_indexes++;
}
GB.NewArray(indexes, sizeof(char *), no_indexes);
mysql_data_seek(res, 0); /* move back to first record */
for ( i = 0, n = 0; i < mysql_num_rows(res); i++ )
for (i = 0, n = 0; i < mysql_num_rows(res); i++ )
{
row = mysql_fetch_row(res);
if ( atoi(row[3]) == 1 /* Start of a new index */)
if (atoi(row[3]) == 1 /* Start of a new index */)
(*indexes)[n++] = GB.NewZeroString(row[2]); /* (BM) The name is row[2], not row[4] */
}
mysql_free_result(res);
return no_indexes;
}
@ -2004,14 +2055,13 @@ static int index_list(DB_DATABASE *db, const char *table, char ***indexes)
static int index_info(DB_DATABASE *db, const char *table, const char *index, DB_INDEX *info)
{
const char *query =
"show index from `&1`";
const char *query = "show index from `&1`";
MYSQL_RES *res;
MYSQL_ROW row = 0;
int i, n;
if (do_query(db, "Unable to get index info: &1", &res, query, 2, table, index))
if (do_query_cached(db, "Unable to get index info: &1", &res, "si:&1", query, 1, table))
return TRUE;
n = mysql_num_rows(res);
@ -2049,7 +2099,6 @@ static int index_info(DB_DATABASE *db, const char *table, const char *index, DB_
i++; /* (BM) i must be incremented */
}
mysql_free_result(res);
info->fields = DB.Query.GetNew();
return FALSE;
@ -2072,9 +2121,8 @@ static int index_info(DB_DATABASE *db, const char *table, const char *index, DB_
static int index_delete(DB_DATABASE *db, const char *table, const char *index)
{
return
do_query(db, "Unable to delete index: &1", NULL,
"drop index `&1` on `&2`", 1, index, table);
clear_table_cache(db, table);
return do_query(db, "Unable to delete index: &1", NULL, "drop index `&1` on `&2`", 1, index, table);
}
/*****************************************************************************
@ -2108,6 +2156,7 @@ static int index_create(DB_DATABASE *db, const char *table, const char *index, D
DB.Query.Add(info->fields);
DB.Query.Add(" )");
clear_table_cache(db, table);
return do_query(db, "Cannot create index: &1", NULL, DB.Query.Get(), 0);
}
@ -2231,9 +2280,7 @@ static int database_delete(DB_DATABASE *db, const char *name)
return TRUE;
}
return
do_query(db, "Unable to delete database: &1", NULL,
"drop database `&1`", 1, name);
return do_query(db, "Unable to delete database: &1", NULL, "drop database `&1`", 1, name);
}
/*****************************************************************************
@ -2252,9 +2299,7 @@ static int database_delete(DB_DATABASE *db, const char *name)
static int database_create(DB_DATABASE *db, const char *name)
{
return
do_query(db, "Unable to create database: &1", NULL,
"create database `&1`", 1, name);
return do_query(db, "Unable to create database: &1", NULL, "create database `&1`", 1, name);
}
@ -2298,8 +2343,8 @@ static int user_exist(DB_DATABASE *db, const char *name)
if (do_query(db, "Unable to check user: &1@&2", &res, query, 2, _name, _host))
{
free(_name);
return FALSE;
free(_name);
return FALSE;
}
exist = mysql_num_rows(res) == 1;
@ -2494,8 +2539,7 @@ static int user_delete(DB_DATABASE *db, const char *name)
//Still need to look at the removal of privileges
// _ret = do_query(db, "Unable to delete user: &1", NULL,
// "revoke all on *.* from &1@&2", 2, _name, _host);
_ret = do_query(db, "Unable to delete user: &1", NULL,
_delete, 2, _name, _host);
_ret = do_query(db, "Unable to delete user: &1", NULL, _delete, 2, _name, _host);
free(_name);
return _ret;
}
@ -2591,9 +2635,7 @@ static int user_set_password(DB_DATABASE *db, const char *name, const char *pass
free(_name);
return
do_query(db, "Cannot change user password: &1",
NULL, DB.Query.Get(), 0);
return do_query(db, "Cannot change user password: &1", NULL, DB.Query.Get(), 0);
}

View file

@ -221,6 +221,7 @@ const void *const GAMBAS_Api[] =
(void *)GB_Eval,
(void *)GB_Alloc,
(void *)GB_AllocZero,
(void *)GB_Free,
(void *)GB_Realloc,
@ -2024,6 +2025,11 @@ void GB_Alloc(void **addr, int len)
ALLOC(addr, len);
}
void GB_AllocZero(void **addr, int len)
{
ALLOC_ZERO(addr, len);
}
void GB_Free(void **addr)
{
FREE(addr);

View file

@ -167,6 +167,7 @@ bool GB_CollectionGet(GB_COLLECTION col, const char *key, int len, GB_VARIANT *v
bool GB_CollectionEnum(GB_COLLECTION col, GB_COLLECTION_ITER *iter, GB_VARIANT *value, char **key, int *len);
void GB_Alloc(void **addr, int len);
void GB_AllocZero(void **addr, int len);
void GB_Free(void **addr);
void GB_Realloc(void **addr, int len);

File diff suppressed because it is too large Load diff

View file

@ -64,6 +64,7 @@ typedef
unsigned no_case : 1; /* table, field and index names must be converted to lower case */
unsigned schema : 1; /* If table names can be prefixed by a schema name and a dot */
unsigned no_collation : 1; /* No collation support at field level */
unsigned system : 1; /* system database */
}
flags;
struct {

View file

@ -1059,6 +1059,7 @@ typedef
GB_VALUE *(*Eval)(void *, void *);
void (*Alloc)(void **, int);
void (*AllocZero)(void **, int);
void (*Free)(void **);
void (*Realloc)(void **, int);